mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
JSON Auto correction + hyperion schema split for better readability (#452)
* revoke schema split * add "getAutoCorrectedConfig" function * revoke schema split * revoke schema split * revoke schema split * Prevent compiler error if none grabber is available * revoke schema split * add "getAutoCorrectedConfig" function * revoke schema split * remove "configMigrator" * remove "configMigrator" * Change TestConfigFile to show how the autocorrection works * revoke schema split * revoke schema split * remove "ConfigMigrator" * remove "ConfigMigrator" * remove "ConfigMigratorBase" * remove "ConfigMigratorBase" * Add QJsonUtils.h * added ability "ignore-required" It has been added the ability to correct the configuration without having to pay attention to the keyword "required" in the hyperion schema * Allow Comments in Hyperion Schema * add ability to ignore the "required" keyword in hyperion schema * add ability to ignore the "required" keyword in hyperion schema * add ability to ignore the "required" keyword in hyperion schema * //Allow Comments in Hyperion Schema * Update jsonschema.py to version 0.8.0 to support ... references in json schema * add RefResolver from jsonschema.py to resolve references in hyperion schema * remove dupe code * split the hyperion schema in separatly files For better readability * add function "resolveReferences" to resolve references in hyperion schema. * remove CURRENT_CONFIG_VERSION * remove CURRENT_CONFIG_VERSION * split the hyperion schema in separatly files For better readability * Create schema-backgroundEffect.json * Add the rest of the Hyperion schema via upload * Remove Comments in config file * Add return variable to function writeJson(). fix function resolveReferences(). edit function load() to handle QPair result from schemaChecker. * edit function validate() to return QPair variable * fit function loadEffectDefinition() * fit function checkJson() * Expand error check by dividing "_error" variable in "_error" and "_schemaError". Replace variable "bool" in validate() in QPair * Extend function "cmd_cfg_set" to handle auto correction * Extend function "loadConfig" to handle auto correction * fix function loadConfig()
This commit is contained in:
parent
622a171808
commit
5bd020a570
@ -14,7 +14,6 @@ SET ( HYPERION_VERSION_STABLE OFF )
|
|||||||
SET ( HYPERION_VERSION_MAJOR 2 )
|
SET ( HYPERION_VERSION_MAJOR 2 )
|
||||||
SET ( HYPERION_VERSION_MINOR 0 )
|
SET ( HYPERION_VERSION_MINOR 0 )
|
||||||
SET ( HYPERION_VERSION_PATCH 0 )
|
SET ( HYPERION_VERSION_PATCH 0 )
|
||||||
SET ( CURRENT_CONFIG_VERSION 2 )
|
|
||||||
|
|
||||||
SET ( DEFAULT_AMLOGIC OFF )
|
SET ( DEFAULT_AMLOGIC OFF )
|
||||||
SET ( DEFAULT_DISPMANX OFF )
|
SET ( DEFAULT_DISPMANX OFF )
|
||||||
@ -160,7 +159,7 @@ IF ( ${CHECK_EFFECTS_FAILED} )
|
|||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
EXECUTE_PROCESS (
|
EXECUTE_PROCESS (
|
||||||
COMMAND python test/jsonchecks/checkschema.py config/hyperion.config.json.default libsrc/hyperion/schemas/hyperion.schema-${CURRENT_CONFIG_VERSION}.json
|
COMMAND python test/jsonchecks/checkschema.py config/hyperion.config.json.default libsrc/hyperion/hyperion.schema.json
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
RESULT_VARIABLE CHECK_CONFIG_FAILED
|
RESULT_VARIABLE CHECK_CONFIG_FAILED
|
||||||
)
|
)
|
||||||
|
@ -30,9 +30,6 @@
|
|||||||
// Define to enable profiler for development purpose
|
// Define to enable profiler for development purpose
|
||||||
#cmakedefine ENABLE_PROFILER
|
#cmakedefine ENABLE_PROFILER
|
||||||
|
|
||||||
// Define version id of current config
|
|
||||||
#define CURRENT_CONFIG_VERSION ${CURRENT_CONFIG_VERSION}
|
|
||||||
|
|
||||||
// the hyperion build id string
|
// the hyperion build id string
|
||||||
#define HYPERION_BUILD_ID "${HYPERION_BUILD_ID}"
|
#define HYPERION_BUILD_ID "${HYPERION_BUILD_ID}"
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ $(document).ready( function() {
|
|||||||
var r = new FileReader();
|
var r = new FileReader();
|
||||||
r.onload = function(e)
|
r.onload = function(e)
|
||||||
{
|
{
|
||||||
var content = e.target.result;
|
var content = e.target.result.replace(/[^:]?\/\/.*/g, ''); //remove Comments
|
||||||
|
|
||||||
//check file is json
|
//check file is json
|
||||||
var check = isJsonString(content);
|
var check = isJsonString(content);
|
||||||
@ -56,7 +56,7 @@ $(document).ready( function() {
|
|||||||
if(typeof content.leds === 'undefined' || typeof content.general === 'undefined')
|
if(typeof content.leds === 'undefined' || typeof content.general === 'undefined')
|
||||||
{
|
{
|
||||||
showInfoDialog('error', "", $.i18n('infoDialog_import_hyperror_text', f.name));
|
showInfoDialog('error', "", $.i18n('infoDialog_import_hyperror_text', f.name));
|
||||||
dis_imp_btn(true);
|
dis_imp_btn(true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -25,17 +25,14 @@ public:
|
|||||||
// create the validator
|
// create the validator
|
||||||
QJsonSchemaChecker schemaChecker;
|
QJsonSchemaChecker schemaChecker;
|
||||||
schemaChecker.setSchema(schemaTree);
|
schemaChecker.setSchema(schemaTree);
|
||||||
|
|
||||||
bool valid = schemaChecker.validate(configTree);
|
|
||||||
|
|
||||||
QStringList messages = schemaChecker.getMessages();
|
QStringList messages = schemaChecker.getMessages();
|
||||||
for (int i = 0; i < messages.size(); ++i)
|
|
||||||
{
|
if (!schemaChecker.validate(configTree).first)
|
||||||
std::cout << messages[i].toStdString() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!valid)
|
|
||||||
{
|
{
|
||||||
|
for (int i = 0; i < messages.size(); ++i)
|
||||||
|
std::cout << messages[i].toStdString() << std::endl;
|
||||||
|
|
||||||
std::cerr << "Validation failed for configuration file: " << config.toStdString() << std::endl;
|
std::cerr << "Validation failed for configuration file: " << config.toStdString() << std::endl;
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
@ -54,6 +51,7 @@ public:
|
|||||||
throw std::runtime_error(QString("Configuration file not found: '" + path + "' (" + file.errorString() + ")").toStdString());
|
throw std::runtime_error(QString("Configuration file not found: '" + path + "' (" + file.errorString() + ")").toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Allow Comments in Config
|
||||||
QString config = QString(file.readAll());
|
QString config = QString(file.readAll());
|
||||||
config.remove(QRegularExpression("([^:]?\\/\\/.*)"));
|
config.remove(QRegularExpression("([^:]?\\/\\/.*)"));
|
||||||
|
|
||||||
@ -112,23 +110,62 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error(QString("ERROR: Json schema wrong: " + error.errorString() + " at Line: " + QString::number(errorLine)
|
throw std::runtime_error(QString("ERROR: Json schema wrong: " + error.errorString() +
|
||||||
+ ", Column: " + QString::number(errorColumn)).toStdString()
|
" at Line: " + QString::number(errorLine) +
|
||||||
);
|
", Column: " + QString::number(errorColumn)).toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return doc.object();
|
return resolveReferences(doc.object());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void writeJson(const QString& filename, QJsonObject& jsonTree)
|
static QJsonObject resolveReferences(const QJsonObject& schema)
|
||||||
|
{
|
||||||
|
QJsonObject result;
|
||||||
|
|
||||||
|
for (QJsonObject::const_iterator i = schema.begin(); i != schema.end(); ++i)
|
||||||
|
{
|
||||||
|
QString attribute = i.key();
|
||||||
|
const QJsonValue & attributeValue = *i;
|
||||||
|
|
||||||
|
if (attribute == "$ref" && attributeValue.isString())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
result = readSchema(":/" + attributeValue.toString());
|
||||||
|
}
|
||||||
|
catch (std::runtime_error& error)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(error.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (attributeValue.isObject())
|
||||||
|
result.insert(attribute, resolveReferences(attributeValue.toObject()));
|
||||||
|
else
|
||||||
|
result.insert(attribute, attributeValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool writeJson(const QString& filename, QJsonObject& jsonTree)
|
||||||
{
|
{
|
||||||
QJsonDocument doc;
|
QJsonDocument doc;
|
||||||
|
|
||||||
doc.setObject(jsonTree);
|
doc.setObject(jsonTree);
|
||||||
QByteArray configData = doc.toJson(QJsonDocument::Indented);
|
QByteArray configData = doc.toJson(QJsonDocument::Indented);
|
||||||
|
|
||||||
QFile configFile(filename);
|
QFile configFile(filename);
|
||||||
configFile.open(QIODevice::WriteOnly | QIODevice::Truncate);
|
if (!configFile.open(QFile::WriteOnly | QFile::Truncate))
|
||||||
|
return false;
|
||||||
|
|
||||||
configFile.write(configData);
|
configFile.write(configData);
|
||||||
|
|
||||||
|
QFile::FileError error = configFile.error();
|
||||||
|
if (error != QFile::NoError)
|
||||||
|
return false;
|
||||||
|
|
||||||
configFile.close();
|
configFile.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
#include <QPair>
|
||||||
|
|
||||||
/// JsonSchemaChecker is a very basic implementation of json schema.
|
/// JsonSchemaChecker is a very basic implementation of json schema.
|
||||||
/// The json schema definition draft can be found at
|
/// The json schema definition draft can be found at
|
||||||
@ -33,13 +34,23 @@ public:
|
|||||||
/// @return true upon succes
|
/// @return true upon succes
|
||||||
///
|
///
|
||||||
bool setSchema(const QJsonObject & schema);
|
bool setSchema(const QJsonObject & schema);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Validate a JSON structure
|
/// @brief Validate a JSON structure
|
||||||
/// @param value The JSON value to check
|
/// @param value The JSON value to check
|
||||||
/// @return true when the arguments is valid according to the schema
|
/// @param ignoreRequired Ignore the "required" keyword in hyperion schema. Default is false
|
||||||
|
/// @return The first boolean is true when the arguments is valid according to the schema. The second is true when the schema contains no errors
|
||||||
|
/// @return TODO: Check the Schema in SetSchema() function and remove the QPair result
|
||||||
///
|
///
|
||||||
bool validate(const QJsonObject & value, bool ignoreRequired = false);
|
QPair<bool, bool> validate(const QJsonObject & value, bool ignoreRequired = false);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Auto correct a JSON structure
|
||||||
|
/// @param value The JSON value to correct
|
||||||
|
/// @param ignoreRequired Ignore the "required" keyword in hyperion schema. Default is false
|
||||||
|
/// @return The corrected JSON structure
|
||||||
|
///
|
||||||
|
QJsonObject getAutoCorrectedConfig(const QJsonObject & value, bool ignoreRequired = false);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @return A list of error messages
|
/// @return A list of error messages
|
||||||
@ -72,7 +83,7 @@ private:
|
|||||||
/// @param[in] value The given value
|
/// @param[in] value The given value
|
||||||
/// @param[in] schema The specified type (as json-value)
|
/// @param[in] schema The specified type (as json-value)
|
||||||
///
|
///
|
||||||
void checkType(const QJsonValue & value, const QJsonValue & schema);
|
void checkType(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks is required properties of an json-object exist and if all properties are of the
|
/// Checks is required properties of an json-object exist and if all properties are of the
|
||||||
@ -101,7 +112,7 @@ private:
|
|||||||
/// @param[in] value The given value
|
/// @param[in] value The given value
|
||||||
/// @param[in] schema The minimum value (as json-value)
|
/// @param[in] schema The minimum value (as json-value)
|
||||||
///
|
///
|
||||||
void checkMinimum(const QJsonValue & value, const QJsonValue & schema);
|
void checkMinimum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks if the given value is smaller or equal to the specified value. If this is not the
|
/// Checks if the given value is smaller or equal to the specified value. If this is not the
|
||||||
@ -110,7 +121,7 @@ private:
|
|||||||
/// @param[in] value The given value
|
/// @param[in] value The given value
|
||||||
/// @param[in] schema The maximum value (as json-value)
|
/// @param[in] schema The maximum value (as json-value)
|
||||||
///
|
///
|
||||||
void checkMaximum(const QJsonValue & value, const QJsonValue & schema);
|
void checkMaximum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks if the given value is hugher than the specified value. If this is the
|
/// Checks if the given value is hugher than the specified value. If this is the
|
||||||
@ -119,7 +130,7 @@ private:
|
|||||||
/// @param value The given value
|
/// @param value The given value
|
||||||
/// @param schema The minimum size specification (as json-value)
|
/// @param schema The minimum size specification (as json-value)
|
||||||
///
|
///
|
||||||
void checkMinLength(const QJsonValue & value, const QJsonValue & schema);
|
void checkMinLength(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks if the given value is smaller than the specified value. If this is the
|
/// Checks if the given value is smaller than the specified value. If this is the
|
||||||
@ -128,7 +139,7 @@ private:
|
|||||||
/// @param value The given value
|
/// @param value The given value
|
||||||
/// @param schema The maximum size specification (as json-value)
|
/// @param schema The maximum size specification (as json-value)
|
||||||
///
|
///
|
||||||
void checkMaxLength(const QJsonValue & value, const QJsonValue & schema);
|
void checkMaxLength(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Validates all the items of an array.
|
/// Validates all the items of an array.
|
||||||
@ -145,7 +156,7 @@ private:
|
|||||||
/// @param value The json-array
|
/// @param value The json-array
|
||||||
/// @param schema The minimum size specification (as json-value)
|
/// @param schema The minimum size specification (as json-value)
|
||||||
///
|
///
|
||||||
void checkMinItems(const QJsonValue & value, const QJsonValue & schema);
|
void checkMinItems(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks if a given array has at most a maximum number of items. If this is not the case
|
/// Checks if a given array has at most a maximum number of items. If this is not the case
|
||||||
@ -154,7 +165,7 @@ private:
|
|||||||
/// @param value The json-array
|
/// @param value The json-array
|
||||||
/// @param schema The maximum size specification (as json-value)
|
/// @param schema The maximum size specification (as json-value)
|
||||||
///
|
///
|
||||||
void checkMaxItems(const QJsonValue & value, const QJsonValue & schema);
|
void checkMaxItems(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Checks if a given array contains only unique items. If this is not the case
|
/// Checks if a given array contains only unique items. If this is not the case
|
||||||
@ -172,17 +183,23 @@ private:
|
|||||||
/// @param value The enum value
|
/// @param value The enum value
|
||||||
/// @param schema The enum schema definition
|
/// @param schema The enum schema definition
|
||||||
///
|
///
|
||||||
void checkEnum(const QJsonValue & value, const QJsonValue & schema);
|
void checkEnum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// The schema of the entire json-configuration
|
/// The schema of the entire json-configuration
|
||||||
QJsonObject _qSchema;
|
QJsonObject _qSchema;
|
||||||
/// ignore the required value in json schema
|
/// ignore the required value in json schema
|
||||||
bool _ignoreRequired;
|
bool _ignoreRequired;
|
||||||
|
/// Auto correction variable
|
||||||
|
QString _correct;
|
||||||
|
/// The auto corrected json-configuration
|
||||||
|
QJsonObject _autoCorrected;
|
||||||
/// The current location into a json-configuration structure being checked
|
/// The current location into a json-configuration structure being checked
|
||||||
QStringList _currentPath;
|
QStringList _currentPath;
|
||||||
/// The result messages collected during the schema verification
|
/// The result messages collected during the schema verification
|
||||||
QStringList _messages;
|
QStringList _messages;
|
||||||
/// Flag indicating an error occured during validation
|
/// Flag indicating an error occured during validation
|
||||||
bool _error;
|
bool _error;
|
||||||
|
/// Flag indicating an schema error occured during validation
|
||||||
|
bool _schemaError;
|
||||||
};
|
};
|
||||||
|
273
include/utils/jsonschema/QJsonUtils.h
Normal file
273
include/utils/jsonschema/QJsonUtils.h
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
// QT include
|
||||||
|
#include <QString>
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QJsonArray>
|
||||||
|
|
||||||
|
class QJsonUtils
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static void modify(QJsonObject& value, QStringList path, const QJsonValue& newValue = QJsonValue::Null, QString propertyName = "")
|
||||||
|
{
|
||||||
|
QJsonObject result;
|
||||||
|
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
if (path.first() == "[root]")
|
||||||
|
path.removeFirst();
|
||||||
|
|
||||||
|
for (QStringList::iterator it = path.begin(); it != path.end(); ++it)
|
||||||
|
{
|
||||||
|
QString current = *it;
|
||||||
|
if (current.left(1) == ".")
|
||||||
|
*it = current.mid(1, current.size()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value.isEmpty())
|
||||||
|
modifyValue(value, result, path, newValue, propertyName);
|
||||||
|
else if (newValue != QJsonValue::Null && !propertyName.isEmpty())
|
||||||
|
result[propertyName] = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QJsonValue create(QJsonValue schema, bool ignoreRequired = false)
|
||||||
|
{
|
||||||
|
return createValue(schema, ignoreRequired);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
static QJsonValue createValue(QJsonValue schema, bool ignoreRequired)
|
||||||
|
{
|
||||||
|
QJsonObject result;
|
||||||
|
QJsonObject obj = schema.toObject();
|
||||||
|
|
||||||
|
if (obj.find("type") != obj.end() && obj.find("type").value().isString())
|
||||||
|
{
|
||||||
|
QJsonValue ret = QJsonValue::Null;
|
||||||
|
|
||||||
|
if (obj.find("type").value().toString() == "object" && ( obj.find("required").value().toBool() || ignoreRequired ) )
|
||||||
|
ret = createValue(obj["properties"], ignoreRequired);
|
||||||
|
else if (obj.find("type").value().toString() == "array" && ( obj.find("required").value().toBool() || ignoreRequired ) )
|
||||||
|
{
|
||||||
|
QJsonArray array;
|
||||||
|
|
||||||
|
if (obj.find("default") != obj.end())
|
||||||
|
ret = obj.find("default").value();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ret = createValue(obj["items"], ignoreRequired);
|
||||||
|
|
||||||
|
if (!ret.toObject().isEmpty())
|
||||||
|
array.append(ret);
|
||||||
|
ret = array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( obj.find("required").value().toBool() || ignoreRequired )
|
||||||
|
if (obj.find("default") != obj.end())
|
||||||
|
ret = obj.find("default").value();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (QJsonObject::const_iterator i = obj.begin(); i != obj.end(); ++i)
|
||||||
|
{
|
||||||
|
QString attribute = i.key();
|
||||||
|
const QJsonValue & attributeValue = *i;
|
||||||
|
QJsonValue subValue = obj[attribute];
|
||||||
|
|
||||||
|
if (attributeValue.toObject().find("type") != attributeValue.toObject().end())
|
||||||
|
{
|
||||||
|
if (attributeValue.toObject().find("type").value().toString() == "object" && ( attributeValue.toObject().find("required").value().toBool() || ignoreRequired ) )
|
||||||
|
{
|
||||||
|
if (obj.contains("properties"))
|
||||||
|
result[attribute] = createValue(obj["properties"], ignoreRequired);
|
||||||
|
else
|
||||||
|
result[attribute] = createValue(subValue, ignoreRequired);
|
||||||
|
}
|
||||||
|
else if (attributeValue.toObject().find("type").value().toString() == "array" && ( attributeValue.toObject().find("required").value().toBool() || ignoreRequired ) )
|
||||||
|
{
|
||||||
|
QJsonArray array;
|
||||||
|
|
||||||
|
if (attributeValue.toObject().find("default") != attributeValue.toObject().end())
|
||||||
|
result[attribute] = attributeValue.toObject().find("default").value();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QJsonValue retEmpty;
|
||||||
|
retEmpty = createValue(attributeValue.toObject()["items"], ignoreRequired);
|
||||||
|
|
||||||
|
if (!retEmpty.toObject().isEmpty())
|
||||||
|
array.append(retEmpty);
|
||||||
|
result[attribute] = array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( attributeValue.toObject().find("required").value().toBool() || ignoreRequired )
|
||||||
|
{
|
||||||
|
if (attributeValue.toObject().find("default") != attributeValue.toObject().end())
|
||||||
|
result[attribute] = attributeValue.toObject().find("default").value();
|
||||||
|
else
|
||||||
|
result[attribute] = QJsonValue::Null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void modifyValue(QJsonValue source, QJsonObject& target, QStringList path, const QJsonValue& newValue, QString& property)
|
||||||
|
{
|
||||||
|
QJsonObject obj = source.toObject();
|
||||||
|
|
||||||
|
if (!obj.isEmpty())
|
||||||
|
{
|
||||||
|
for (QJsonObject::iterator i = obj.begin(); i != obj.end(); ++i)
|
||||||
|
{
|
||||||
|
QString propertyName = i.key();
|
||||||
|
QJsonValue subValue = obj[propertyName];
|
||||||
|
|
||||||
|
if (subValue.isObject())
|
||||||
|
{
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
if (propertyName == path.first())
|
||||||
|
{
|
||||||
|
path.removeFirst();
|
||||||
|
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
QJsonObject obj;
|
||||||
|
modifyValue(subValue, obj, path, newValue, property);
|
||||||
|
subValue = obj;
|
||||||
|
}
|
||||||
|
else if (newValue != QJsonValue::Null)
|
||||||
|
subValue = newValue;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!subValue.toObject().isEmpty())
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (path.first() == property && newValue != QJsonValue::Null)
|
||||||
|
{
|
||||||
|
target[property] = newValue;
|
||||||
|
property = QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!subValue.toObject().isEmpty())
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
else if (subValue.isArray())
|
||||||
|
{
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
if (propertyName == path.first())
|
||||||
|
{
|
||||||
|
path.removeFirst();
|
||||||
|
|
||||||
|
int arrayLevel = -1;
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
if ((path.first().left(1) == "[") && (path.first().right(1) == "]"))
|
||||||
|
{
|
||||||
|
arrayLevel = path.first().mid(1, path.first().size()-2).toInt();
|
||||||
|
path.removeFirst();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray array = subValue.toArray();
|
||||||
|
QJsonArray json_array;
|
||||||
|
|
||||||
|
for (QJsonArray::iterator i = array.begin(); i != array.end(); ++i)
|
||||||
|
{
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
QJsonObject arr;
|
||||||
|
modifyValue(*i, arr, path, newValue, property);
|
||||||
|
subValue = arr;
|
||||||
|
}
|
||||||
|
else if (newValue != QJsonValue::Null)
|
||||||
|
subValue = newValue;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!subValue.toObject().isEmpty())
|
||||||
|
json_array.append(subValue);
|
||||||
|
else if (newValue != QJsonValue::Null && arrayLevel != -1)
|
||||||
|
json_array.append( (i - array.begin() == arrayLevel) ? subValue : *i );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_array.isEmpty())
|
||||||
|
target[propertyName] = json_array;
|
||||||
|
else if (newValue != QJsonValue::Null && arrayLevel == -1)
|
||||||
|
target[propertyName] = newValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (path.first() == property && newValue != QJsonValue::Null)
|
||||||
|
{
|
||||||
|
target[property] = newValue;
|
||||||
|
property = QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
if (!subValue.toArray().isEmpty())
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!path.isEmpty())
|
||||||
|
{
|
||||||
|
if (propertyName == path.first())
|
||||||
|
{
|
||||||
|
path.removeFirst();
|
||||||
|
|
||||||
|
if (path.isEmpty())
|
||||||
|
{
|
||||||
|
if (newValue != QJsonValue::Null && property.isEmpty())
|
||||||
|
subValue = newValue;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (path.first() == property && newValue != QJsonValue::Null)
|
||||||
|
{
|
||||||
|
target[property] = newValue;
|
||||||
|
property = QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
target[propertyName] = subValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (newValue != QJsonValue::Null && !property.isEmpty())
|
||||||
|
{
|
||||||
|
target[property] = newValue;
|
||||||
|
property = QString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
@ -150,7 +150,7 @@ bool EffectEngine::loadEffectDefinition(const QString &path, const QString &effe
|
|||||||
|
|
||||||
QJsonSchemaChecker schemaChecker;
|
QJsonSchemaChecker schemaChecker;
|
||||||
schemaChecker.setSchema(configSchema.object());
|
schemaChecker.setSchema(configSchema.object());
|
||||||
if (!schemaChecker.validate(configEffect.object()))
|
if (!schemaChecker.validate(configEffect.object()).first)
|
||||||
{
|
{
|
||||||
const QStringList & errors = schemaChecker.getMessages();
|
const QStringList & errors = schemaChecker.getMessages();
|
||||||
foreach (auto & error, errors)
|
foreach (auto & error, errors)
|
||||||
|
@ -5,9 +5,84 @@
|
|||||||
{
|
{
|
||||||
"general" :
|
"general" :
|
||||||
{
|
{
|
||||||
"type" : "object",
|
"$ref": "schema-general.json"
|
||||||
"required" : true
|
},
|
||||||
|
"logger" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-logger.json"
|
||||||
|
},
|
||||||
|
"device" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-device.json"
|
||||||
|
},
|
||||||
|
"color" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-color.json"
|
||||||
|
},
|
||||||
|
"smoothing":
|
||||||
|
{
|
||||||
|
"$ref": "schema-smoothing.json"
|
||||||
|
},
|
||||||
|
"grabberV4L2" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-grabberV4L2.json"
|
||||||
|
},
|
||||||
|
"framegrabber" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-framegrabber.json"
|
||||||
|
},
|
||||||
|
"blackborderdetector" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-blackborderdetector.json"
|
||||||
|
},
|
||||||
|
"kodiVideoChecker" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-kodiVideoChecker.json"
|
||||||
|
},
|
||||||
|
"foregroundEffect" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-foregroundEffect.json"
|
||||||
|
},
|
||||||
|
"backgroundEffect" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-backgroundEffect.json"
|
||||||
|
},
|
||||||
|
"forwarder" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-forwarder.json"
|
||||||
|
},
|
||||||
|
"jsonServer" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-jsonServer.json"
|
||||||
|
},
|
||||||
|
"protoServer" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-protoServer.json"
|
||||||
|
},
|
||||||
|
"boblightServer" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-boblightServer.json"
|
||||||
|
},
|
||||||
|
"udpListener" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-udpListener.json"
|
||||||
|
},
|
||||||
|
"webConfig" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-webConfig.json"
|
||||||
|
},
|
||||||
|
"effects" :
|
||||||
|
{
|
||||||
|
"$ref": "schema-effects.json"
|
||||||
|
},
|
||||||
|
"ledConfig":
|
||||||
|
{
|
||||||
|
"$ref": "schema-ledConfig.json"
|
||||||
|
},
|
||||||
|
"leds":
|
||||||
|
{
|
||||||
|
"$ref": "schema-leds.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties" : true
|
"additionalProperties" : false
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,26 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
<file alias="hyperion-schema">hyperion.schema.json</file>
|
<file alias="hyperion-schema">hyperion.schema.json</file>
|
||||||
<file alias="hyperion-schema-1">schemas/hyperion.schema-1.json</file>
|
<file alias="hyperion_default.config">../../config/hyperion.config.json.default</file>
|
||||||
<file alias="hyperion-schema-2">schemas/hyperion.schema-2.json</file>
|
<file alias="schema-general.json">schema/schema-general.json</file>
|
||||||
<file alias="hyperion_default.config">../../config/hyperion.config.json.default</file>
|
<file alias="schema-logger.json">schema/schema-logger.json</file>
|
||||||
</qresource>
|
<file alias="schema-device.json">schema/schema-device.json</file>
|
||||||
|
<file alias="schema-color.json">schema/schema-color.json</file>
|
||||||
|
<file alias="schema-smoothing.json">schema/schema-smoothing.json</file>
|
||||||
|
<file alias="schema-grabberV4L2.json">schema/schema-grabberV4L2.json</file>
|
||||||
|
<file alias="schema-framegrabber.json">schema/schema-framegrabber.json</file>
|
||||||
|
<file alias="schema-blackborderdetector.json">schema/schema-blackborderdetector.json</file>
|
||||||
|
<file alias="schema-kodiVideoChecker.json">schema/schema-kodiVideoChecker.json</file>
|
||||||
|
<file alias="schema-foregroundEffect.json">schema/schema-foregroundEffect.json</file>
|
||||||
|
<file alias="schema-backgroundEffect.json">schema/schema-backgroundEffect.json</file>
|
||||||
|
<file alias="schema-forwarder.json">schema/schema-forwarder.json</file>
|
||||||
|
<file alias="schema-jsonServer.json">schema/schema-jsonServer.json</file>
|
||||||
|
<file alias="schema-protoServer.json">schema/schema-protoServer.json</file>
|
||||||
|
<file alias="schema-boblightServer.json">schema/schema-boblightServer.json</file>
|
||||||
|
<file alias="schema-udpListener.json">schema/schema-udpListener.json</file>
|
||||||
|
<file alias="schema-webConfig.json">schema/schema-webConfig.json</file>
|
||||||
|
<file alias="schema-effects.json">schema/schema-effects.json</file>
|
||||||
|
<file alias="schema-ledConfig.json">schema/schema-ledConfig.json</file>
|
||||||
|
<file alias="schema-leds.json">schema/schema-leds.json</file>
|
||||||
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
48
libsrc/hyperion/schema/schema-backgroundEffect.json
Normal file
48
libsrc/hyperion/schema/schema-backgroundEffect.json
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_bge_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"type" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_fge_type_title",
|
||||||
|
"enum" : ["color", "effect"],
|
||||||
|
"default" : "effect",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_color", "edt_conf_enum_effect"]
|
||||||
|
},
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"color" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"title" : "edt_conf_fge_color_title",
|
||||||
|
"default" : [255,138,0],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"effect" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"format" : "select",
|
||||||
|
"title" : "edt_conf_fge_effect_title",
|
||||||
|
"propertyOrder" : 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
72
libsrc/hyperion/schema/schema-blackborderdetector.json
Normal file
72
libsrc/hyperion/schema/schema-blackborderdetector.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_bb_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"threshold" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_bb_threshold_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 100,
|
||||||
|
"default" : 5,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"unknownFrameCnt" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_bb_unknownFrameCnt_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 600,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"borderFrameCnt" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_bb_borderFrameCnt_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 50,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"maxInconsistentCnt" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_bb_maxInconsistentCnt_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 10,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"blurRemoveCnt" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_bb_blurRemoveCnt_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 1,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 6
|
||||||
|
},
|
||||||
|
"mode" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title": "edt_conf_bb_mode_title",
|
||||||
|
"enum" : ["default", "classic", "osd"],
|
||||||
|
"default" : "default",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_bbdefault", "edt_conf_enum_bbclassic", "edt_conf_enum_bbosd"]
|
||||||
|
},
|
||||||
|
"propertyOrder" : 7
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
33
libsrc/hyperion/schema/schema-boblightServer.json
Normal file
33
libsrc/hyperion/schema/schema-boblightServer.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_bobls_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"port" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"required" : true,
|
||||||
|
"title" : "edt_conf_general_port_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 65535,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"priority" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_general_priority_title",
|
||||||
|
"minimum" : 100,
|
||||||
|
"maximum" : 254,
|
||||||
|
"default" : 201,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
257
libsrc/hyperion/schema/schema-color.json
Normal file
257
libsrc/hyperion/schema/schema-color.json
Normal file
@ -0,0 +1,257 @@
|
|||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"title" : "edt_conf_color_heading_title",
|
||||||
|
"required" : true,
|
||||||
|
"properties":
|
||||||
|
{
|
||||||
|
"imageToLedMappingType" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"required" : true,
|
||||||
|
"title" : "edt_conf_color_imageToLedMappingType_title",
|
||||||
|
"enum" : ["multicolor_mean", "unicolor_mean"],
|
||||||
|
"default" : "multicolor_mean",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_multicolor_mean", "edt_conf_enum_unicolor_mean"]
|
||||||
|
},
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"channelAdjustment" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_channelAdjustment_header_title",
|
||||||
|
"required" : true,
|
||||||
|
"propertyOrder" : 3,
|
||||||
|
"items" :
|
||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"required" : true,
|
||||||
|
"title" : "edt_conf_color_channelAdjustment_header_itemtitle",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"id" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_color_id_title",
|
||||||
|
"required" : true,
|
||||||
|
"default" : "A userdefined name",
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"leds" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_color_leds_title",
|
||||||
|
"required" : true,
|
||||||
|
"default" : "*",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"black" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_black_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [0,0,0],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"white" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_white_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [255,255,255],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"red" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_red_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [255,0,0],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"green" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_green_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [0,255,0],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 6
|
||||||
|
},
|
||||||
|
"blue" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_blue_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [0,0,255],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 7
|
||||||
|
},
|
||||||
|
"cyan" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_cyan_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [0,255,255],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 8
|
||||||
|
},
|
||||||
|
"magenta" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_magenta_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [255,0,255],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 9
|
||||||
|
},
|
||||||
|
"yellow" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_color_yellow_title",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"required" : true,
|
||||||
|
"default": [255,255,0],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 10
|
||||||
|
},
|
||||||
|
"backlightThreshold" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_color_backlightThreshold_title",
|
||||||
|
"required" : true,
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum": 100,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 11
|
||||||
|
},
|
||||||
|
"backlightColored" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_color_backlightColored_title",
|
||||||
|
"required" : true,
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 12
|
||||||
|
},
|
||||||
|
"brightness" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_color_brightness_title",
|
||||||
|
"required" : true,
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum": 100,
|
||||||
|
"default" : 100,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 13
|
||||||
|
},
|
||||||
|
"brightnessCompensation" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_color_brightnessComp_title",
|
||||||
|
"required" : true,
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum": 100,
|
||||||
|
"default" : 90,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"access" : "advanced",
|
||||||
|
"propertyOrder" : 14
|
||||||
|
},
|
||||||
|
"gammaRed" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_color_gammaRed_title",
|
||||||
|
"required" : true,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"maximum": 100.0,
|
||||||
|
"default" : 1.5,
|
||||||
|
"step" : 0.1,
|
||||||
|
"propertyOrder" : 15
|
||||||
|
},
|
||||||
|
"gammaGreen" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_color_gammaGreen_title",
|
||||||
|
"required" : true,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"maximum": 100.0,
|
||||||
|
"default" : 1.5,
|
||||||
|
"step" : 0.1,
|
||||||
|
"propertyOrder" : 16
|
||||||
|
},
|
||||||
|
"gammaBlue" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_color_gammaBlue_title",
|
||||||
|
"required" : true,
|
||||||
|
"minimum" : 0.1,
|
||||||
|
"maximum": 100.0,
|
||||||
|
"default" : 1.5,
|
||||||
|
"step" : 0.1,
|
||||||
|
"propertyOrder" : 17
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
41
libsrc/hyperion/schema/schema-device.json
Normal file
41
libsrc/hyperion/schema/schema-device.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_dev_general_heading_title",
|
||||||
|
"required" : true,
|
||||||
|
"defaultProperties": ["ledCount","colorOrder","rewriteTime","minimumWriteTime"],
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"type" :
|
||||||
|
{
|
||||||
|
"type" : "string"
|
||||||
|
},
|
||||||
|
"ledCount" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"title" : "edt_dev_general_ledCount_title",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"colorOrder" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_dev_general_colorOrder_title",
|
||||||
|
"enum" : ["rgb", "bgr", "rbg", "brg", "gbr", "grb"],
|
||||||
|
"default" : "rgb",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_rgb", "edt_conf_enum_bgr", "edt_conf_enum_rbg", "edt_conf_enum_brg", "edt_conf_enum_gbr", "edt_conf_enum_grb"]
|
||||||
|
},
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"rewriteTime": {
|
||||||
|
"type": "integer",
|
||||||
|
"title":"edt_dev_general_rewriteTime_title",
|
||||||
|
"default": 1000,
|
||||||
|
"append" : "edt_append_ms",
|
||||||
|
"minimum": 0,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 4
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : true
|
||||||
|
}
|
29
libsrc/hyperion/schema/schema-effects.json
Normal file
29
libsrc/hyperion/schema/schema-effects.json
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_effp_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"paths" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_effp_paths_title",
|
||||||
|
"default" : ["../custom-effects"],
|
||||||
|
"items" : {
|
||||||
|
"type": "string",
|
||||||
|
"title" : "edt_conf_effp_paths_itemtitle"
|
||||||
|
},
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"disable" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_effp_disable_title",
|
||||||
|
"items" : {
|
||||||
|
"type": "string",
|
||||||
|
"title" : "edt_conf_effp_disable_itemtitle"
|
||||||
|
},
|
||||||
|
"propertyOrder" : 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
57
libsrc/hyperion/schema/schema-foregroundEffect.json
Normal file
57
libsrc/hyperion/schema/schema-foregroundEffect.json
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_fge_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"type" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_fge_type_title",
|
||||||
|
"enum" : ["color", "effect"],
|
||||||
|
"default" : "effect",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_color", "edt_conf_enum_effect"]
|
||||||
|
},
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"color" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"format" : "colorpicker",
|
||||||
|
"title" : "edt_conf_fge_color_title",
|
||||||
|
"default" : [255,0,0],
|
||||||
|
"items" : {
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 255
|
||||||
|
},
|
||||||
|
"minItems" : 3,
|
||||||
|
"maxItems" : 3,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"effect" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"format" : "select",
|
||||||
|
"title" : "edt_conf_fge_effect_title",
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"duration_ms" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_fge_duration_ms_title",
|
||||||
|
"default" : 3000,
|
||||||
|
"minimum" : 100,
|
||||||
|
"append" : "edt_append_ms",
|
||||||
|
"propertyOrder" : 5
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
36
libsrc/hyperion/schema/schema-forwarder.json
Normal file
36
libsrc/hyperion/schema/schema-forwarder.json
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_fw_heading_title",
|
||||||
|
"required" : true,
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"json" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_fw_json_title",
|
||||||
|
"required" : true,
|
||||||
|
"items" : {
|
||||||
|
"type": "string",
|
||||||
|
"title" : "edt_conf_fw_json_itemtitle"
|
||||||
|
},
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"proto" :
|
||||||
|
{
|
||||||
|
"type" : "array",
|
||||||
|
"title" : "edt_conf_fw_proto_title",
|
||||||
|
"items" : {
|
||||||
|
"type": "string",
|
||||||
|
"title" : "edt_conf_fw_proto_itemtitle"
|
||||||
|
},
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
132
libsrc/hyperion/schema/schema-framegrabber.json
Normal file
132
libsrc/hyperion/schema/schema-framegrabber.json
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_fg_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"type" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_fg_type_title",
|
||||||
|
"enum" : ["auto","dispmanx","amlogic","x11","framebuffer"],
|
||||||
|
"default" : "auto",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"width" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_fg_width_title",
|
||||||
|
"minimum" : 10,
|
||||||
|
"default" : 80,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"height" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_fg_height_title",
|
||||||
|
"minimum" : 10,
|
||||||
|
"default" : 45,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"frequency_Hz" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_fg_frequency_Hz_title",
|
||||||
|
"minimum" : 1,
|
||||||
|
"default" : 10,
|
||||||
|
"append" : "edt_append_hz",
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"priority" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_general_priority_title",
|
||||||
|
"minimum" : 100,
|
||||||
|
"maximum" : 254,
|
||||||
|
"default" : 250,
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"cropLeft" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropLeft_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 6
|
||||||
|
},
|
||||||
|
"cropRight" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropRight_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 7
|
||||||
|
},
|
||||||
|
"cropTop" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropTop_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 8
|
||||||
|
},
|
||||||
|
"cropBottom" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropBottom_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 9
|
||||||
|
},
|
||||||
|
"useXGetImage" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_fg_useXGetImage_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 10
|
||||||
|
},
|
||||||
|
"horizontalPixelDecimation" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_fg_horizontalPixelDecimation_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 8,
|
||||||
|
"propertyOrder" : 11
|
||||||
|
},
|
||||||
|
"verticalPixelDecimation" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_fg_verticalPixelDecimation_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 8,
|
||||||
|
"propertyOrder" : 12
|
||||||
|
},
|
||||||
|
"device" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_fg_device_title",
|
||||||
|
"default" : "/dev/fb0",
|
||||||
|
"propertyOrder" : 13
|
||||||
|
},
|
||||||
|
"display" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_fg_display_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"propertyOrder" : 14
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
34
libsrc/hyperion/schema/schema-general.json
Normal file
34
libsrc/hyperion/schema/schema-general.json
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_gen_heading_title",
|
||||||
|
"required" : true,
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"name" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_gen_name_title",
|
||||||
|
"default" : "My Hyperion Config",
|
||||||
|
"minLength" : 4,
|
||||||
|
"maxLength" : 20,
|
||||||
|
"required" : true,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"showOptHelp" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_gen_showOptHelp_title",
|
||||||
|
"default" : true,
|
||||||
|
"required" : true,
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"configVersion" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"default" : 2,
|
||||||
|
"minimum" : 1,
|
||||||
|
"access" : "system",
|
||||||
|
"required" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
226
libsrc/hyperion/schema/schema-grabberV4L2.json
Normal file
226
libsrc/hyperion/schema/schema-grabberV4L2.json
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
{
|
||||||
|
"type":"array",
|
||||||
|
"title" : "edt_conf_v4l2_heading_title",
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 2,
|
||||||
|
"items":
|
||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_v4l2_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"device" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_v4l2_device_title",
|
||||||
|
"default" : "auto",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"input" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_input_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"standard" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_v4l2_standard_title",
|
||||||
|
"enum" : ["PAL","NTSC"],
|
||||||
|
"default" : "PAL",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_PAL", "edt_conf_enum_NTSC"]
|
||||||
|
},
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"width" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_width_title",
|
||||||
|
"minimum" : -1,
|
||||||
|
"default" : -1,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"height" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_height_title",
|
||||||
|
"minimum" : -1,
|
||||||
|
"default" : -1,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 6
|
||||||
|
},
|
||||||
|
"frameDecimation" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_frameDecimation_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 2,
|
||||||
|
"propertyOrder" : 7
|
||||||
|
},
|
||||||
|
"sizeDecimation" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "Size decimation",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 6,
|
||||||
|
"propertyOrder" : 8
|
||||||
|
},
|
||||||
|
"priority" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 100,
|
||||||
|
"maximum" : 253,
|
||||||
|
"title" : "edt_conf_general_priority_title",
|
||||||
|
"default" : 240,
|
||||||
|
"propertyOrder" : 9
|
||||||
|
},
|
||||||
|
"mode" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_v4l2_mode_title",
|
||||||
|
"enum" : ["2D","3DSBS","3DTAB"],
|
||||||
|
"default" : "2D",
|
||||||
|
"propertyOrder" : 10
|
||||||
|
},
|
||||||
|
"useKodiChecker" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_v4l2_useKodiChecker_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 11
|
||||||
|
},
|
||||||
|
"cropLeft" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropLeft_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 12
|
||||||
|
},
|
||||||
|
"cropRight" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropRight_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 13
|
||||||
|
},
|
||||||
|
"cropTop" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropTop_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 14
|
||||||
|
},
|
||||||
|
"cropBottom" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_v4l2_cropBottom_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_pixel",
|
||||||
|
"propertyOrder" : 15
|
||||||
|
},
|
||||||
|
"signalDetection" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_v4l2_signalDetection_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 16
|
||||||
|
},
|
||||||
|
"redSignalThreshold" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_v4l2_redSignalThreshold_title",
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 1.0,
|
||||||
|
"default" : 0.1,
|
||||||
|
"step" : 0.005,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 17
|
||||||
|
},
|
||||||
|
"greenSignalThreshold" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_v4l2_greenSignalThreshold_title",
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 1.0,
|
||||||
|
"default" : 0.1,
|
||||||
|
"step" : 0.025,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 18
|
||||||
|
},
|
||||||
|
"blueSignalThreshold" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_v4l2_blueSignalThreshold_title",
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 1.0,
|
||||||
|
"default" : 0.1,
|
||||||
|
"step" : 0.005,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 19
|
||||||
|
},
|
||||||
|
"signalDetectionVerticalOffsetMin" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_v4l2_signalDetectionVerticalOffsetMin_title",
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 1.0,
|
||||||
|
"default" : 0.1,
|
||||||
|
"step" : 0.005,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 20
|
||||||
|
},
|
||||||
|
"signalDetectionVerticalOffsetMax" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_v4l2_signalDetectionVerticalOffsetMax_title",
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 1.0,
|
||||||
|
"default" : 0.1,
|
||||||
|
"step" : 0.005,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 21
|
||||||
|
},
|
||||||
|
"signalDetectionHorizontalOffsetMin" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_v4l2_signalDetectionHorizontalOffsetMin_title",
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 1.0,
|
||||||
|
"default" : 0.1,
|
||||||
|
"step" : 0.005,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 22
|
||||||
|
},
|
||||||
|
"signalDetectionHorizontalOffsetMax" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_v4l2_signalDetectionHorizontalOffsetMax_title",
|
||||||
|
"minimum" : 0.0,
|
||||||
|
"maximum" : 1.0,
|
||||||
|
"default" : 0.1,
|
||||||
|
"step" : 0.005,
|
||||||
|
"append" : "edt_append_percent",
|
||||||
|
"propertyOrder" : 23
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
||||||
|
}
|
18
libsrc/hyperion/schema/schema-jsonServer.json
Normal file
18
libsrc/hyperion/schema/schema-jsonServer.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"required" : true,
|
||||||
|
"title" : "edt_conf_js_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"port" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"required" : true,
|
||||||
|
"title" : "edt_conf_general_port_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 65535,
|
||||||
|
"default" : 19444
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
80
libsrc/hyperion/schema/schema-kodiVideoChecker.json
Normal file
80
libsrc/hyperion/schema/schema-kodiVideoChecker.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_kodic_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"kodiAddress" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_kodic_kodiAddress_title",
|
||||||
|
"default" : "127.0.0.1",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"kodiTcpPort" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_kodic_kodiTcpPort_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 65535,
|
||||||
|
"default" : 9090,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"grabVideo" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_kodic_grabVideo_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"grabPictures" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_kodic_grabPictures_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"grabAudio" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_kodic_grabAudio_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 6
|
||||||
|
},
|
||||||
|
"grabMenu" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_kodic_grabMenu_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 7
|
||||||
|
},
|
||||||
|
"grabPause" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_kodic_grabPause_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 8
|
||||||
|
},
|
||||||
|
"grabScreensaver" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_kodic_grabScreensaver_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 9
|
||||||
|
},
|
||||||
|
"enable3DDetection" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_kodic_enable3DDetection_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 10
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
80
libsrc/hyperion/schema/schema-ledConfig.json
Normal file
80
libsrc/hyperion/schema/schema-ledConfig.json
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"top" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 8
|
||||||
|
},
|
||||||
|
"bottom" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 8
|
||||||
|
},
|
||||||
|
"left" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 5
|
||||||
|
},
|
||||||
|
"right" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 5
|
||||||
|
},
|
||||||
|
"glength" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0
|
||||||
|
},
|
||||||
|
"gpos" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0
|
||||||
|
},
|
||||||
|
"position" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"default" : 0
|
||||||
|
},
|
||||||
|
"reverse" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"default" : false
|
||||||
|
},
|
||||||
|
"hdepth" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 1,
|
||||||
|
"maximum" : 100,
|
||||||
|
"default" : 8
|
||||||
|
},
|
||||||
|
"vdepth" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 1,
|
||||||
|
"maximum" : 100,
|
||||||
|
"default" : 5
|
||||||
|
},
|
||||||
|
"overlap" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"default" : 0
|
||||||
|
},
|
||||||
|
"edgegap" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 50,
|
||||||
|
"default" : 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
70
libsrc/hyperion/schema/schema-leds.json
Normal file
70
libsrc/hyperion/schema/schema-leds.json
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
{
|
||||||
|
"type":"array",
|
||||||
|
"required":true,
|
||||||
|
"items":
|
||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"properties":
|
||||||
|
{
|
||||||
|
"index":
|
||||||
|
{
|
||||||
|
"type":"integer",
|
||||||
|
"required":true
|
||||||
|
},
|
||||||
|
"clone":
|
||||||
|
{
|
||||||
|
"type":"integer"
|
||||||
|
},
|
||||||
|
"hscan":
|
||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"properties":
|
||||||
|
{
|
||||||
|
"minimum":
|
||||||
|
{
|
||||||
|
"type":"number",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 1,
|
||||||
|
"required":true
|
||||||
|
},
|
||||||
|
"maximum":
|
||||||
|
{
|
||||||
|
"type":"number",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 1,
|
||||||
|
"required":true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
},
|
||||||
|
"vscan":
|
||||||
|
{
|
||||||
|
"type":"object",
|
||||||
|
"properties":
|
||||||
|
{
|
||||||
|
"minimum":
|
||||||
|
{
|
||||||
|
"type":"number",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 1,
|
||||||
|
"required":true
|
||||||
|
},
|
||||||
|
"maximum":
|
||||||
|
{
|
||||||
|
"type":"number",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 1,
|
||||||
|
"required":true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
},
|
||||||
|
"colorOrder":
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"enum" : ["rgb", "bgr", "rbg", "brg", "gbr", "grb"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
||||||
|
}
|
18
libsrc/hyperion/schema/schema-logger.json
Normal file
18
libsrc/hyperion/schema/schema-logger.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_log_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"level" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"enum" : ["silent", "warn", "verbose", "debug"],
|
||||||
|
"title" : "edt_conf_log_level_title",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_logsilent", "edt_conf_enum_logwarn", "edt_conf_enum_logverbose", "edt_conf_enum_logdebug"]
|
||||||
|
},
|
||||||
|
"default" : "warn"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
18
libsrc/hyperion/schema/schema-protoServer.json
Normal file
18
libsrc/hyperion/schema/schema-protoServer.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"required" : true,
|
||||||
|
"title" : "edt_conf_ps_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"port" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"required" : true,
|
||||||
|
"title" : "edt_conf_general_port_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 65535,
|
||||||
|
"default" : 19445
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
63
libsrc/hyperion/schema/schema-smoothing.json
Normal file
63
libsrc/hyperion/schema/schema-smoothing.json
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_smooth_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"type" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_smooth_type_title",
|
||||||
|
"enum" : ["linear"],
|
||||||
|
"default" : "linear",
|
||||||
|
"options" : {
|
||||||
|
"enum_titles" : ["edt_conf_enum_linear"]
|
||||||
|
},
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"time_ms" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_smooth_time_ms_title",
|
||||||
|
"minimum" : 25,
|
||||||
|
"maximum": 600,
|
||||||
|
"default" : 200,
|
||||||
|
"append" : "edt_append_ms",
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"updateFrequency" :
|
||||||
|
{
|
||||||
|
"type" : "number",
|
||||||
|
"title" : "edt_conf_smooth_updateFrequency_title",
|
||||||
|
"minimum" : 1.0,
|
||||||
|
"maximum" : 100.0,
|
||||||
|
"default" : 25.0,
|
||||||
|
"append" : "edt_append_hz",
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"updateDelay" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_smooth_updateDelay_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum": 2048,
|
||||||
|
"default" : 0,
|
||||||
|
"append" : "edt_append_ms",
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"continuousOutput" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_smooth_continuousOutput_title",
|
||||||
|
"default" : true,
|
||||||
|
"propertyOrder" : 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
56
libsrc/hyperion/schema/schema-udpListener.json
Normal file
56
libsrc/hyperion/schema/schema-udpListener.json
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_udpl_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"address" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_udpl_address_title",
|
||||||
|
"default" : "239.255.28.01",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"port" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_general_port_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 65535,
|
||||||
|
"default" : 2801,
|
||||||
|
"propertyOrder" : 3
|
||||||
|
},
|
||||||
|
"priority" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_general_priority_title",
|
||||||
|
"minimum" : 100,
|
||||||
|
"maximum" : 254,
|
||||||
|
"default" : 200,
|
||||||
|
"propertyOrder" : 4
|
||||||
|
},
|
||||||
|
"timeout" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_udpl_timeout_title",
|
||||||
|
"minimum" : 1000,
|
||||||
|
"default" : 10000,
|
||||||
|
"append" : "edt_append_ms",
|
||||||
|
"propertyOrder" : 5
|
||||||
|
},
|
||||||
|
"shared" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_udpl_shared_title",
|
||||||
|
"default" : false,
|
||||||
|
"propertyOrder" : 6
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
33
libsrc/hyperion/schema/schema-webConfig.json
Normal file
33
libsrc/hyperion/schema/schema-webConfig.json
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"type" : "object",
|
||||||
|
"title" : "edt_conf_webc_heading_title",
|
||||||
|
"properties" :
|
||||||
|
{
|
||||||
|
"enable" :
|
||||||
|
{
|
||||||
|
"type" : "boolean",
|
||||||
|
"title" : "edt_conf_general_enable_title",
|
||||||
|
"default" : true,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 1
|
||||||
|
},
|
||||||
|
"document_root" :
|
||||||
|
{
|
||||||
|
"type" : "string",
|
||||||
|
"title" : "edt_conf_webc_docroot_title",
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 2
|
||||||
|
},
|
||||||
|
"port" :
|
||||||
|
{
|
||||||
|
"type" : "integer",
|
||||||
|
"title" : "edt_conf_general_port_title",
|
||||||
|
"minimum" : 0,
|
||||||
|
"maximum" : 65535,
|
||||||
|
"default" : 8099,
|
||||||
|
"access" : "expert",
|
||||||
|
"propertyOrder" : 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties" : false
|
||||||
|
}
|
@ -1,386 +0,0 @@
|
|||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : true,
|
|
||||||
"properties" : {
|
|
||||||
"device" : {
|
|
||||||
"type" : "object",
|
|
||||||
"required" : true,
|
|
||||||
"properties" : {
|
|
||||||
"name" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"type" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"output" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"rate" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true,
|
|
||||||
"minimum" : 0
|
|
||||||
},
|
|
||||||
"colorOrder" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : false
|
|
||||||
},
|
|
||||||
"bgr-output" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"color": {
|
|
||||||
"type":"object",
|
|
||||||
"required":false,
|
|
||||||
"properties": {
|
|
||||||
"hsv" : {
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"saturationGain" : {
|
|
||||||
"type" : "number",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 0.0
|
|
||||||
},
|
|
||||||
"valueGain" : {
|
|
||||||
"type" : "number",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 0.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"hsl" : {
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"saturationGain" : {
|
|
||||||
"type" : "number",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 0.0
|
|
||||||
},
|
|
||||||
"luminanceGain" : {
|
|
||||||
"type" : "number",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 0.0
|
|
||||||
},
|
|
||||||
"luminanceMinimum" : {
|
|
||||||
"type" : "number",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 0.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"red": {
|
|
||||||
"type":"object",
|
|
||||||
"required":false,
|
|
||||||
"properties":{
|
|
||||||
"gamma": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"blacklevel": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"whitelevel": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"threshold": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false,
|
|
||||||
"minimum" : 0.0,
|
|
||||||
"maximum" : 1.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"green": {
|
|
||||||
"type":"object",
|
|
||||||
"required":false,
|
|
||||||
"properties":{
|
|
||||||
"gamma": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"blacklevel": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"whitelevel": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"threshold": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false,
|
|
||||||
"minimum" : 0.0,
|
|
||||||
"maximum" : 1.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"blue": {
|
|
||||||
"type":"object",
|
|
||||||
"required":false,
|
|
||||||
"properties":{
|
|
||||||
"gamma": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"whitelevel": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"blacklevel": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false
|
|
||||||
},
|
|
||||||
"threshold": {
|
|
||||||
"type":"number",
|
|
||||||
"required":false,
|
|
||||||
"minimum" : 0.0,
|
|
||||||
"maximum" : 1.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"smoothing" : {
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"type" : {
|
|
||||||
"type" : "enum",
|
|
||||||
"required" : true,
|
|
||||||
"values" : ["none", "linear"]
|
|
||||||
},
|
|
||||||
"time_ms" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 10
|
|
||||||
},
|
|
||||||
"updateFrequency" : {
|
|
||||||
"type" : "number",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 0.001
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"leds": {
|
|
||||||
"type":"array",
|
|
||||||
"required":true,
|
|
||||||
"items": {
|
|
||||||
"type":"object",
|
|
||||||
"properties": {
|
|
||||||
"index": {
|
|
||||||
"type":"integer",
|
|
||||||
"required":true
|
|
||||||
},
|
|
||||||
"hscan": {
|
|
||||||
"type":"object",
|
|
||||||
"required":true,
|
|
||||||
"properties": {
|
|
||||||
"minimum": {
|
|
||||||
"type":"number",
|
|
||||||
"required":true
|
|
||||||
},
|
|
||||||
"maximum": {
|
|
||||||
"type":"number",
|
|
||||||
"required":true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"vscan": {
|
|
||||||
"type":"object",
|
|
||||||
"required":true,
|
|
||||||
"properties": {
|
|
||||||
"minimum": {
|
|
||||||
"type":"number",
|
|
||||||
"required":true
|
|
||||||
},
|
|
||||||
"maximum": {
|
|
||||||
"type":"number",
|
|
||||||
"required":true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"colorOrder" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"effects" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"paths" : {
|
|
||||||
"type" : "array",
|
|
||||||
"required" : false,
|
|
||||||
"items" : {
|
|
||||||
"type" : "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"blackborderdetector" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"enable" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"threshold" : {
|
|
||||||
"type" : "number",
|
|
||||||
"required" : false,
|
|
||||||
"minimum" : 0.0,
|
|
||||||
"maximum" : 1.0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"xbmcVideoChecker" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"xbmcAddress" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"xbmcTcpPort" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"grabVideo" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"grabPictures" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"grabAudio" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"grabMenu" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"grabPause" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : false
|
|
||||||
},
|
|
||||||
"grabScreensaver" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : false
|
|
||||||
},
|
|
||||||
"enable3DDetection" : {
|
|
||||||
"type" : "boolean",
|
|
||||||
"required" : false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"bootsequence" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"path" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"effect" : {
|
|
||||||
"type" : "string",
|
|
||||||
"required" : true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"framegrabber" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"width" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"height" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true
|
|
||||||
},
|
|
||||||
"frequency_Hz" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"jsonServer" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"port" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true,
|
|
||||||
"minimum" : 0,
|
|
||||||
"maximum" : 65535
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"protoServer" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"port" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true,
|
|
||||||
"minimum" : 0,
|
|
||||||
"maximum" : 65535
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
},
|
|
||||||
"boblightServer" :
|
|
||||||
{
|
|
||||||
"type" : "object",
|
|
||||||
"required" : false,
|
|
||||||
"properties" : {
|
|
||||||
"port" : {
|
|
||||||
"type" : "integer",
|
|
||||||
"required" : true,
|
|
||||||
"minimum" : 0,
|
|
||||||
"maximum" : 65535
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties" : false
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -27,6 +27,7 @@ SET(Utils_HEADERS
|
|||||||
${CURRENT_HEADER_DIR}/RgbToRgbw.h
|
${CURRENT_HEADER_DIR}/RgbToRgbw.h
|
||||||
${CURRENT_HEADER_DIR}/jsonschema/QJsonFactory.h
|
${CURRENT_HEADER_DIR}/jsonschema/QJsonFactory.h
|
||||||
${CURRENT_HEADER_DIR}/jsonschema/QJsonSchemaChecker.h
|
${CURRENT_HEADER_DIR}/jsonschema/QJsonSchemaChecker.h
|
||||||
|
${CURRENT_HEADER_DIR}/jsonschema/QJsonUtils.h
|
||||||
${CURRENT_HEADER_DIR}/global_defines.h
|
${CURRENT_HEADER_DIR}/global_defines.h
|
||||||
${CURRENT_HEADER_DIR}/SysInfo.h
|
${CURRENT_HEADER_DIR}/SysInfo.h
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QVariantMap>
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
@ -594,6 +593,7 @@ void JsonProcessor::handleServerInfoCommand(const QJsonObject&, const QString& c
|
|||||||
ledDevices["available"] = availableLedDevices;
|
ledDevices["available"] = availableLedDevices;
|
||||||
info["ledDevices"] = ledDevices;
|
info["ledDevices"] = ledDevices;
|
||||||
|
|
||||||
|
#if defined(ENABLE_DISPMANX) || defined(ENABLE_V4L2) || defined(ENABLE_FB) || defined(ENABLE_AMLOGIC) || defined(ENABLE_OSX) || defined(ENABLE_X11)
|
||||||
// get available grabbers
|
// get available grabbers
|
||||||
QJsonObject grabbers;
|
QJsonObject grabbers;
|
||||||
//grabbers["active"] = ????;
|
//grabbers["active"] = ????;
|
||||||
@ -605,6 +605,9 @@ void JsonProcessor::handleServerInfoCommand(const QJsonObject&, const QString& c
|
|||||||
|
|
||||||
grabbers["available"] = availableGrabbers;
|
grabbers["available"] = availableGrabbers;
|
||||||
info["grabbers"] = grabbers;
|
info["grabbers"] = grabbers;
|
||||||
|
#else
|
||||||
|
info["grabbers"] = QString("none");
|
||||||
|
#endif
|
||||||
|
|
||||||
// get available components
|
// get available components
|
||||||
QJsonArray component;
|
QJsonArray component;
|
||||||
@ -844,45 +847,19 @@ void JsonProcessor::handleSchemaGetCommand(const QJsonObject& message, const QSt
|
|||||||
|
|
||||||
// make sure the resources are loaded (they may be left out after static linking)
|
// make sure the resources are loaded (they may be left out after static linking)
|
||||||
Q_INIT_RESOURCE(resource);
|
Q_INIT_RESOURCE(resource);
|
||||||
QJsonParseError error;
|
|
||||||
|
|
||||||
// read the hyperion json schema from the resource
|
// read the hyperion json schema from the resource
|
||||||
QFile schemaData(":/hyperion-schema-"+QString::number(_hyperion->getConfigVersionId()));
|
QString schemaFile = ":/hyperion-schema";
|
||||||
|
|
||||||
if (!schemaData.open(QIODevice::ReadOnly))
|
try
|
||||||
{
|
{
|
||||||
std::stringstream error;
|
schemaJson = QJsonFactory::readSchema(schemaFile);
|
||||||
error << "Schema not found: " << schemaData.errorString().toStdString();
|
|
||||||
throw std::runtime_error(error.str());
|
|
||||||
}
|
}
|
||||||
|
catch(const std::runtime_error& error)
|
||||||
QByteArray schema = schemaData.readAll();
|
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(schema, &error);
|
|
||||||
schemaData.close();
|
|
||||||
|
|
||||||
if (error.error != QJsonParseError::NoError)
|
|
||||||
{
|
{
|
||||||
// report to the user the failure and their locations in the document.
|
throw std::runtime_error(error.what());
|
||||||
int errorLine(0), errorColumn(0);
|
|
||||||
|
|
||||||
for( int i=0, count=qMin( error.offset,schema.size()); i<count; ++i )
|
|
||||||
{
|
|
||||||
++errorColumn;
|
|
||||||
if(schema.at(i) == '\n' )
|
|
||||||
{
|
|
||||||
errorColumn = 0;
|
|
||||||
++errorLine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::stringstream sstream;
|
|
||||||
sstream << "ERROR: Json schema wrong: " << error.errorString().toStdString() << " at Line: " << errorLine << ", Column: " << errorColumn;
|
|
||||||
|
|
||||||
throw std::runtime_error(sstream.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
schemaJson = doc.object();
|
|
||||||
|
|
||||||
// collect all LED Devices
|
// collect all LED Devices
|
||||||
properties = schemaJson["properties"].toObject();
|
properties = schemaJson["properties"].toObject();
|
||||||
alldevices = LedDevice::getLedDeviceSchemas();
|
alldevices = LedDevice::getLedDeviceSchemas();
|
||||||
@ -1139,7 +1116,7 @@ bool JsonProcessor::checkJson(const QJsonObject& message, const QString& schemaR
|
|||||||
schemaChecker.setSchema(schemaJson.object());
|
schemaChecker.setSchema(schemaJson.object());
|
||||||
|
|
||||||
// check the message
|
// check the message
|
||||||
if (!schemaChecker.validate(message, ignoreRequired))
|
if (!schemaChecker.validate(message, ignoreRequired).first)
|
||||||
{
|
{
|
||||||
const QStringList & errors = schemaChecker.getMessages();
|
const QStringList & errors = schemaChecker.getMessages();
|
||||||
errorMessage = "{";
|
errorMessage = "{";
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
// Utils-Jsonschema includes
|
// Utils-Jsonschema includes
|
||||||
#include <utils/jsonschema/QJsonSchemaChecker.h>
|
#include <utils/jsonschema/QJsonSchemaChecker.h>
|
||||||
|
#include <utils/jsonschema/QJsonUtils.h>
|
||||||
|
|
||||||
QJsonSchemaChecker::QJsonSchemaChecker()
|
QJsonSchemaChecker::QJsonSchemaChecker()
|
||||||
{
|
{
|
||||||
@ -25,11 +26,12 @@ bool QJsonSchemaChecker::setSchema(const QJsonObject & schema)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QJsonSchemaChecker::validate(const QJsonObject & value, bool ignoreRequired)
|
QPair<bool, bool> QJsonSchemaChecker::validate(const QJsonObject & value, bool ignoreRequired)
|
||||||
{
|
{
|
||||||
// initialize state
|
// initialize state
|
||||||
_ignoreRequired = ignoreRequired;
|
_ignoreRequired = ignoreRequired;
|
||||||
_error = false;
|
_error = false;
|
||||||
|
_schemaError = false;
|
||||||
_messages.clear();
|
_messages.clear();
|
||||||
_currentPath.clear();
|
_currentPath.clear();
|
||||||
_currentPath.append("[root]");
|
_currentPath.append("[root]");
|
||||||
@ -37,7 +39,27 @@ bool QJsonSchemaChecker::validate(const QJsonObject & value, bool ignoreRequired
|
|||||||
// validate
|
// validate
|
||||||
validate(value, _qSchema);
|
validate(value, _qSchema);
|
||||||
|
|
||||||
return !_error;
|
return QPair<bool, bool>(!_error, !_schemaError);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject QJsonSchemaChecker::getAutoCorrectedConfig(const QJsonObject& value, bool ignoreRequired)
|
||||||
|
{
|
||||||
|
_ignoreRequired = ignoreRequired;
|
||||||
|
QStringList sequence = QStringList() << "remove" << "modify" << "create";
|
||||||
|
_error = false;
|
||||||
|
_schemaError = false;
|
||||||
|
_messages.clear();
|
||||||
|
_autoCorrected = value;
|
||||||
|
|
||||||
|
for(const QString &correct : sequence)
|
||||||
|
{
|
||||||
|
_correct = correct;
|
||||||
|
_currentPath.clear();
|
||||||
|
_currentPath.append("[root]");
|
||||||
|
validate(_autoCorrected, _qSchema);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _autoCorrected;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &schema)
|
void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &schema)
|
||||||
@ -48,15 +70,17 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s
|
|||||||
QString attribute = i.key();
|
QString attribute = i.key();
|
||||||
const QJsonValue & attributeValue = *i;
|
const QJsonValue & attributeValue = *i;
|
||||||
|
|
||||||
|
QJsonObject::const_iterator defaultValue = schema.find("default");
|
||||||
|
|
||||||
if (attribute == "type")
|
if (attribute == "type")
|
||||||
checkType(value, attributeValue);
|
checkType(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "properties")
|
else if (attribute == "properties")
|
||||||
{
|
{
|
||||||
if (value.isObject())
|
if (value.isObject())
|
||||||
checkProperties(value.toObject(), attributeValue.toObject());
|
checkProperties(value.toObject(), attributeValue.toObject());
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_error = true;
|
_schemaError = true;
|
||||||
setMessage("properties attribute is only valid for objects");
|
setMessage("properties attribute is only valid for objects");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -76,19 +100,19 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_error = true;
|
_schemaError = true;
|
||||||
setMessage("additional properties attribute is only valid for objects");
|
setMessage("additional properties attribute is only valid for objects");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (attribute == "minimum")
|
else if (attribute == "minimum")
|
||||||
checkMinimum(value, attributeValue);
|
checkMinimum(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "maximum")
|
else if (attribute == "maximum")
|
||||||
checkMaximum(value, attributeValue);
|
checkMaximum(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "minLength")
|
else if (attribute == "minLength")
|
||||||
checkMinLength(value, attributeValue);
|
checkMinLength(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "maxLength")
|
else if (attribute == "maxLength")
|
||||||
checkMaxLength(value, attributeValue);
|
checkMaxLength(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "items")
|
else if (attribute == "items")
|
||||||
{
|
{
|
||||||
if (value.isArray())
|
if (value.isArray())
|
||||||
@ -101,13 +125,13 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (attribute == "minItems")
|
else if (attribute == "minItems")
|
||||||
checkMinItems(value, attributeValue);
|
checkMinItems(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "maxItems")
|
else if (attribute == "maxItems")
|
||||||
checkMaxItems(value, attributeValue);
|
checkMaxItems(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "uniqueItems")
|
else if (attribute == "uniqueItems")
|
||||||
checkUniqueItems(value, attributeValue);
|
checkUniqueItems(value, attributeValue);
|
||||||
else if (attribute == "enum")
|
else if (attribute == "enum")
|
||||||
checkEnum(value, attributeValue);
|
checkEnum(value, attributeValue, (defaultValue != schema.end() ? defaultValue.value() : QJsonValue::Null));
|
||||||
else if (attribute == "required")
|
else if (attribute == "required")
|
||||||
; // nothing to do. value is present so always oke
|
; // nothing to do. value is present so always oke
|
||||||
else if (attribute == "id")
|
else if (attribute == "id")
|
||||||
@ -118,7 +142,7 @@ void QJsonSchemaChecker::validate(const QJsonValue & value, const QJsonObject &s
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// no check function defined for this attribute
|
// no check function defined for this attribute
|
||||||
_error = true;
|
_schemaError = true;
|
||||||
setMessage("No check function defined for attribute " + attribute);
|
setMessage("No check function defined for attribute " + attribute);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -135,7 +159,7 @@ const QStringList & QJsonSchemaChecker::getMessages() const
|
|||||||
return _messages;
|
return _messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkType(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkType(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
QString type = schema.toString();
|
QString type = schema.toString();
|
||||||
|
|
||||||
@ -145,7 +169,12 @@ void QJsonSchemaChecker::checkType(const QJsonValue & value, const QJsonValue &
|
|||||||
else if (type == "number")
|
else if (type == "number")
|
||||||
wrongType = !value.isDouble();
|
wrongType = !value.isDouble();
|
||||||
else if (type == "integer")
|
else if (type == "integer")
|
||||||
wrongType = (rint(value.toDouble()) != value.toDouble());
|
{
|
||||||
|
if (value.isDouble()) //check if value type not boolean (true = 1 && false = 0)
|
||||||
|
wrongType = (rint(value.toDouble()) != value.toDouble());
|
||||||
|
else
|
||||||
|
wrongType = true;
|
||||||
|
}
|
||||||
else if (type == "double")
|
else if (type == "double")
|
||||||
wrongType = !value.isDouble();
|
wrongType = !value.isDouble();
|
||||||
else if (type == "boolean")
|
else if (type == "boolean")
|
||||||
@ -160,13 +189,16 @@ void QJsonSchemaChecker::checkType(const QJsonValue & value, const QJsonValue &
|
|||||||
wrongType = !value.isString();
|
wrongType = !value.isString();
|
||||||
else if (type == "any")
|
else if (type == "any")
|
||||||
wrongType = false;
|
wrongType = false;
|
||||||
// else
|
|
||||||
// assert(false);
|
|
||||||
|
|
||||||
if (wrongType)
|
if (wrongType)
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage(type + " expected");
|
|
||||||
|
if (_correct == "modify")
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage(type + " expected");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +208,7 @@ void QJsonSchemaChecker::checkProperties(const QJsonObject & value, const QJsonO
|
|||||||
{
|
{
|
||||||
QString property = i.key();
|
QString property = i.key();
|
||||||
|
|
||||||
const QJsonValue & propertyValue = i.value();
|
const QJsonValue & propertyValue = *i;
|
||||||
|
|
||||||
_currentPath.append("." + property);
|
_currentPath.append("." + property);
|
||||||
QJsonObject::const_iterator required = propertyValue.toObject().find("required");
|
QJsonObject::const_iterator required = propertyValue.toObject().find("required");
|
||||||
@ -185,11 +217,19 @@ void QJsonSchemaChecker::checkProperties(const QJsonObject & value, const QJsonO
|
|||||||
{
|
{
|
||||||
validate(value[property], propertyValue.toObject());
|
validate(value[property], propertyValue.toObject());
|
||||||
}
|
}
|
||||||
else if (required != propertyValue.toObject().end() && required.value().toBool() && !_ignoreRequired)
|
else if (required != propertyValue.toObject().end() && propertyValue.toObject().find("required").value().toBool() && !_ignoreRequired)
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("missing member");
|
|
||||||
|
if (_correct == "create")
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, QJsonUtils::create(propertyValue, _ignoreRequired), property);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("missing member");
|
||||||
}
|
}
|
||||||
|
else if (_correct == "create" && _ignoreRequired)
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, QJsonUtils::create(propertyValue, _ignoreRequired), property);
|
||||||
|
|
||||||
_currentPath.removeLast();
|
_currentPath.removeLast();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -208,7 +248,12 @@ void QJsonSchemaChecker::checkAdditionalProperties(const QJsonObject & value, co
|
|||||||
if (schema.toBool() == false)
|
if (schema.toBool() == false)
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("no schema definition");
|
|
||||||
|
if (_correct == "remove")
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("no schema definition");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -220,7 +265,7 @@ void QJsonSchemaChecker::checkAdditionalProperties(const QJsonObject & value, co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkMinimum(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkMinimum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
if (!value.isDouble())
|
if (!value.isDouble())
|
||||||
{
|
{
|
||||||
@ -233,11 +278,18 @@ void QJsonSchemaChecker::checkMinimum(const QJsonValue & value, const QJsonValue
|
|||||||
if (value.toDouble() < schema.toDouble())
|
if (value.toDouble() < schema.toDouble())
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("value is too small (minimum=" + schema.toString() + ")");
|
|
||||||
|
if (_correct == "modify")
|
||||||
|
(defaultValue != QJsonValue::Null) ?
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, schema);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("value is too small (minimum=" + QString::number(schema.toDouble()) + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkMaximum(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkMaximum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
if (!value.isDouble())
|
if (!value.isDouble())
|
||||||
{
|
{
|
||||||
@ -250,11 +302,18 @@ void QJsonSchemaChecker::checkMaximum(const QJsonValue & value, const QJsonValue
|
|||||||
if (value.toDouble() > schema.toDouble())
|
if (value.toDouble() > schema.toDouble())
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("value is too large (maximum=" + schema.toString() + ")");
|
|
||||||
|
if (_correct == "modify")
|
||||||
|
(defaultValue != QJsonValue::Null) ?
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, schema);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("value is too large (maximum=" + QString::number(schema.toDouble()) + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkMinLength(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkMinLength(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
if (!value.isString())
|
if (!value.isString())
|
||||||
{
|
{
|
||||||
@ -267,11 +326,18 @@ void QJsonSchemaChecker::checkMinLength(const QJsonValue & value, const QJsonVal
|
|||||||
if (value.toString().size() < schema.toInt())
|
if (value.toString().size() < schema.toInt())
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("value is too short (minLength=" + schema.toString() + ")");
|
|
||||||
|
if (_correct == "modify")
|
||||||
|
(defaultValue != QJsonValue::Null) ?
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, schema);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("value is too short (minLength=" + QString::number(schema.toInt()) + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkMaxLength(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkMaxLength(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
if (!value.isString())
|
if (!value.isString())
|
||||||
{
|
{
|
||||||
@ -284,7 +350,14 @@ void QJsonSchemaChecker::checkMaxLength(const QJsonValue & value, const QJsonVal
|
|||||||
if (value.toString().size() > schema.toInt())
|
if (value.toString().size() > schema.toInt())
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("value is too long (maxLength=" + schema.toString() + ")");
|
|
||||||
|
if (_correct == "modify")
|
||||||
|
(defaultValue != QJsonValue::Null) ?
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, schema);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("value is too long (maxLength=" + QString::number(schema.toInt()) + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -299,6 +372,11 @@ void QJsonSchemaChecker::checkItems(const QJsonValue & value, const QJsonObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
QJsonArray jArray = value.toArray();
|
QJsonArray jArray = value.toArray();
|
||||||
|
|
||||||
|
if (_correct == "remove")
|
||||||
|
if (jArray.isEmpty())
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath);
|
||||||
|
|
||||||
for(int i = 0; i < jArray.size(); ++i)
|
for(int i = 0; i < jArray.size(); ++i)
|
||||||
{
|
{
|
||||||
// validate each item
|
// validate each item
|
||||||
@ -308,7 +386,7 @@ void QJsonSchemaChecker::checkItems(const QJsonValue & value, const QJsonObject
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkMinItems(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkMinItems(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
if (!value.isArray())
|
if (!value.isArray())
|
||||||
{
|
{
|
||||||
@ -318,17 +396,22 @@ void QJsonSchemaChecker::checkMinItems(const QJsonValue & value, const QJsonValu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int minimum = schema.toInt();
|
|
||||||
|
|
||||||
QJsonArray jArray = value.toArray();
|
QJsonArray jArray = value.toArray();
|
||||||
if (static_cast<int>(jArray.size()) < minimum)
|
if (jArray.size() < schema.toInt())
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("array is too large (minimum=" + QString::number(minimum) + ")");
|
|
||||||
|
if (_correct == "modify")
|
||||||
|
(defaultValue != QJsonValue::Null) ?
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, schema);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("array is too small (minimum=" + QString::number(schema.toInt()) + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkMaxItems(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkMaxItems(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
if (!value.isArray())
|
if (!value.isArray())
|
||||||
{
|
{
|
||||||
@ -338,13 +421,18 @@ void QJsonSchemaChecker::checkMaxItems(const QJsonValue & value, const QJsonValu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int maximum = schema.toInt();
|
|
||||||
|
|
||||||
QJsonArray jArray = value.toArray();
|
QJsonArray jArray = value.toArray();
|
||||||
if (static_cast<int>(jArray.size()) > maximum)
|
if (jArray.size() > schema.toInt())
|
||||||
{
|
{
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("array is too large (maximum=" + QString::number(maximum) + ")");
|
|
||||||
|
if (_correct == "modify")
|
||||||
|
(defaultValue != QJsonValue::Null) ?
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, schema);
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("array is too large (maximum=" + QString::number(schema.toInt()) + ")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -362,6 +450,8 @@ void QJsonSchemaChecker::checkUniqueItems(const QJsonValue & value, const QJsonV
|
|||||||
{
|
{
|
||||||
// make sure no two items are identical
|
// make sure no two items are identical
|
||||||
|
|
||||||
|
bool removeDuplicates = false;
|
||||||
|
|
||||||
QJsonArray jArray = value.toArray();
|
QJsonArray jArray = value.toArray();
|
||||||
for(int i = 0; i < jArray.size(); ++i)
|
for(int i = 0; i < jArray.size(); ++i)
|
||||||
{
|
{
|
||||||
@ -371,14 +461,28 @@ void QJsonSchemaChecker::checkUniqueItems(const QJsonValue & value, const QJsonV
|
|||||||
{
|
{
|
||||||
// found a value twice
|
// found a value twice
|
||||||
_error = true;
|
_error = true;
|
||||||
setMessage("array must have unique values");
|
removeDuplicates = true;
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
setMessage("array must have unique values");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (removeDuplicates && _correct == "modify")
|
||||||
|
{
|
||||||
|
QJsonArray uniqueItemsArray;
|
||||||
|
|
||||||
|
for(int i = 0; i < jArray.size(); ++i)
|
||||||
|
if (!uniqueItemsArray.contains(jArray[i]))
|
||||||
|
uniqueItemsArray.append(jArray[i]);
|
||||||
|
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, uniqueItemsArray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QJsonSchemaChecker::checkEnum(const QJsonValue & value, const QJsonValue & schema)
|
void QJsonSchemaChecker::checkEnum(const QJsonValue & value, const QJsonValue & schema, const QJsonValue & defaultValue)
|
||||||
{
|
{
|
||||||
if (schema.isArray())
|
if (schema.isArray())
|
||||||
{
|
{
|
||||||
@ -395,7 +499,16 @@ void QJsonSchemaChecker::checkEnum(const QJsonValue & value, const QJsonValue &
|
|||||||
|
|
||||||
// nothing found
|
// nothing found
|
||||||
_error = true;
|
_error = true;
|
||||||
QJsonDocument doc(schema.toArray());
|
|
||||||
QString strJson(doc.toJson(QJsonDocument::Compact));
|
if (_correct == "modify")
|
||||||
setMessage("Unknown enum value (allowed values are: " + schema.toString() + strJson+ ")");
|
(defaultValue != QJsonValue::Null) ?
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, defaultValue) :
|
||||||
|
QJsonUtils::modify(_autoCorrected, _currentPath, schema.toArray().first());
|
||||||
|
|
||||||
|
if (_correct == "")
|
||||||
|
{
|
||||||
|
QJsonDocument doc(schema.toArray());
|
||||||
|
QString strJson(doc.toJson(QJsonDocument::Compact));
|
||||||
|
setMessage("Unknown enum value (allowed values are: " + strJson+ ")");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,14 +105,43 @@ void CgiHandler::cmd_cfg_set()
|
|||||||
{
|
{
|
||||||
// make sure the resources are loaded (they may be left out after static linking)
|
// make sure the resources are loaded (they may be left out after static linking)
|
||||||
Q_INIT_RESOURCE(resource);
|
Q_INIT_RESOURCE(resource);
|
||||||
QJsonObject schemaJson = QJsonFactory::readSchema(":/hyperion-schema-"+QString::number(_hyperion->getConfigVersionId()));
|
|
||||||
|
QString schemaFile = ":/hyperion-schema";
|
||||||
|
QJsonObject schemaJson;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
schemaJson = QJsonFactory::readSchema(schemaFile);
|
||||||
|
}
|
||||||
|
catch(const std::runtime_error& error)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(error.what());
|
||||||
|
}
|
||||||
|
|
||||||
QJsonSchemaChecker schemaChecker;
|
QJsonSchemaChecker schemaChecker;
|
||||||
schemaChecker.setSchema(schemaJson);
|
schemaChecker.setSchema(schemaJson);
|
||||||
if ( schemaChecker.validate(hyperionConfigJsonObj) )
|
|
||||||
|
QPair<bool, bool> validate = schemaChecker.validate(hyperionConfigJsonObj);
|
||||||
|
|
||||||
|
|
||||||
|
if (validate.first && validate.second)
|
||||||
{
|
{
|
||||||
QJsonFactory::writeJson(_hyperion->getConfigFileName(), hyperionConfigJsonObj);
|
QJsonFactory::writeJson(_hyperion->getConfigFileName(), hyperionConfigJsonObj);
|
||||||
}
|
}
|
||||||
else
|
else if (!validate.first && validate.second)
|
||||||
|
{
|
||||||
|
Warning(_log,"Errors have been found in the configuration file. Automatic correction is applied");
|
||||||
|
|
||||||
|
QStringList schemaErrors = schemaChecker.getMessages();
|
||||||
|
foreach (auto & schemaError, schemaErrors)
|
||||||
|
Info(_log, schemaError.toUtf8().constData());
|
||||||
|
|
||||||
|
hyperionConfigJsonObj = schemaChecker.getAutoCorrectedConfig(hyperionConfigJsonObj);
|
||||||
|
|
||||||
|
if (!QJsonFactory::writeJson(_hyperion->getConfigFileName(), hyperionConfigJsonObj))
|
||||||
|
throw std::runtime_error("ERROR: can not save configuration file, aborting ");
|
||||||
|
}
|
||||||
|
else //Error in Schema
|
||||||
{
|
{
|
||||||
QString errorMsg = "ERROR: Json validation failed: \n";
|
QString errorMsg = "ERROR: Json validation failed: \n";
|
||||||
QStringList schemaErrors = schemaChecker.getMessages();
|
QStringList schemaErrors = schemaChecker.getMessages();
|
||||||
@ -121,6 +150,7 @@ void CgiHandler::cmd_cfg_set()
|
|||||||
Error(_log, "config write validation: %s", QSTRING_CSTR(schemaError));
|
Error(_log, "config write validation: %s", QSTRING_CSTR(schemaError));
|
||||||
errorMsg += schemaError + "\n";
|
errorMsg += schemaError + "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::runtime_error(errorMsg.toStdString());
|
throw std::runtime_error(errorMsg.toStdString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,6 @@ QT5_WRAP_CPP(Hyperiond_HEADERS_MOC ${Hyperiond_QT_HEADERS})
|
|||||||
add_executable(hyperiond
|
add_executable(hyperiond
|
||||||
${Hyperiond_QT_HEADERS}
|
${Hyperiond_QT_HEADERS}
|
||||||
${Hyperiond_HEADERS_MOC}
|
${Hyperiond_HEADERS_MOC}
|
||||||
configMigratorBase.cpp
|
|
||||||
configMigratorBase.h
|
|
||||||
configMigrator.cpp
|
|
||||||
configMigrator.h
|
|
||||||
hyperiond.cpp
|
hyperiond.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
#include "configMigrator.h"
|
|
||||||
|
|
||||||
|
|
||||||
ConfigMigrator::ConfigMigrator()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigMigrator::~ConfigMigrator()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ConfigMigrator::migrate(QString configFile, int fromVersion,int toVersion)
|
|
||||||
{
|
|
||||||
Debug(_log, "migrate config %s from version %d to %d.", configFile.toLocal8Bit().constData(), fromVersion, toVersion);
|
|
||||||
|
|
||||||
for (int v=fromVersion; v<toVersion; v++)
|
|
||||||
{
|
|
||||||
switch(v)
|
|
||||||
{
|
|
||||||
case 1: migrateFrom1(); break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw std::runtime_error("ERROR: config migration - unknown version");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ConfigMigrator::migrateFrom1()
|
|
||||||
{
|
|
||||||
throw std::runtime_error("ERROR: config migration not implemented");
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "configMigratorBase.h"
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
///
|
|
||||||
/// class that contains migration code
|
|
||||||
/// helper code goeas to base class
|
|
||||||
class ConfigMigrator : public ConfigMigratorBase
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConfigMigrator();
|
|
||||||
~ConfigMigrator();
|
|
||||||
|
|
||||||
bool migrate(QString configFile, int fromVersion,int toVersion);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void migrateFrom1();
|
|
||||||
};
|
|
@ -1,11 +0,0 @@
|
|||||||
#include "configMigratorBase.h"
|
|
||||||
|
|
||||||
ConfigMigratorBase::ConfigMigratorBase()
|
|
||||||
: _log(Logger::getInstance("ConfigMigrator"))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfigMigratorBase::~ConfigMigratorBase()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <utils/Logger.h>
|
|
||||||
|
|
||||||
#include <QString>
|
|
||||||
|
|
||||||
class ConfigMigratorBase
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConfigMigratorBase();
|
|
||||||
~ConfigMigratorBase();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Logger * _log;
|
|
||||||
};
|
|
@ -12,6 +12,7 @@
|
|||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
|
#include <QPair>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
@ -31,7 +32,6 @@
|
|||||||
#include <udplistener/UDPListener.h>
|
#include <udplistener/UDPListener.h>
|
||||||
|
|
||||||
#include "hyperiond.h"
|
#include "hyperiond.h"
|
||||||
#include "configMigrator.h"
|
|
||||||
|
|
||||||
HyperionDaemon::HyperionDaemon(QString configFile, QObject *parent)
|
HyperionDaemon::HyperionDaemon(QString configFile, QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
@ -52,7 +52,7 @@ HyperionDaemon::HyperionDaemon(QString configFile, QObject *parent)
|
|||||||
, _hyperion(nullptr)
|
, _hyperion(nullptr)
|
||||||
, _stats(nullptr)
|
, _stats(nullptr)
|
||||||
{
|
{
|
||||||
loadConfig(configFile, CURRENT_CONFIG_VERSION );
|
loadConfig(configFile);
|
||||||
|
|
||||||
if (Logger::getLogLevel() == Logger::WARNING)
|
if (Logger::getLogLevel() == Logger::WARNING)
|
||||||
{
|
{
|
||||||
@ -135,16 +135,16 @@ void HyperionDaemon::run()
|
|||||||
connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects()));
|
connect(_hyperion,SIGNAL(closing()),this,SLOT(freeObjects()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int HyperionDaemon::tryLoadConfig(const QString & configFile, const int schemaVersion)
|
void HyperionDaemon::loadConfig(const QString & configFile)
|
||||||
{
|
{
|
||||||
|
Info(_log, "Selected configuration file: %s", configFile.toUtf8().constData());
|
||||||
|
|
||||||
// make sure the resources are loaded (they may be left out after static linking)
|
// make sure the resources are loaded (they may be left out after static linking)
|
||||||
Q_INIT_RESOURCE(resource);
|
Q_INIT_RESOURCE(resource);
|
||||||
|
|
||||||
// read the json schema from the resource
|
// read the json schema from the resource
|
||||||
|
|
||||||
QString schemaFile = ":/hyperion-schema";
|
QString schemaFile = ":/hyperion-schema";
|
||||||
if (schemaVersion > 0)
|
|
||||||
schemaFile += "-" + QString::number(schemaVersion);
|
|
||||||
|
|
||||||
QJsonObject schemaJson;
|
QJsonObject schemaJson;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -159,45 +159,25 @@ int HyperionDaemon::tryLoadConfig(const QString & configFile, const int schemaVe
|
|||||||
schemaChecker.setSchema(schemaJson);
|
schemaChecker.setSchema(schemaJson);
|
||||||
|
|
||||||
_qconfig = QJsonFactory::readConfig(configFile);
|
_qconfig = QJsonFactory::readConfig(configFile);
|
||||||
if (!schemaChecker.validate(_qconfig))
|
QPair<bool, bool> validate = schemaChecker.validate(_qconfig);
|
||||||
|
|
||||||
|
if (!validate.first && validate.second)
|
||||||
|
{
|
||||||
|
Warning(_log,"Errors have been found in the configuration file. Automatic correction is applied");
|
||||||
|
|
||||||
|
_qconfig = schemaChecker.getAutoCorrectedConfig(_qconfig);
|
||||||
|
|
||||||
|
if (!QJsonFactory::writeJson(configFile, _qconfig))
|
||||||
|
throw std::runtime_error("ERROR: can not save configuration file, aborting ");
|
||||||
|
}
|
||||||
|
else if (validate.first && !validate.second) //Error in Schema
|
||||||
{
|
{
|
||||||
QStringList schemaErrors = schemaChecker.getMessages();
|
QStringList schemaErrors = schemaChecker.getMessages();
|
||||||
foreach (auto & schemaError, schemaErrors)
|
foreach (auto & schemaError, schemaErrors)
|
||||||
{
|
|
||||||
std::cout << schemaError.toStdString() << std::endl;
|
std::cout << schemaError.toStdString() << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
throw std::runtime_error("ERROR: Json validation failed");
|
throw std::runtime_error("ERROR: Json validation failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
const QJsonObject & generalConfig = _qconfig["general"].toObject();
|
|
||||||
return generalConfig["configVersion"].toInt(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HyperionDaemon::loadConfig(const QString & configFile, const int neededConfigVersion)
|
|
||||||
{
|
|
||||||
Info(_log, "Selected configuration file: %s", configFile.toUtf8().constData());
|
|
||||||
|
|
||||||
int configVersionId = tryLoadConfig(configFile,0);
|
|
||||||
|
|
||||||
// no config id found, assume legacy hyperion
|
|
||||||
if (configVersionId < 0)
|
|
||||||
{
|
|
||||||
Debug(_log, "config file has no version, assume old hyperion.");
|
|
||||||
configVersionId = tryLoadConfig(configFile,1);
|
|
||||||
}
|
|
||||||
Debug(_log, "config version: %d", configVersionId);
|
|
||||||
configVersionId = tryLoadConfig(configFile, configVersionId);
|
|
||||||
|
|
||||||
if (neededConfigVersion == configVersionId)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// migrate configVersionId
|
|
||||||
ConfigMigrator migrator;
|
|
||||||
migrator.migrate(configFile, configVersionId, neededConfigVersion);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,9 +54,8 @@ class HyperionDaemon : public QObject
|
|||||||
public:
|
public:
|
||||||
HyperionDaemon(QString configFile, QObject *parent=nullptr);
|
HyperionDaemon(QString configFile, QObject *parent=nullptr);
|
||||||
~HyperionDaemon();
|
~HyperionDaemon();
|
||||||
|
|
||||||
int tryLoadConfig(const QString & configFile, const int schemaVersion);
|
void loadConfig(const QString & configFile);
|
||||||
void loadConfig(const QString & configFile, const int neededConfigVersion);
|
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
void startInitialEffect();
|
void startInitialEffect();
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
|
|
||||||
// STL includes
|
|
||||||
#include <cstdlib>
|
|
||||||
|
|
||||||
// QT includes
|
// QT includes
|
||||||
#include <QResource>
|
#include <QResource>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
// JsonSchema includes
|
// JsonSchema includes
|
||||||
#include <utils/jsonschema/QJsonFactory.h>
|
#include <utils/jsonschema/QJsonFactory.h>
|
||||||
@ -12,7 +9,7 @@
|
|||||||
#include <hyperion/LedString.h>
|
#include <hyperion/LedString.h>
|
||||||
#include "HyperionConfig.h"
|
#include "HyperionConfig.h"
|
||||||
|
|
||||||
bool loadConfig(const QString & configFile)
|
bool loadConfig(const QString & configFile, bool correct, bool ignore)
|
||||||
{
|
{
|
||||||
// make sure the resources are loaded (they may be left out after static linking)
|
// make sure the resources are loaded (they may be left out after static linking)
|
||||||
Q_INIT_RESOURCE(resource);
|
Q_INIT_RESOURCE(resource);
|
||||||
@ -39,46 +36,75 @@ bool loadConfig(const QString & configFile)
|
|||||||
// read and validate the configuration file from the command line
|
// read and validate the configuration file from the command line
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const QJsonObject jsonConfig = QJsonFactory::readConfig(configFile);
|
QJsonObject jsonConfig = QJsonFactory::readConfig(configFile);
|
||||||
|
|
||||||
if (!schemaChecker.validate(jsonConfig))
|
if (!correct)
|
||||||
{
|
{
|
||||||
QStringList schemaErrors = schemaChecker.getMessages();
|
if (!schemaChecker.validate(jsonConfig).first)
|
||||||
foreach (auto & schemaError, schemaErrors)
|
|
||||||
{
|
{
|
||||||
std::cout << "config write validation: " << schemaError.toStdString() << std::endl;
|
QStringList schemaErrors = schemaChecker.getMessages();
|
||||||
|
foreach (auto & schemaError, schemaErrors)
|
||||||
|
{
|
||||||
|
qDebug() << "config write validation: " << schemaError;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "FAILED";
|
||||||
|
exit(1);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
std::cout << "FAILED" << std::endl;
|
else
|
||||||
exit(1);
|
{
|
||||||
return false;
|
jsonConfig = schemaChecker.getAutoCorrectedConfig(jsonConfig, ignore); // The second parameter is to ignore the "required" keyword in hyperion schema
|
||||||
|
QJsonFactory::writeJson(configFile, jsonConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void usage()
|
||||||
|
{
|
||||||
|
qDebug() << "Missing required configuration file to test";
|
||||||
|
qDebug() << "Usage: test_configfile <option> [configfile]";
|
||||||
|
qDebug() << "<option>:";
|
||||||
|
qDebug() << "\t--ac - for json auto correction";
|
||||||
|
qDebug() << "\t--ac-ignore-required - for json auto correction without paying attention 'required' keyword in hyperion schema";
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
if (argc != 2)
|
if (argc < 2)
|
||||||
{
|
{
|
||||||
std::cerr << "Missing required configuration file to test" << std::endl;
|
usage();
|
||||||
std::cerr << "Usage: test_configfile [configfile]" << std::endl;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString configFile(argv[1]);
|
QString option = argv[1];
|
||||||
std::cout << "Configuration file selected: " << configFile.toStdString() << std::endl;
|
QString configFile;
|
||||||
std::cout << "Attemp to load..." << std::endl;
|
|
||||||
|
if (option == "--ac" || option == "--ac-ignore-required")
|
||||||
|
if (argc > 2)
|
||||||
|
configFile = argv[2];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
configFile = argv[1];
|
||||||
|
|
||||||
|
qDebug() << "Configuration file selected: " << configFile;
|
||||||
|
qDebug() << "Attemp to load...";
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (loadConfig(configFile))
|
if (loadConfig(configFile, (option == "--ac" || option == "--ac-ignore-required"), option == "--ac-ignore-required"))
|
||||||
std::cout << "PASSED" << std::endl;
|
qDebug() << "PASSED";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
catch (std::runtime_error exception)
|
catch (std::runtime_error exception)
|
||||||
{
|
{
|
||||||
std::cout << "FAILED" << std::endl;
|
qDebug() << "FAILED";
|
||||||
std::cout << exception.what() << std::endl;
|
qDebug() << exception.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import json, sys, glob
|
import json, sys, glob
|
||||||
from os import path
|
from os import path
|
||||||
from jsonschema import Draft3Validator
|
from jsonschema import Draft3Validator, RefResolver
|
||||||
|
|
||||||
print('-- validate json file')
|
print('-- validate json file')
|
||||||
|
|
||||||
@ -11,9 +11,8 @@ schemaFileName = sys.argv[2]
|
|||||||
try:
|
try:
|
||||||
with open(schemaFileName) as schemaFile:
|
with open(schemaFileName) as schemaFile:
|
||||||
with open(jsonFileName) as jsonFile:
|
with open(jsonFileName) as jsonFile:
|
||||||
j = json.loads(jsonFile.read())
|
resolver = RefResolver('file://%s/schema/' % path.abspath(path.dirname(schemaFileName)), None)
|
||||||
validator = Draft3Validator(json.loads(schemaFile.read()))
|
Draft3Validator(json.loads(schemaFile.read()), resolver=resolver).validate(json.loads(jsonFile.read()))
|
||||||
validator.validate(j)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print('validation error: '+jsonFileName + ' '+schemaFileName+' ('+str(e)+')')
|
print('validation error: '+jsonFileName + ' '+schemaFileName+' ('+str(e)+')')
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -4,46 +4,71 @@ An implementation of JSON Schema for Python
|
|||||||
The main functionality is provided by the validator classes for each of the
|
The main functionality is provided by the validator classes for each of the
|
||||||
supported JSON Schema versions.
|
supported JSON Schema versions.
|
||||||
|
|
||||||
Most commonly, the :function:`validate` function is the quickest way to simply
|
Most commonly, :func:`validate` is the quickest way to simply validate a given
|
||||||
validate a given instance under a schema, and will create a validator for you.
|
instance under a schema, and will create a validator for you.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import division, unicode_literals
|
from __future__ import division, unicode_literals
|
||||||
|
|
||||||
import collections
|
import collections
|
||||||
|
import json
|
||||||
import itertools
|
import itertools
|
||||||
import operator
|
import operator
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
|
||||||
|
|
||||||
|
|
||||||
__version__ = "0.7"
|
__version__ = "0.8.0"
|
||||||
|
|
||||||
FLOAT_TOLERANCE = 10 ** -15
|
|
||||||
PY3 = sys.version_info[0] >= 3
|
PY3 = sys.version_info[0] >= 3
|
||||||
|
|
||||||
if PY3:
|
if PY3:
|
||||||
|
from urllib import parse as urlparse
|
||||||
|
from urllib.parse import unquote
|
||||||
|
from urllib.request import urlopen
|
||||||
basestring = unicode = str
|
basestring = unicode = str
|
||||||
iteritems = operator.methodcaller("items")
|
iteritems = operator.methodcaller("items")
|
||||||
from urllib.parse import unquote
|
|
||||||
else:
|
else:
|
||||||
from itertools import izip as zip
|
from itertools import izip as zip
|
||||||
iteritems = operator.methodcaller("iteritems")
|
|
||||||
from urllib import unquote
|
from urllib import unquote
|
||||||
|
from urllib2 import urlopen
|
||||||
|
import urlparse
|
||||||
|
iteritems = operator.methodcaller("iteritems")
|
||||||
|
|
||||||
|
|
||||||
|
FLOAT_TOLERANCE = 10 ** -15
|
||||||
|
validators = {}
|
||||||
|
|
||||||
|
|
||||||
|
def validates(version):
|
||||||
|
"""
|
||||||
|
Register the decorated validator for a ``version`` of the specification.
|
||||||
|
|
||||||
|
Registered validators and their meta schemas will be considered when
|
||||||
|
parsing ``$schema`` properties' URIs.
|
||||||
|
|
||||||
|
:argument str version: an identifier to use as the version's name
|
||||||
|
:returns: a class decorator to decorate the validator with the version
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _validates(cls):
|
||||||
|
validators[version] = cls
|
||||||
|
return cls
|
||||||
|
return _validates
|
||||||
|
|
||||||
|
|
||||||
class UnknownType(Exception):
|
class UnknownType(Exception):
|
||||||
"""
|
"""
|
||||||
An unknown type was given.
|
An attempt was made to check if an instance was of an unknown type.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class InvalidRef(Exception):
|
class RefResolutionError(Exception):
|
||||||
"""
|
"""
|
||||||
An invalid reference was given.
|
A JSON reference failed to resolve.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -52,21 +77,23 @@ class SchemaError(Exception):
|
|||||||
"""
|
"""
|
||||||
The provided schema is malformed.
|
The provided schema is malformed.
|
||||||
|
|
||||||
The same attributes exist for ``SchemaError``s as for ``ValidationError``s.
|
The same attributes are present as for :exc:`ValidationError`\s.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
validator = None
|
def __init__(self, message, validator=None, path=()):
|
||||||
|
super(SchemaError, self).__init__(message, validator, path)
|
||||||
def __init__(self, message):
|
|
||||||
super(SchemaError, self).__init__(message)
|
|
||||||
self.message = message
|
self.message = message
|
||||||
self.path = []
|
self.path = list(path)
|
||||||
|
self.validator = validator
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.message
|
||||||
|
|
||||||
|
|
||||||
class ValidationError(Exception):
|
class ValidationError(Exception):
|
||||||
"""
|
"""
|
||||||
The instance didn't properly validate with the provided schema.
|
The instance didn't properly validate under the provided schema.
|
||||||
|
|
||||||
Relevant attributes are:
|
Relevant attributes are:
|
||||||
* ``message`` : a human readable message explaining the error
|
* ``message`` : a human readable message explaining the error
|
||||||
@ -76,19 +103,20 @@ class ValidationError(Exception):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# the failing validator will be set externally at whatever recursion level
|
def __init__(self, message, validator=None, path=()):
|
||||||
# is immediately above the validation failure
|
# Any validator that recurses (e.g. properties and items) must append
|
||||||
validator = None
|
# to the ValidationError's path to properly maintain where in the
|
||||||
|
# instance the error occurred
|
||||||
def __init__(self, message):
|
super(ValidationError, self).__init__(message, validator, path)
|
||||||
super(ValidationError, self).__init__(message)
|
|
||||||
self.message = message
|
self.message = message
|
||||||
|
self.path = list(path)
|
||||||
|
self.validator = validator
|
||||||
|
|
||||||
# Any validator that recurses must append to the ValidationError's
|
def __str__(self):
|
||||||
# path (e.g., properties and items)
|
return self.message
|
||||||
self.path = []
|
|
||||||
|
|
||||||
|
|
||||||
|
@validates("draft3")
|
||||||
class Draft3Validator(object):
|
class Draft3Validator(object):
|
||||||
"""
|
"""
|
||||||
A validator for JSON Schema draft 3.
|
A validator for JSON Schema draft 3.
|
||||||
@ -100,37 +128,20 @@ class Draft3Validator(object):
|
|||||||
"number" : (int, float), "object" : dict, "string" : basestring,
|
"number" : (int, float), "object" : dict, "string" : basestring,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, schema, types=()):
|
def __init__(self, schema, types=(), resolver=None):
|
||||||
"""
|
|
||||||
Initialize a validator.
|
|
||||||
|
|
||||||
``schema`` should be a *valid* JSON Schema object already converted to
|
|
||||||
a native Python object (typically a dict via ``json.load``).
|
|
||||||
|
|
||||||
``types`` is a mapping (or iterable of 2-tuples) containing additional
|
|
||||||
types or alternate types to verify via the 'type' property. For
|
|
||||||
instance, the default types for the 'number' JSON Schema type are
|
|
||||||
``int`` and ``float``. To override this behavior (e.g. for also
|
|
||||||
allowing ``decimal.Decimal``), pass ``types={"number" : (int, float,
|
|
||||||
decimal.Decimal)} *including* the default types if so desired, which
|
|
||||||
are fairly obvious but can be accessed via the ``DEFAULT_TYPES``
|
|
||||||
attribute on this class if necessary.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
self._types = dict(self.DEFAULT_TYPES)
|
self._types = dict(self.DEFAULT_TYPES)
|
||||||
self._types.update(types)
|
self._types.update(types)
|
||||||
self._types["any"] = tuple(self._types.values())
|
|
||||||
|
|
||||||
|
if resolver is None:
|
||||||
|
resolver = RefResolver.from_schema(schema)
|
||||||
|
|
||||||
|
self.resolver = resolver
|
||||||
self.schema = schema
|
self.schema = schema
|
||||||
|
|
||||||
def is_type(self, instance, type):
|
def is_type(self, instance, type):
|
||||||
"""
|
if type == "any":
|
||||||
Check if an ``instance`` is of the provided (JSON Schema) ``type``.
|
return True
|
||||||
|
elif type not in self._types:
|
||||||
"""
|
|
||||||
|
|
||||||
if type not in self._types:
|
|
||||||
raise UnknownType(type)
|
raise UnknownType(type)
|
||||||
type = self._types[type]
|
type = self._types[type]
|
||||||
|
|
||||||
@ -142,36 +153,17 @@ class Draft3Validator(object):
|
|||||||
return isinstance(instance, type)
|
return isinstance(instance, type)
|
||||||
|
|
||||||
def is_valid(self, instance, _schema=None):
|
def is_valid(self, instance, _schema=None):
|
||||||
"""
|
|
||||||
Check if the ``instance`` is valid under the current schema.
|
|
||||||
|
|
||||||
Returns a bool indicating whether validation succeeded.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
error = next(self.iter_errors(instance, _schema), None)
|
error = next(self.iter_errors(instance, _schema), None)
|
||||||
return error is None
|
return error is None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check_schema(cls, schema):
|
def check_schema(cls, schema):
|
||||||
"""
|
|
||||||
Validate a ``schema`` against the meta-schema to see if it is valid.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
for error in cls(cls.META_SCHEMA).iter_errors(schema):
|
for error in cls(cls.META_SCHEMA).iter_errors(schema):
|
||||||
s = SchemaError(error.message)
|
raise SchemaError(
|
||||||
s.path = error.path
|
error.message, validator=error.validator, path=error.path,
|
||||||
s.validator = error.validator
|
)
|
||||||
# I think we're safer raising these always, not yielding them
|
|
||||||
raise s
|
|
||||||
|
|
||||||
def iter_errors(self, instance, _schema=None):
|
def iter_errors(self, instance, _schema=None):
|
||||||
"""
|
|
||||||
Lazily yield each of the errors in the given ``instance``.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
if _schema is None:
|
if _schema is None:
|
||||||
_schema = self.schema
|
_schema = self.schema
|
||||||
|
|
||||||
@ -183,17 +175,12 @@ class Draft3Validator(object):
|
|||||||
|
|
||||||
errors = validator(v, instance, _schema) or ()
|
errors = validator(v, instance, _schema) or ()
|
||||||
for error in errors:
|
for error in errors:
|
||||||
# if the validator hasn't already been set (due to recursion)
|
# set the validator if it wasn't already set by the called fn
|
||||||
# make sure to set it
|
if error.validator is None:
|
||||||
error.validator = error.validator or k
|
error.validator = k
|
||||||
yield error
|
yield error
|
||||||
|
|
||||||
def validate(self, *args, **kwargs):
|
def validate(self, *args, **kwargs):
|
||||||
"""
|
|
||||||
Validate an ``instance`` under the given ``schema``.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
for error in self.iter_errors(*args, **kwargs):
|
for error in self.iter_errors(*args, **kwargs):
|
||||||
raise error
|
raise error
|
||||||
|
|
||||||
@ -201,21 +188,12 @@ class Draft3Validator(object):
|
|||||||
types = _list(types)
|
types = _list(types)
|
||||||
|
|
||||||
for type in types:
|
for type in types:
|
||||||
# Ouch. Brain hurts. Two paths here, either we have a schema, then
|
if self.is_type(type, "object"):
|
||||||
# check if the instance is valid under it
|
if self.is_valid(instance, type):
|
||||||
if ((
|
return
|
||||||
self.is_type(type, "object") and
|
elif self.is_type(type, "string"):
|
||||||
self.is_valid(instance, type)
|
if self.is_type(instance, type):
|
||||||
|
return
|
||||||
# Or we have a type as a string, just check if the instance is that
|
|
||||||
# type. Also, HACK: we can reach the `or` here if skip_types is
|
|
||||||
# something other than error. If so, bail out.
|
|
||||||
|
|
||||||
) or (
|
|
||||||
self.is_type(type, "string") and
|
|
||||||
(self.is_type(instance, type) or type not in self._types)
|
|
||||||
)):
|
|
||||||
return
|
|
||||||
else:
|
else:
|
||||||
yield ValidationError(_types_msg(instance, types))
|
yield ValidationError(_types_msg(instance, types))
|
||||||
|
|
||||||
@ -229,14 +207,16 @@ class Draft3Validator(object):
|
|||||||
error.path.append(property)
|
error.path.append(property)
|
||||||
yield error
|
yield error
|
||||||
elif subschema.get("required", False):
|
elif subschema.get("required", False):
|
||||||
error = ValidationError(
|
yield ValidationError(
|
||||||
"%r is a required property" % (property,)
|
"%r is a required property" % (property,),
|
||||||
|
validator="required",
|
||||||
|
path=[property],
|
||||||
)
|
)
|
||||||
error.path.append(property)
|
|
||||||
error.validator = "required"
|
|
||||||
yield error
|
|
||||||
|
|
||||||
def validate_patternProperties(self, patternProperties, instance, schema):
|
def validate_patternProperties(self, patternProperties, instance, schema):
|
||||||
|
if not self.is_type(instance, "object"):
|
||||||
|
return
|
||||||
|
|
||||||
for pattern, subschema in iteritems(patternProperties):
|
for pattern, subschema in iteritems(patternProperties):
|
||||||
for k, v in iteritems(instance):
|
for k, v in iteritems(instance):
|
||||||
if re.match(pattern, k):
|
if re.match(pattern, k):
|
||||||
@ -292,9 +272,10 @@ class Draft3Validator(object):
|
|||||||
yield error
|
yield error
|
||||||
|
|
||||||
def validate_additionalItems(self, aI, instance, schema):
|
def validate_additionalItems(self, aI, instance, schema):
|
||||||
if not self.is_type(instance, "array"):
|
if (
|
||||||
return
|
not self.is_type(instance, "array") or
|
||||||
if not self.is_type(schema.get("items"), "array"):
|
not self.is_type(schema.get("items"), "array")
|
||||||
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.is_type(aI, "object"):
|
if self.is_type(aI, "object"):
|
||||||
@ -397,11 +378,7 @@ class Draft3Validator(object):
|
|||||||
yield error
|
yield error
|
||||||
|
|
||||||
def validate_ref(self, ref, instance, schema):
|
def validate_ref(self, ref, instance, schema):
|
||||||
if ref != "#" and not ref.startswith("#/"):
|
resolved = self.resolver.resolve(ref)
|
||||||
warnings.warn("jsonschema only supports json-pointer $refs")
|
|
||||||
return
|
|
||||||
|
|
||||||
resolved = resolve_json_pointer(self.schema, ref)
|
|
||||||
for error in self.iter_errors(instance, resolved):
|
for error in self.iter_errors(instance, resolved):
|
||||||
yield error
|
yield error
|
||||||
|
|
||||||
@ -490,22 +467,89 @@ Draft3Validator.META_SCHEMA = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class Validator(Draft3Validator):
|
class RefResolver(object):
|
||||||
"""
|
"""
|
||||||
Deprecated: Use :class:`Draft3Validator` instead.
|
Resolve JSON References.
|
||||||
|
|
||||||
|
:argument str base_uri: URI of the referring document
|
||||||
|
:argument referrer: the actual referring document
|
||||||
|
:argument dict store: a mapping from URIs to documents to cache
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, base_uri, referrer, store=()):
|
||||||
self, version=None, unknown_type="skip", unknown_property="skip",
|
self.base_uri = base_uri
|
||||||
*args, **kwargs
|
self.referrer = referrer
|
||||||
):
|
self.store = dict(store, **_meta_schemas())
|
||||||
super(Validator, self).__init__({}, *args, **kwargs)
|
|
||||||
warnings.warn(
|
@classmethod
|
||||||
"Validator is deprecated and will be removed. "
|
def from_schema(cls, schema, *args, **kwargs):
|
||||||
"Use Draft3Validator instead.",
|
"""
|
||||||
DeprecationWarning, stacklevel=2,
|
Construct a resolver from a JSON schema object.
|
||||||
)
|
|
||||||
|
:argument schema schema: the referring schema
|
||||||
|
:rtype: :class:`RefResolver`
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
return cls(schema.get("id", ""), schema, *args, **kwargs)
|
||||||
|
|
||||||
|
def resolve(self, ref):
|
||||||
|
"""
|
||||||
|
Resolve a JSON ``ref``.
|
||||||
|
|
||||||
|
:argument str ref: reference to resolve
|
||||||
|
:returns: the referrant document
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
base_uri = self.base_uri
|
||||||
|
uri, fragment = urlparse.urldefrag(urlparse.urljoin(base_uri, ref))
|
||||||
|
|
||||||
|
if uri in self.store:
|
||||||
|
document = self.store[uri]
|
||||||
|
elif not uri or uri == self.base_uri:
|
||||||
|
document = self.referrer
|
||||||
|
else:
|
||||||
|
document = self.resolve_remote(uri)
|
||||||
|
|
||||||
|
return self.resolve_fragment(document, fragment.lstrip("/"))
|
||||||
|
|
||||||
|
def resolve_fragment(self, document, fragment):
|
||||||
|
"""
|
||||||
|
Resolve a ``fragment`` within the referenced ``document``.
|
||||||
|
|
||||||
|
:argument document: the referrant document
|
||||||
|
:argument str fragment: a URI fragment to resolve within it
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
parts = unquote(fragment).split("/") if fragment else []
|
||||||
|
|
||||||
|
for part in parts:
|
||||||
|
part = part.replace("~1", "/").replace("~0", "~")
|
||||||
|
|
||||||
|
if part not in document:
|
||||||
|
raise RefResolutionError(
|
||||||
|
"Unresolvable JSON pointer: %r" % fragment
|
||||||
|
)
|
||||||
|
|
||||||
|
document = document[part]
|
||||||
|
|
||||||
|
return document
|
||||||
|
|
||||||
|
def resolve_remote(self, uri):
|
||||||
|
"""
|
||||||
|
Resolve a remote ``uri``.
|
||||||
|
|
||||||
|
Does not check the store first.
|
||||||
|
|
||||||
|
:argument str uri: the URI to resolve
|
||||||
|
:returns: the retrieved document
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
return json.load(urlopen(uri))
|
||||||
|
|
||||||
|
|
||||||
class ErrorTree(object):
|
class ErrorTree(object):
|
||||||
@ -528,6 +572,11 @@ class ErrorTree(object):
|
|||||||
return k in self._contents
|
return k in self._contents
|
||||||
|
|
||||||
def __getitem__(self, k):
|
def __getitem__(self, k):
|
||||||
|
"""
|
||||||
|
Retrieve the child tree with key ``k``.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
return self._contents[k]
|
return self._contents[k]
|
||||||
|
|
||||||
def __setitem__(self, k, v):
|
def __setitem__(self, k, v):
|
||||||
@ -537,36 +586,30 @@ class ErrorTree(object):
|
|||||||
return iter(self._contents)
|
return iter(self._contents)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
|
return self.total_errors
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<%s (%s total errors)>" % (self.__class__.__name__, len(self))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def total_errors(self):
|
||||||
|
"""
|
||||||
|
The total number of errors in the entire tree, including children.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
child_errors = sum(len(tree) for _, tree in iteritems(self._contents))
|
child_errors = sum(len(tree) for _, tree in iteritems(self._contents))
|
||||||
return len(self.errors) + child_errors
|
return len(self.errors) + child_errors
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return "<%s (%s errors)>" % (self.__class__.__name__, len(self))
|
|
||||||
|
|
||||||
|
def _meta_schemas():
|
||||||
def resolve_json_pointer(schema, ref):
|
|
||||||
"""
|
"""
|
||||||
Resolve a local reference ``ref`` within the given root ``schema``.
|
Collect the urls and meta schemas from each known validator.
|
||||||
|
|
||||||
``ref`` should be a local ref whose ``#`` is still present.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if ref == "#":
|
meta_schemas = (v.META_SCHEMA for v in validators.values())
|
||||||
return schema
|
return dict((urlparse.urldefrag(m["id"])[0], m) for m in meta_schemas)
|
||||||
|
|
||||||
parts = ref.lstrip("#/").split("/")
|
|
||||||
|
|
||||||
parts = map(unquote, parts)
|
|
||||||
parts = [part.replace('~1', '/').replace('~0', '~') for part in parts]
|
|
||||||
|
|
||||||
try:
|
|
||||||
for part in parts:
|
|
||||||
schema = schema[part]
|
|
||||||
except KeyError:
|
|
||||||
raise InvalidRef("Unresolvable json-pointer %r" % ref)
|
|
||||||
else:
|
|
||||||
return schema
|
|
||||||
|
|
||||||
|
|
||||||
def _find_additional_properties(instance, schema):
|
def _find_additional_properties(instance, schema):
|
||||||
@ -675,6 +718,19 @@ def _delist(thing):
|
|||||||
return thing
|
return thing
|
||||||
|
|
||||||
|
|
||||||
|
def _unbool(element, true=object(), false=object()):
|
||||||
|
"""
|
||||||
|
A hack to make True and 1 and False and 0 unique for _uniq.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
if element is True:
|
||||||
|
return true
|
||||||
|
elif element is False:
|
||||||
|
return false
|
||||||
|
return element
|
||||||
|
|
||||||
|
|
||||||
def _uniq(container):
|
def _uniq(container):
|
||||||
"""
|
"""
|
||||||
Check if all of a container's elements are unique.
|
Check if all of a container's elements are unique.
|
||||||
@ -686,17 +742,18 @@ def _uniq(container):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return len(set(container)) == len(container)
|
return len(set(_unbool(i) for i in container)) == len(container)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
try:
|
try:
|
||||||
sort = sorted(container)
|
sort = sorted(_unbool(i) for i in container)
|
||||||
sliced = itertools.islice(container, 1, None)
|
sliced = itertools.islice(sort, 1, None)
|
||||||
for i, j in zip(container, sliced):
|
for i, j in zip(sort, sliced):
|
||||||
if i == j:
|
if i == j:
|
||||||
return False
|
return False
|
||||||
except (NotImplementedError, TypeError):
|
except (NotImplementedError, TypeError):
|
||||||
seen = []
|
seen = []
|
||||||
for e in container:
|
for e in container:
|
||||||
|
e = _unbool(e)
|
||||||
if e in seen:
|
if e in seen:
|
||||||
return False
|
return False
|
||||||
seen.append(e)
|
seen.append(e)
|
||||||
@ -707,28 +764,29 @@ def validate(instance, schema, cls=Draft3Validator, *args, **kwargs):
|
|||||||
"""
|
"""
|
||||||
Validate an ``instance`` under the given ``schema``.
|
Validate an ``instance`` under the given ``schema``.
|
||||||
|
|
||||||
First verifies that the provided schema is itself valid, since not doing so
|
>>> validate([2, 3, 4], {"maxItems" : 2})
|
||||||
can lead to less obvious failures when validating. If you know it is or
|
Traceback (most recent call last):
|
||||||
don't care, use ``YourValidator(schema).validate(instance)`` directly
|
...
|
||||||
instead (e.g. ``Draft3Validator``).
|
ValidationError: [2, 3, 4] is too long
|
||||||
|
|
||||||
|
:func:`validate` will first verify that the provided schema is itself
|
||||||
|
valid, since not doing so can lead to less obvious error messages and fail
|
||||||
|
in less obvious or consistent ways. If you know you have a valid schema
|
||||||
|
already or don't care, you might prefer using the ``validate`` method
|
||||||
|
directly on a specific validator (e.g. :meth:`Draft3Validator.validate`).
|
||||||
|
|
||||||
``cls`` is a validator class that will be used to validate the instance.
|
``cls`` is a validator class that will be used to validate the instance.
|
||||||
By default this is a draft 3 validator. Any other provided positional and
|
By default this is a draft 3 validator. Any other provided positional and
|
||||||
keyword arguments will be provided to this class when constructing a
|
keyword arguments will be provided to this class when constructing a
|
||||||
validator.
|
validator.
|
||||||
|
|
||||||
|
:raises:
|
||||||
|
:exc:`ValidationError` if the instance is invalid
|
||||||
|
|
||||||
|
:exc:`SchemaError` if the schema itself is invalid
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
meta_validate = kwargs.pop("meta_validate", None)
|
cls.check_schema(schema)
|
||||||
|
|
||||||
if meta_validate is not None:
|
|
||||||
warnings.warn(
|
|
||||||
"meta_validate is deprecated and will be removed. If you do not "
|
|
||||||
"want to validate a schema, use Draft3Validator.validate instead.",
|
|
||||||
DeprecationWarning, stacklevel=2,
|
|
||||||
)
|
|
||||||
|
|
||||||
if meta_validate is not False: # yes this is needed since True was default
|
|
||||||
cls.check_schema(schema)
|
|
||||||
cls(schema, *args, **kwargs).validate(instance)
|
cls(schema, *args, **kwargs).validate(instance)
|
||||||
|
Loading…
Reference in New Issue
Block a user