Refactor Hyperion JSON-API (#1727)

This commit is contained in:
LordGrey
2024-05-08 22:06:32 +02:00
committed by GitHub
parent 94850d890a
commit cf287f5adb
64 changed files with 4203 additions and 2962 deletions

View File

@@ -14,11 +14,15 @@
// qt includes
#include <QString>
class QTimer;
class JsonCB;
class JsonCallbacks;
class HyperionIManager;
const QString NO_AUTH = "No Authorization";
// Constants
namespace {
const char NO_AUTHORIZATION[] = "No Authorization";;
}
///
/// @brief API for Hyperion to be inherted from a child class with specific protocol implementations
@@ -31,205 +35,214 @@ const QString NO_AUTH = "No Authorization";
class API : public QObject
{
Q_OBJECT
Q_OBJECT
public:
#include <api/apiStructs.h>
// workaround Q_ARG std::map template issues
typedef std::map<int, registerData> MapRegister;
typedef QMap<QString, AuthManager::AuthDefinition> MapAuthDefs;
///
/// Constructor
///
///@ param The parent Logger
/// @param localConnection Is this a local network connection? Use utils/NetOrigin to check that
/// @param parent Parent QObject
///
API(Logger *log, bool localConnection, QObject *parent);
protected:
///
/// @brief Initialize the API
/// This call is REQUIRED!
///
void init();
///
/// @brief Set a single color
/// @param[in] priority The priority of the written color
/// @param[in] ledColor The color to write to the leds
/// @param[in] timeout_ms The time the leds are set to the given color [ms]
/// @param[in] origin The setter
///
void setColor(int priority, const std::vector<uint8_t> &ledColors, int timeout_ms = -1, const QString &origin = "API", hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set a image
/// @param[in] data The command data
/// @param[in] comp The component that should be used
/// @param[out] replyMsg The replyMsg on failure
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// @return True on success
///
bool setImage(ImageCmdData &data, hyperion::Components comp, QString &replyMsg, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Clear a priority in the Muxer, if -1 all priorities are cleared
/// @param priority The priority to clear
/// @param replyMsg the message on failure
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// @return True on success
///
bool clearPriority(int priority, QString &replyMsg, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set a new component state
/// @param comp The component name
/// @param compState The new state of the comp
/// @param replyMsg The reply on failure
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// @ return True on success
///
bool setComponentState(const QString &comp, bool &compState, QString &replyMsg, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set a ledToImageMapping type
/// @param type mapping type string
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setLedMappingType(int type, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set the 2D/3D modes type
/// @param mode The VideoMode
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setVideoMode(VideoMode mode, hyperion::Components callerComp = hyperion::COMP_INVALID);
#if defined(ENABLE_EFFECTENGINE)
///
/// @brief Set an effect
/// @param dat The effect data
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// REQUIRED dat fields: effectName, priority, duration, origin
/// @return True on success else false
///
bool setEffect(const EffectCmdData &dat, hyperion::Components callerComp = hyperion::COMP_INVALID);
#endif
///
/// @brief Set source auto select enabled or disabled
/// @param sate The new state
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setSourceAutoSelect(bool state, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set the visible priority to given priority
/// @param priority The priority to set
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setVisiblePriority(int priority, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Register a input or update the meta data of a previous register call
/// ATTENTION: Check unregisterInput() method description !!!
/// @param[in] priority The priority of the channel
/// @param[in] component The component of the channel
/// @param[in] origin Who set the channel (CustomString@IP)
/// @param[in] owner Specific owner string, might be empty
/// @param[in] callerComp The component that call this (e.g. PROTO/FLAT)
///
void registerInput(int priority, hyperion::Components component, const QString &origin, const QString &owner, hyperion::Components callerComp);
///
/// @brief Revoke a registerInput() call by priority. We maintain all registered priorities in this scope
/// ATTENTION: This is MANDATORY if you change (priority change) or stop(clear/timeout) DURING lifetime. If this class destructs it's not needed
/// @param priority The priority to unregister
///
void unregisterInput(int priority);
///
/// @brief Handle the instance switching
/// @param inst The requested instance
/// @return True on success else false
///
bool setHyperionInstance(quint8 inst);
// workaround Q_ARG std::map template issues
typedef std::map<int, registerData> MapRegister;
typedef QMap<QString, AuthManager::AuthDefinition> MapAuthDefs;
///
/// @brief Check if Hyperion ist enabled
/// @return True when enabled else false
///
bool isHyperionEnabled();
/// Constructor
///
///@ param The parent Logger
/// @param localConnection Is this a local network connection? Use utils/NetOrigin to check that
/// @param parent Parent QObject
///
API(Logger *log, bool localConnection, QObject *parent);
///
/// @brief Get all instances data
/// @return The instance data
///
QVector<QVariantMap> getAllInstanceData();
protected:
///
/// @brief Initialize the API
/// This call is REQUIRED!
///
void init();
///
/// @brief Start instance
/// @param index The instance index
/// @param tan The tan
/// @return True on success else false
///
bool startInstance(quint8 index, int tan = 0);
virtual void stopDataConnections() = 0;
///
/// @brief Stop instance
/// @param index The instance index
///
void stopInstance(quint8 index);
///
/// @brief Set a single color
/// @param[in] priority The priority of the written color
/// @param[in] ledColor The color to write to the leds
/// @param[in] timeout_ms The time the leds are set to the given color [ms]
/// @param[in] origin The setter
///
void setColor(int priority, const std::vector<uint8_t> &ledColors, int timeout_ms = -1, const QString &origin = "API", hyperion::Components callerComp = hyperion::COMP_INVALID);
//////////////////////////////////
/// AUTH / ADMINISTRATION METHODS
//////////////////////////////////
///
/// @brief Set a image
/// @param[in] data The command data
/// @param[in] comp The component that should be used
/// @param[out] replyMsg The replyMsg on failure
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// @return True on success
///
bool setImage(ImageCmdData &data, hyperion::Components comp, QString &replyMsg, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Delete instance. Requires ADMIN ACCESS
/// @param index The instance index
/// @param replyMsg The reply Msg
/// @return False with reply
///
bool deleteInstance(quint8 index, QString &replyMsg);
///
/// @brief Clear a priority in the Muxer, if -1 all priorities are cleared
/// @param priority The priority to clear
/// @param replyMsg the message on failure
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// @return True on success
///
bool clearPriority(int priority, QString &replyMsg, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Create instance. Requires ADMIN ACCESS
/// @param name With given name
/// @return False with reply
///
QString createInstance(const QString &name);
///
/// @brief Set a new component state
/// @param comp The component name
/// @param compState The new state of the comp
/// @param replyMsg The reply on failure
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// @ return True on success
///
bool setComponentState(const QString &comp, bool &compState, QString &replyMsg, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Rename an instance. Requires ADMIN ACCESS
/// @param index The instance index
/// @param name With given name
/// @return False with reply
///
QString setInstanceName(quint8 index, const QString &name);
///
/// @brief Set a ledToImageMapping type
/// @param type mapping type string
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setLedMappingType(int type, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set the 2D/3D modes type
/// @param mode The VideoMode
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setVideoMode(VideoMode mode, hyperion::Components callerComp = hyperion::COMP_INVALID);
#if defined(ENABLE_EFFECTENGINE)
///
/// @brief Delete an effect. Requires ADMIN ACCESS
/// @param name The effect name
/// @return True on success else false
///
QString deleteEffect(const QString &name);
///
/// @brief Delete an effect. Requires ADMIN ACCESS
/// @param name The effect name
/// @return True on success else false
///
QString saveEffect(const QJsonObject &data);
///
/// @brief Set an effect
/// @param dat The effect data
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
/// REQUIRED dat fields: effectName, priority, duration, origin
/// @return True on success else false
///
bool setEffect(const EffectCmdData &dat, hyperion::Components callerComp = hyperion::COMP_INVALID);
#endif
///
/// @brief Save settings object. Requires ADMIN ACCESS
/// @param data The data object
///
///
/// @brief Set source auto select enabled or disabled
/// @param sate The new state
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setSourceAutoSelect(bool state, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Set the visible priority to given priority
/// @param priority The priority to set
/// @param callerComp The HYPERION COMPONENT that calls this function! e.g. PROT/FLATBUF
///
void setVisiblePriority(int priority, hyperion::Components callerComp = hyperion::COMP_INVALID);
///
/// @brief Register a input or update the meta data of a previous register call
/// ATTENTION: Check unregisterInput() method description !!!
/// @param[in] priority The priority of the channel
/// @param[in] component The component of the channel
/// @param[in] origin Who set the channel (CustomString@IP)
/// @param[in] owner Specific owner string, might be empty
/// @param[in] callerComp The component that call this (e.g. PROTO/FLAT)
///
void registerInput(int priority, hyperion::Components component, const QString &origin, const QString &owner, hyperion::Components callerComp);
///
/// @brief Revoke a registerInput() call by priority. We maintain all registered priorities in this scope
/// ATTENTION: This is MANDATORY if you change (priority change) or stop(clear/timeout) DURING lifetime. If this class destructs it's not needed
/// @param priority The priority to unregister
///
void unregisterInput(int priority);
///
/// @brief Handle the instance switching
/// @param inst The requested instance
/// @return True on success else false
///
bool setHyperionInstance(quint8 inst);
///
/// @brief Check if Hyperion ist enabled
/// @return True when enabled else false
///
bool isHyperionEnabled();
///
/// @brief Get all instances data
/// @return The instance data
///
QVector<QVariantMap> getAllInstanceData() const;
///
/// @brief Get the current instances index
/// @return The instance index set
///
quint8 getCurrentInstanceIndex() const { return _currInstanceIndex; }
///
/// @brief Start instance
/// @param index The instance index
/// @param tan The tan
/// @return True on success else false
///
bool startInstance(quint8 index, int tan = 0);
///
/// @brief Stop instance
/// @param index The instance index
///
void stopInstance(quint8 index);
//////////////////////////////////
/// AUTH / ADMINISTRATION METHODS
//////////////////////////////////
///
/// @brief Delete instance. Requires ADMIN ACCESS
/// @param index The instance index
/// @param replyMsg The reply Msg
/// @return False with reply
///
bool deleteInstance(quint8 index, QString &replyMsg);
///
/// @brief Create instance. Requires ADMIN ACCESS
/// @param name With given name
/// @return False with reply
///
QString createInstance(const QString &name);
///
/// @brief Rename an instance. Requires ADMIN ACCESS
/// @param index The instance index
/// @param name With given name
/// @return False with reply
///
QString setInstanceName(quint8 index, const QString &name);
#if defined(ENABLE_EFFECTENGINE)
///
/// @brief Delete an effect. Requires ADMIN ACCESS
/// @param name The effect name
/// @return True on success else false
///
QString deleteEffect(const QString &name);
///
/// @brief Delete an effect. Requires ADMIN ACCESS
/// @param name The effect name
/// @return True on success else false
///
QString saveEffect(const QJsonObject &data);
#endif
///
/// @brief Save settings object. Requires ADMIN ACCESS
/// @param data The data object
///
bool saveSettings(const QJsonObject &data);
///
@@ -238,171 +251,189 @@ protected:
///
bool restoreSettings(const QJsonObject &data);
///
/// @brief Test if we are authorized to use the interface
/// @return The result
///
bool isAuthorized() { return _authorized; };
///
/// @brief Set the authorizationn state
/// @param authorized True, if authorized
///
void setAuthorization(bool authorized) { _authorized = authorized; }
///
/// @brief Test if we are authorized to use the admin interface
/// @return The result
///
bool isAdminAuthorized() { return _adminAuthorized; };
///
/// @brief Test if we are authorized to use the interface
/// @return The result
///
bool isAuthorized() const { return _authorized; }
///
/// @brief Update the Password of Hyperion. Requires ADMIN ACCESS
/// @param password Old password
/// @param newPassword New password
/// @return True on success else false
///
bool updateHyperionPassword(const QString &password, const QString &newPassword);
///
/// @brief Set the authorizationn state for admin activities
/// @param authorized True, if authorized
///
void setAdminAuthorization(bool adminAuthorized) { _adminAuthorized = adminAuthorized; }
///
/// @brief Get a new token from AuthManager. Requires ADMIN ACCESS
/// @param comment The comment of the request
/// @param def The final definition
/// @return Empty string on success else error message
///
QString createToken(const QString &comment, AuthManager::AuthDefinition &def);
///
/// @brief Test if we are authorized to use admin activites
/// @return The result
///
bool isAdminAuthorized() const { return _adminAuthorized; }
///
/// @brief Rename a token by given id. Requires ADMIN ACCESS
/// @param id The id of the token
/// @param comment The new comment
/// @return Empty string on success else error message
///
QString renameToken(const QString &id, const QString &comment);
///
/// @brief Return, if connection is from local network segment
/// @return The result
///
bool islocalConnection() const { return _localConnection; }
///
/// @brief Delete a token by given id. Requires ADMIN ACCESS
/// @param id The id of the token
/// @return Empty string on success else error message
///
QString deleteToken(const QString &id);
///
/// @brief Update the Password of Hyperion. Requires ADMIN ACCESS
/// @param password Old password
/// @param newPassword New password
/// @return True on success else false
///
bool updateHyperionPassword(const QString &password, const QString &newPassword);
///
/// @brief Set a new token request
/// @param comment The comment
/// @param id The id
///
/// @brief Get a new token from AuthManager. Requires ADMIN ACCESS
/// @param comment The comment of the request
/// @param def The final definition
/// @return Empty string on success else error message
///
QString createToken(const QString &comment, AuthManager::AuthDefinition &def);
///
/// @brief Rename a token by given id. Requires ADMIN ACCESS
/// @param tokenId The id of the token
/// @param comment The new comment
/// @return Empty string on success else error message
///
QString renameToken(const QString &tokenId, const QString &comment);
///
/// @brief Delete a token by given id. Requires ADMIN ACCESS
/// @param tokenId The id of the token
/// @return Empty string on success else error message
///
QString deleteToken(const QString &tokenId);
///
/// @brief Set a new token request
/// @param comment The comment
/// @param tokenId The id of the token
/// @param tan The tan
///
void setNewTokenRequest(const QString &comment, const QString &id, const int &tan);
///
void setNewTokenRequest(const QString &comment, const QString &tokenId, const int &tan);
///
/// @brief Cancel new token request
/// @param comment The comment
/// @param id The id
///
void cancelNewTokenRequest(const QString &comment, const QString &id);
///
/// @brief Cancel new token request
/// @param comment The comment
/// @param tokenId The id of the token
///
void cancelNewTokenRequest(const QString &comment, const QString &tokenId);
///
/// @brief Handle a pending token request. Requires ADMIN ACCESS
/// @param id The id fo the request
/// @param accept True when it should be accepted, else false
/// @return True on success
bool handlePendingTokenRequest(const QString &id, bool accept);
///
/// @brief Get the current List of Tokens. Requires ADMIN ACCESS
/// @param def returns the defintions
/// @return True on success
///
bool getTokenList(QVector<AuthManager::AuthDefinition> &def);
///
/// @brief Get all current pending token requests. Requires ADMIN ACCESS
/// @return True on success
///
bool getPendingTokenRequests(QVector<AuthManager::AuthDefinition> &map);
///
/// @brief Is User Token Authorized. On success this will grant acces to API and ADMIN API
/// @param userToken The user Token
/// @return True on succes
///
bool isUserTokenAuthorized(const QString &userToken);
///
/// @brief Get the current User Token (session token). Requires ADMIN ACCESS
/// @param userToken The user Token
/// @return True on success
///
bool getUserToken(QString &userToken);
///
/// @brief Is a token authorized. On success this will grant acces to the API (NOT ADMIN API)
/// @param token The user Token
///
/// @brief Handle a pending token request. Requires ADMIN ACCESS
/// @param tokenId The id fo the request
/// @param accept True when it should be accepted, else false
/// @return True on success
///
bool isTokenAuthorized(const QString &token);
bool handlePendingTokenRequest(const QString &tokenId, bool accept);
///
/// @brief Is User authorized. On success this will grant acces to the API and ADMIN API
/// @param password The password of the User
/// @return True if authorized
///
bool isUserAuthorized(const QString &password);
///
/// @brief Get the current List of Tokens. Requires ADMIN ACCESS
/// @param def returns the defintions
/// @return True on success
///
bool getTokenList(QVector<AuthManager::AuthDefinition> &def);
///
/// @brief Test if Hyperion has the default PW
/// @return The result
///
bool hasHyperionDefaultPw();
///
/// @brief Get all current pending token requests. Requires ADMIN ACCESS
/// @return True on success
///
bool getPendingTokenRequests(QVector<AuthManager::AuthDefinition> &map);
///
/// @brief Logout revokes all authorizations
///
void logout();
///
/// @brief Is User Token Authorized. On success this will grant acces to API and ADMIN API
/// @param userToken The user Token
/// @return True on succes
///
bool isUserTokenAuthorized(const QString &userToken);
/// Reflect auth status of this client
bool _authorized;
bool _adminAuthorized;
///
/// @brief Get the current User Token (session token). Requires ADMIN ACCESS
/// @param userToken The user Token
/// @return True on success
///
bool getUserToken(QString &userToken);
/// Is this a local connection
bool _localConnection;
///
/// @brief Is a token authorized. On success this will grant acces to the API (NOT ADMIN API)
/// @param token The user Token
/// @return True on success
///
bool isTokenAuthorized(const QString &token);
AuthManager *_authManager;
HyperionIManager *_instanceManager;
///
/// @brief Is User authorized. On success this will grant acces to the API and ADMIN API
/// @param password The password of the User
/// @return True if authorized
///
bool isUserAuthorized(const QString &password);
Logger *_log;
Hyperion *_hyperion;
///
/// @brief Test if Hyperion has the default PW
/// @return The result
///
bool hasHyperionDefaultPw();
///
/// @brief Logout revokes all authorizations
///
void logout();
AuthManager *_authManager;
HyperionIManager *_instanceManager;
Logger *_log;
Hyperion *_hyperion;
signals:
///
/// @brief The API might decide to block connections for security reasons, this emitter should close the socket
///
void forceClose();
///
/// @brief The API might decide to block connections for security reasons, this emitter should close the socket
///
void forceClose();
///
/// @brief Emits whenever a new Token request is pending. This signal is just active when ADMIN ACCESS has been granted
/// @param id The id of the request
/// @param comment The comment of the request; If the commen is EMPTY the request has been revoked by the caller. So remove it from the pending list
///
void onPendingTokenRequest(const QString &id, const QString &comment);
///
/// @brief Emits whenever a new Token request is pending. This signal is just active when ADMIN ACCESS has been granted
/// @param tokenId The id of the request
/// @param comment The comment of the request; If the commen is EMPTY the request has been revoked by the caller. So remove it from the pending list
///
void onPendingTokenRequest(const QString &tokenId, const QString &comment);
///
/// @brief Handle emits from AuthManager of accepted/denied/timeouts token request, just if QObject matches with this instance it will emit.
/// @param success If true the request was accepted else false and no token was created
/// @param token The new token that is now valid
/// @param comment The comment that was part of the request
/// @param id The id that was part of the request
/// @param tan The tan that was part of the request
///
void onTokenResponse(bool success, const QString &token, const QString &comment, const QString &id, const int &tan);
///
/// @brief Handle emits from AuthManager of accepted/denied/timeouts token request, just if QObject matches with this instance it will emit.
/// @param success If true the request was accepted else false and no token was created
/// @param token The new token that is now valid
/// @param comment The comment that was part of the request
/// @param tokenId The id that was part of the request
/// @param tan The tan that was part of the request
///
void onTokenResponse(bool success, const QString &token, const QString &comment, const QString &tokenId, const int &tan);
///
/// @brief Handle emits from HyperionIManager of startInstance request, just if QObject matches with this instance it will emit.
/// @param tan The tan that was part of the request
///
void onStartInstanceResponse(const int &tan);
///
/// @brief Handle emits from HyperionIManager of startInstance request, just if QObject matches with this instance it will emit.
/// @param tan The tan that was part of the request
///
void onStartInstanceResponse(const int &tan);
private:
void stopDataConnectionss();
// Contains all active register call data
std::map<int, registerData> _activeRegisters;
/// Reflect authorization status of this client
bool _authorized;
bool _adminAuthorized;
// current instance index
quint8 _currInstanceIndex;
/// Is this a local connection
bool _localConnection;
// Contains all active register call data
std::map<int, registerData> _activeRegisters;
// current instance index
quint8 _currInstanceIndex;
};

View File

@@ -2,19 +2,24 @@
// parent class
#include <api/API.h>
#include <api/JsonApiCommand.h>
#include <events/EventEnum.h>
// hyperion includes
#include <utils/Components.h>
#include <hyperion/Hyperion.h>
#include <hyperion/HyperionIManager.h>
#include <utils/RgbChannelAdjustment.h>
// qt includes
#include <QJsonObject>
#include <QString>
#include <QSharedPointer>
#include <QScopedPointer>
class QTimer;
class JsonCB;
class JsonCallbacks;
class AuthManager;
class JsonAPI : public API
@@ -46,40 +51,24 @@ public:
void initialize();
public slots:
///
/// @brief Is called whenever the current Hyperion instance pushes new led raw values (if enabled)
/// @param ledColors The current led colors
///
void streamLedcolorsUpdate(const std::vector<ColorRgb> &ledColors);
///
/// @brief Push images whenever hyperion emits (if enabled)
/// @param image The current image
///
void setImage(const Image<ColorRgb> &image);
///
/// @brief Process and push new log messages from logger (if enabled)
///
void incommingLogMessage(const Logger::T_LOG_MESSAGE &);
private slots:
///
/// @brief Handle emits from API of a new Token request.
/// @param id The id of the request
/// @param identifier The identifier of the request
/// @param comment The comment which needs to be accepted
///
void newPendingTokenRequest(const QString &id, const QString &comment);
void issueNewPendingTokenRequest(const QString &identifier, const QString &comment);
///
/// @brief Handle emits from AuthManager of accepted/denied/timeouts token request, just if QObject matches with this instance we are allowed to send response.
/// @param success If true the request was accepted else false and no token was created
/// @param token The new token that is now valid
/// @param comment The comment that was part of the request
/// @param id The id that was part of the request
/// @param identifier The identifier that was part of the request
/// @param tan The tan that was part of the request
///
void handleTokenResponse(bool success, const QString &token, const QString &comment, const QString &id, const int &tan);
void handleTokenResponse(bool success, const QString &token, const QString &comment, const QString &identifier, const int &tan);
///
/// @brief Handle whenever the state of a instance (HyperionIManager) changes according to enum instanceState
@@ -89,11 +78,6 @@ private slots:
///
void handleInstanceStateChange(InstanceState state, quint8 instance, const QString &name = QString());
///
/// @brief Stream a new LED Colors update
///
void streamLedColorsUpdate();
signals:
///
/// Signal emits with the reply message provided with handleMessage()
@@ -111,31 +95,9 @@ signals:
void signalEvent(Event event);
private:
// true if further callbacks are forbidden (http)
bool _noListener;
/// The peer address of the client
QString _peerAddress;
// The JsonCB instance which handles data subscription/notifications
JsonCB *_jsonCB;
// streaming buffers
QJsonObject _streaming_leds_reply;
QJsonObject _streaming_image_reply;
QJsonObject _streaming_logging_reply;
/// flag to determine state of log streaming
bool _streaming_logging_activated;
/// timer for led color refresh
QTimer *_ledStreamTimer;
/// led stream connection handle
QMetaObject::Connection _ledStreamConnection;
/// the current streaming led values
std::vector<ColorRgb> _currentLedValues;
void handleCommand(const JsonApiCommand& cmd, const QJsonObject &message);
void handleInstanceCommand(const JsonApiCommand& cmd, const QJsonObject &message);
///
/// @brief Handle the switches of Hyperion instances
@@ -150,14 +112,14 @@ private:
///
/// @param message the incoming message
///
void handleColorCommand(const QJsonObject &message, const QString &command, int tan);
void handleColorCommand(const QJsonObject& message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Image message
///
/// @param message the incoming message
///
void handleImageCommand(const QJsonObject &message, const QString &command, int tan);
void handleImageCommand(const QJsonObject &message, const JsonApiCommand& cmd);
#if defined(ENABLE_EFFECTENGINE)
///
@@ -165,21 +127,21 @@ private:
///
/// @param message the incoming message
///
void handleEffectCommand(const QJsonObject &message, const QString &command, int tan);
void handleEffectCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Effect message (Write JSON Effect)
///
/// @param message the incoming message
///
void handleCreateEffectCommand(const QJsonObject &message, const QString &command, int tan);
void handleCreateEffectCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Effect message (Delete JSON Effect)
///
/// @param message the incoming message
///
void handleDeleteEffectCommand(const QJsonObject &message, const QString &command, int tan);
void handleDeleteEffectCommand(const QJsonObject &message, const JsonApiCommand& cmd);
#endif
///
@@ -187,158 +149,250 @@ private:
///
/// @param message the incoming message
///
void handleSysInfoCommand(const QJsonObject &message, const QString &command, int tan);
void handleSysInfoCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Server info message
///
/// @param message the incoming message
///
void handleServerInfoCommand(const QJsonObject &message, const QString &command, int tan);
void handleServerInfoCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Clear message
///
/// @param message the incoming message
///
void handleClearCommand(const QJsonObject &message, const QString &command, int tan);
void handleClearCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Clearall message
///
/// @param message the incoming message
///
void handleClearallCommand(const QJsonObject &message, const QString &command, int tan);
void handleClearallCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Adjustment message
///
/// @param message the incoming message
///
void handleAdjustmentCommand(const QJsonObject &message, const QString &command, int tan);
void handleAdjustmentCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON SourceSelect message
///
/// @param message the incoming message
///
void handleSourceSelectCommand(const QJsonObject &message, const QString &command, int tan);
void handleSourceSelectCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON GetConfig message and check subcommand
///
/// @param message the incoming message
///
void handleConfigCommand(const QJsonObject &message, const QString &command, int tan);
void handleConfigCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON GetSchema message from handleConfigCommand()
///
/// @param message the incoming message
///
void handleSchemaGetCommand(const QJsonObject &message, const QString &command, int tan);
void handleSchemaGetCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON SetConfig message from handleConfigCommand()
///
/// @param message the incoming message
///
void handleConfigSetCommand(const QJsonObject &message, const QString &command, int tan);
void handleConfigSetCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON RestoreConfig message from handleConfigCommand()
///
/// @param message the incoming message
///
void handleConfigRestoreCommand(const QJsonObject &message, const QString &command, int tan);
void handleConfigRestoreCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON Component State message
///
/// @param message the incoming message
///
void handleComponentStateCommand(const QJsonObject &message, const QString &command, int tan);
void handleComponentStateCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON Led Colors message
///
/// @param message the incoming message
///
void handleLedColorsCommand(const QJsonObject &message, const QString &command, int tan);
void handleLedColorsCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON Logging message
///
/// @param message the incoming message
///
void handleLoggingCommand(const QJsonObject &message, const QString &command, int tan);
void handleLoggingCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON Processing message
///
/// @param message the incoming message
///
void handleProcessingCommand(const QJsonObject &message, const QString &command, int tan);
void handleProcessingCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON VideoMode message
///
/// @param message the incoming message
///
void handleVideoModeCommand(const QJsonObject &message, const QString &command, int tan);
void handleVideoModeCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON plugin message
///
/// @param message the incoming message
///
void handleAuthorizeCommand(const QJsonObject &message, const QString &command, int tan);
void handleAuthorizeCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON instance message
///
/// @param message the incoming message
///
void handleInstanceCommand(const QJsonObject &message, const QString &command, int tan);
void handleInstanceCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON Led Device message
///
/// @param message the incoming message
///
void handleLedDeviceCommand(const QJsonObject &message, const QString &command, int tan);
void handleLedDeviceCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON message regarding Input Sources (Grabbers)
///
/// @param message the incoming message
///
void handleInputSourceCommand(const QJsonObject& message, const QString& command, int tan);
void handleInputSourceCommand(const QJsonObject& message, const JsonApiCommand& cmd);
/// Handle an incoming JSON message to request remote hyperion servers providing a given hyperion service
///
/// @param message the incoming message
///
void handleServiceCommand(const QJsonObject &message, const QString &command, int tan);
void handleServiceCommand(const QJsonObject &message, const JsonApiCommand& cmd);
/// Handle an incoming JSON message for actions related to the overall Hyperion system
///
/// @param message the incoming message
///
void handleSystemCommand(const QJsonObject &message, const QString &command, int tan);
void handleSystemCommand(const QJsonObject &message, const JsonApiCommand& cmd);
///
/// Handle an incoming JSON message of unknown type
///
void handleNotImplemented(const QString &command, int tan);
void applyColorAdjustments(const QJsonObject &adjustment, ColorAdjustment *colorAdjustment);
void applyColorAdjustment(const QString &colorName, const QJsonObject &adjustment, RgbChannelAdjustment &rgbAdjustment);
void applyGammaTransform(const QString &transformName, const QJsonObject &adjustment, RgbTransform &rgbTransform, char channel);
void applyTransforms(const QJsonObject &adjustment, ColorAdjustment *colorAdjustment);
template<typename T>
void applyTransform(const QString &transformName, const QJsonObject &adjustment, T &transform, void (T::*setFunction)(bool));
template<typename T>
void applyTransform(const QString &transformName, const QJsonObject &adjustment, T &transform, void (T::*setFunction)(double));
template<typename T>
void applyTransform(const QString &transformName, const QJsonObject &adjustment, T &transform, void (T::*setFunction)(uint8_t));
void handleTokenRequired(const JsonApiCommand& cmd);
void handleAdminRequired(const JsonApiCommand& cmd);
void handleNewPasswordRequired(const JsonApiCommand& cmd);
void handleLogout(const JsonApiCommand& cmd);
void handleNewPassword(const QJsonObject &message, const JsonApiCommand& cmd);
void handleCreateToken(const QJsonObject &message, const JsonApiCommand& cmd);
void handleRenameToken(const QJsonObject &message, const JsonApiCommand& cmd);
void handleDeleteToken(const QJsonObject &message, const JsonApiCommand& cmd);
void handleRequestToken(const QJsonObject &message, const JsonApiCommand& cmd);
void handleGetPendingTokenRequests(const JsonApiCommand& cmd);
void handleAnswerRequest(const QJsonObject &message, const JsonApiCommand& cmd);
void handleGetTokenList(const JsonApiCommand& cmd);
void handleLogin(const QJsonObject &message, const JsonApiCommand& cmd);
void handleLedDeviceDiscover(LedDevice& ledDevice, const QJsonObject& message, const JsonApiCommand& cmd);
void handleLedDeviceGetProperties(LedDevice& ledDevice, const QJsonObject& message, const JsonApiCommand& cmd);
void handleLedDeviceIdentify(LedDevice& ledDevice, const QJsonObject& message, const JsonApiCommand& cmd);
void handleLedDeviceAddAuthorization(LedDevice& ledDevice, const QJsonObject& message, const JsonApiCommand& cmd);
QJsonObject getBasicCommandReply(bool success, const QString &command, int tan, InstanceCmd::Type isInstanceCmd) const;
///
/// Send a standard reply indicating success
///
void sendSuccessReply(const QString &command = "", int tan = 0);
void sendSuccessReply(const JsonApiCommand& cmd);
///
/// Send a standard reply indicating success
///
void sendSuccessReply(const QString &command = "", int tan = 0, InstanceCmd::Type isInstanceCmd = InstanceCmd::No);
///
/// Send a standard reply indicating success with data
///
void sendSuccessDataReply(const QJsonDocument &doc, const QString &command = "", int tan = 0);
void sendSuccessDataReply(const QJsonValue &infoData, const JsonApiCommand& cmd);
///
/// Send a standard reply indicating success with data
///
void sendSuccessDataReply(const QJsonValue &infoData, const QString &command = "", int tan = 0, InstanceCmd::Type isInstanceCmd = InstanceCmd::No);
///
/// Send a standard reply indicating success with data and error details
///
void sendSuccessDataReplyWithError(const QJsonValue &infoData, const JsonApiCommand& cmd, const QStringList& errorDetails = {});
///
/// Send a standard reply indicating success with data and error details
///
void sendSuccessDataReplyWithError(const QJsonValue &infoData, const QString &command = "", int tan = 0, const QStringList& errorDetails = {}, InstanceCmd::Type isInstanceCmd = InstanceCmd::No);
///
/// Send a message with data.
/// Note: To be used as a new message and not as a response to a previous request.
///
void sendNewRequest(const QJsonValue &infoData, const JsonApiCommand& cmd);
///
/// Send a message with data
/// Note: To be used as a new message and not as a response to a previous request.
///
void sendNewRequest(const QJsonValue &infoData, const QString &command, InstanceCmd::Type isInstanceCmd = InstanceCmd::No);
///
/// Send an error message back to the client
///
/// @param error String describing the error
///
void sendErrorReply(const QString &error, const QString &command = "", int tan = 0);
void sendErrorReply(const QString &error, const JsonApiCommand& cmd);
///
/// Send an error message back to the client
///
/// @param error String describing the error
/// @param errorDetails additional information detailing the error scenario
///
void sendErrorReply(const QString &error, const QStringList& errorDetails, const JsonApiCommand& cmd);
///
/// Send an error message back to the client
///
/// @param error String describing the error
/// @param errorDetails additional information detailing the error scenario
///
void sendErrorReply(const QString &error, const QStringList& errorDetails = {}, const QString &command = "", int tan = 0, InstanceCmd::Type isInstanceCmd = InstanceCmd::No);
void sendNoAuthorization(const JsonApiCommand& cmd);
///
/// @brief Kill all signal/slot connections to stop possible data emitter
///
void stopDataConnections();
void stopDataConnections() override;
static QString findCommand (const QString& jsonS);
static int findTan (const QString& jsonString);
// true if further callbacks are forbidden (http)
bool _noListener;
/// The peer address of the client
QString _peerAddress;
// The JsonCallbacks instance which handles data subscription/notifications
QSharedPointer<JsonCallbacks> _jsonCB;
};

View File

@@ -0,0 +1,332 @@
#ifndef JSONAPICOMMAND_H
#define JSONAPICOMMAND_H
#include <QMap>
#include <QPair>
#include <QString>
class Command {
public:
enum Type {
Unknown,
Adjustment,
Authorize,
Clear,
ClearAll,
Color,
ComponentState,
Config,
Correction,
CreateEffect,
DeleteEffect,
Effect,
Image,
InputSource,
Instance,
LedColors,
LedDevice,
Logging,
Processing,
ServerInfo,
Service,
SourceSelect,
SysInfo,
System,
Temperature,
Transform,
VideoMode
};
static QString toString(Type type) {
switch (type) {
case Adjustment: return "adjustment";
case Authorize: return "authorize";
case Clear: return "clear";
case ClearAll: return "clearall";
case Color: return "color";
case ComponentState: return "componentstate";
case Config: return "config";
case Correction: return "correction";
case CreateEffect: return "create-effect";
case DeleteEffect: return "delete-effect";
case Effect: return "effect";
case Image: return "image";
case InputSource: return "inputsource";
case Instance: return "instance";
case LedColors: return "ledcolors";
case LedDevice: return "leddevice";
case Logging: return "logging";
case Processing: return "processing";
case ServerInfo: return "serverinfo";
case SourceSelect: return "sourceselect";
case SysInfo: return "sysinfo";
case System: return "system";
case Temperature: return "temperature";
case Transform: return "transform";
case VideoMode: return "videomode";
case Service: return "service";
default: return "unknown";
}
}
};
class SubCommand {
public:
enum Type {
Unknown,
Empty,
AdminRequired,
AddAuthorization,
AnswerRequest,
CreateInstance,
CreateToken,
DeleteInstance,
DeleteToken,
Discover,
GetConfig,
GetInfo,
GetPendingTokenRequests,
GetProperties,
GetSchema,
GetSubscriptionCommands,
GetSubscriptions,
GetTokenList,
Identify,
Idle,
ImageStreamStart,
ImageStreamStop,
LedStreamStart,
LedStreamStop,
Login,
Logout,
NewPassword,
NewPasswordRequired,
Reload,
RenameToken,
RequestToken,
Restart,
RestoreConfig,
Resume,
SaveName,
SetConfig,
Start,
StartInstance,
Stop,
StopInstance,
Subscribe,
Suspend,
SwitchTo,
ToggleIdle,
ToggleSuspend,
TokenRequired,
Unsubscribe
};
static QString toString(Type type) {
switch (type) {
case Empty: return "";
case AdminRequired: return "adminRequired";
case AddAuthorization: return "addAuthorization";
case AnswerRequest: return "answerRequest";
case CreateInstance: return "createInstance";
case CreateToken: return "createToken";
case DeleteInstance: return "deleteInstance";
case DeleteToken: return "deleteToken";
case Discover: return "discover";
case GetConfig: return "getconfig";
case GetInfo: return "getInfo";
case GetPendingTokenRequests: return "getPendingTokenRequests";
case GetProperties: return "getProperties";
case GetSchema: return "getschema";
case GetSubscriptionCommands: return "getSubscriptionCommands";
case GetSubscriptions: return "getSubscriptions";
case GetTokenList: return "getTokenList";
case Identify: return "identify";
case Idle: return "idle";
case ImageStreamStart: return "imagestream-start";
case ImageStreamStop: return "imagestream-stop";
case LedStreamStart: return "ledstream-start";
case LedStreamStop: return "ledstream-stop";
case Login: return "login";
case Logout: return "logout";
case NewPassword: return "newPassword";
case NewPasswordRequired: return "newPasswordRequired";
case Reload: return "reload";
case RenameToken: return "renameToken";
case RequestToken: return "requestToken";
case Restart: return "restart";
case RestoreConfig: return "restoreconfig";
case Resume: return "resume";
case SaveName: return "saveName";
case SetConfig: return "setconfig";
case Start: return "start";
case StartInstance: return "startInstance";
case Stop: return "stop";
case StopInstance: return "stopInstance";
case Subscribe: return "subscribe";
case Suspend: return "suspend";
case SwitchTo: return "switchTo";
case ToggleIdle: return "toggleIdle";
case ToggleSuspend: return "toggleSuspend";
case TokenRequired: return "tokenRequired";
case Unsubscribe: return "unsubscribe";
default: return "unknown";
}
}
};
class Authorization {
public:
enum Type {
Admin,
Yes,
No
};
};
class NoListenerCmd {
public:
enum Type {
No,
Yes
};
};
class InstanceCmd {
public:
enum Type {
No,
Yes,
Multi
};
};
class JsonApiCommand {
public:
JsonApiCommand()
: command(Command::Unknown),
subCommand(SubCommand::Unknown),
tan(0),
authorization(Authorization::Admin),
isInstanceCmd(InstanceCmd::No),
isNolistenerCmd(NoListenerCmd::Yes)
{}
JsonApiCommand(Command::Type command, SubCommand::Type subCommand,
Authorization::Type authorization,
InstanceCmd::Type isInstanceCmd,
NoListenerCmd::Type isNolistenerCmd,
int tan = 0)
: command(command),
subCommand(subCommand),
tan(tan),
authorization(authorization),
isInstanceCmd(isInstanceCmd),
isNolistenerCmd(isNolistenerCmd)
{}
Command::Type getCommand() const { return command; }
SubCommand::Type getSubCommand() const { return subCommand; }
InstanceCmd::Type instanceCmd() const { return isInstanceCmd; }
int getTan() const { return tan; }
QString toString() const {
QString cmd = Command::toString(command);
if (subCommand > SubCommand::Empty) {
cmd += QString("-%2").arg(SubCommand::toString(subCommand));
}
return cmd;
}
Command::Type command;
SubCommand::Type subCommand;
int tan;
Authorization::Type authorization;
InstanceCmd::Type isInstanceCmd;
NoListenerCmd::Type isNolistenerCmd;
};
typedef QMap<QPair<QString, QString>, JsonApiCommand> CommandLookupMap;
class ApiCommandRegister {
public:
static const CommandLookupMap& getCommandLookup() {
static const CommandLookupMap commandLookup {
{ {"adjustment", ""}, { Command::Adjustment, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"authorize", "adminRequired"}, { Command::Authorize, SubCommand::AdminRequired, Authorization::No, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"authorize", "answerRequest"}, { Command::Authorize, SubCommand::AnswerRequest, Authorization::Admin, InstanceCmd::No, NoListenerCmd::No} },
{ {"authorize", "createToken"}, { Command::Authorize, SubCommand::CreateToken, Authorization::Admin, InstanceCmd::No, NoListenerCmd::No} },
{ {"authorize", "deleteToken"}, { Command::Authorize, SubCommand::DeleteToken, Authorization::Admin, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"authorize", "getPendingTokenRequests"}, { Command::Authorize, SubCommand::GetPendingTokenRequests, Authorization::Admin, InstanceCmd::No, NoListenerCmd::No} },
{ {"authorize", "getTokenList"}, { Command::Authorize, SubCommand::GetTokenList, Authorization::Admin, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"authorize", "login"}, { Command::Authorize, SubCommand::Login, Authorization::No, InstanceCmd::No, NoListenerCmd::No} },
{ {"authorize", "logout"}, { Command::Authorize, SubCommand::Logout, Authorization::No, InstanceCmd::No, NoListenerCmd::No} },
{ {"authorize", "newPassword"}, { Command::Authorize, SubCommand::NewPassword, Authorization::Admin, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"authorize", "newPasswordRequired"}, { Command::Authorize, SubCommand::NewPasswordRequired, Authorization::No, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"authorize", "renameToken"}, { Command::Authorize, SubCommand::RenameToken, Authorization::Admin, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"authorize", "requestToken"}, { Command::Authorize, SubCommand::RequestToken, Authorization::No, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"authorize", "tokenRequired"}, { Command::Authorize, SubCommand::TokenRequired, Authorization::No, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"clear", ""}, { Command::Clear, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"clearall", ""}, { Command::ClearAll, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"color", ""}, { Command::Color, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"componentstate", ""}, { Command::ComponentState, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"config", "getconfig"}, { Command::Config, SubCommand::GetConfig, Authorization::Admin, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"config", "getschema"}, { Command::Config, SubCommand::GetSchema, Authorization::Admin, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"config", "reload"}, { Command::Config, SubCommand::Reload, Authorization::Admin, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"config", "restoreconfig"}, { Command::Config, SubCommand::RestoreConfig, Authorization::Admin, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"config", "setconfig"}, { Command::Config, SubCommand::SetConfig, Authorization::Admin, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"correction", ""}, { Command::Correction, SubCommand::Empty, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"create-effect", ""}, { Command::CreateEffect, SubCommand::Empty, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"delete-effect", ""}, { Command::DeleteEffect, SubCommand::Empty, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"effect", ""}, { Command::Effect, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"image", ""}, { Command::Image, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"inputsource", "discover"}, { Command::InputSource, SubCommand::Discover, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"inputsource", "getProperties"}, { Command::InputSource, SubCommand::GetProperties, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"instance", "createInstance"}, { Command::Instance, SubCommand::CreateInstance, Authorization::Admin, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"instance", "deleteInstance"}, { Command::Instance, SubCommand::DeleteInstance, Authorization::Admin, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"instance", "saveName"}, { Command::Instance, SubCommand::SaveName, Authorization::Admin, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"instance", "startInstance"}, { Command::Instance, SubCommand::StartInstance, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"instance", "stopInstance"}, { Command::Instance, SubCommand::StopInstance, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"instance", "switchTo"}, { Command::Instance, SubCommand::SwitchTo, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"ledcolors", "imagestream-start"}, { Command::LedColors, SubCommand::ImageStreamStart, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"ledcolors", "imagestream-stop"}, { Command::LedColors, SubCommand::ImageStreamStop, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"ledcolors", "ledstream-start"}, { Command::LedColors, SubCommand::LedStreamStart, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"ledcolors", "ledstream-stop"}, { Command::LedColors, SubCommand::LedStreamStop, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"leddevice", "addAuthorization"}, { Command::LedDevice, SubCommand::AddAuthorization, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"leddevice", "discover"}, { Command::LedDevice, SubCommand::Discover, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"leddevice", "getProperties"}, { Command::LedDevice, SubCommand::GetProperties, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"leddevice", "identify"}, { Command::LedDevice, SubCommand::Identify, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"logging", "start"}, { Command::Logging, SubCommand::Start, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"logging", "stop"}, { Command::Logging, SubCommand::Stop, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"processing", ""}, { Command::Processing, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"serverinfo", ""}, { Command::ServerInfo, SubCommand::Empty, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"serverinfo", "getInfo"}, { Command::ServerInfo, SubCommand::GetInfo, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"serverinfo", "subscribe"}, { Command::ServerInfo, SubCommand::Subscribe, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::No} },
{ {"serverinfo", "unsubscribe"}, { Command::ServerInfo, SubCommand::Unsubscribe, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::No} },
{ {"serverinfo", "getSubscriptions"}, { Command::ServerInfo, SubCommand::GetSubscriptions, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::No} },
{ {"serverinfo", "getSubscriptionCommands"}, { Command::ServerInfo, SubCommand::GetSubscriptionCommands, Authorization::No, InstanceCmd::No, NoListenerCmd::No} },
{ {"service", "discover"}, { Command::Service, SubCommand::Discover, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"sourceselect", ""}, { Command::SourceSelect, SubCommand::Empty, Authorization::Yes, InstanceCmd::Multi, NoListenerCmd::Yes} },
{ {"sysinfo", ""}, { Command::SysInfo, SubCommand::Empty, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"system", "restart"}, { Command::System, SubCommand::Restart, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"system", "resume"}, { Command::System, SubCommand::Resume, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"system", "suspend"}, { Command::System, SubCommand::Suspend, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"system", "toggleSuspend"}, { Command::System, SubCommand::ToggleSuspend, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"system", "idle"}, { Command::System, SubCommand::Idle, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"system", "toggleIdle"}, { Command::System, SubCommand::ToggleIdle, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} },
{ {"temperature", ""}, { Command::Temperature, SubCommand::Empty, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"transform", ""}, { Command::Transform, SubCommand::Empty, Authorization::Yes, InstanceCmd::Yes, NoListenerCmd::Yes} },
{ {"videomode", ""}, { Command::VideoMode, SubCommand::Empty, Authorization::Yes, InstanceCmd::No, NoListenerCmd::Yes} }
};
return commandLookup;
}
static JsonApiCommand getCommandInfo(const QString& command, const QString& subCommand) {
return getCommandLookup().value({command, subCommand});
}
};
#endif // JSONAPICOMMAND_H

View File

@@ -0,0 +1,135 @@
#ifndef JSONAPISUBSCRIPTION_H
#define JSONAPISUBSCRIPTION_H
#include <HyperionConfig.h> // Required to determine the cmake options
#include <QMap>
#include <QString>
class Subscription {
public:
enum Type {
Unknown,
AdjustmentUpdate,
ComponentsUpdate,
#if defined(ENABLE_EFFECTENGINE)
EffectsUpdate,
#endif
EventUpdate,
ImageToLedMappingUpdate,
ImageUpdate,
InstanceUpdate,
LedColorsUpdate,
LedsUpdate,
LogMsgUpdate,
PrioritiesUpdate,
SettingsUpdate,
TokenUpdate,
VideomodeUpdate
};
static QString toString(Type type) {
switch (type) {
case AdjustmentUpdate: return "adjustment-update";
case ComponentsUpdate: return "components-update";
#if defined(ENABLE_EFFECTENGINE)
case EffectsUpdate: return "effects-update";
#endif
case EventUpdate: return "event-update";
case ImageToLedMappingUpdate: return "imageToLedMapping-update";
case ImageUpdate: return "ledcolors-imagestream-update";
case InstanceUpdate: return "instance-update";
case LedColorsUpdate: return "ledcolors-ledstream-update";
case LedsUpdate: return "leds-update";
case LogMsgUpdate: return "logmsg-update";
case PrioritiesUpdate: return "priorities-update";
case SettingsUpdate: return "settings-update";
case TokenUpdate: return "token-update";
case VideomodeUpdate: return "videomode-update";
default: return "unknown";
}
}
static bool isInstanceSpecific(Type type) {
switch (type) {
case AdjustmentUpdate:
case ComponentsUpdate:
#if defined(ENABLE_EFFECTENGINE)
case EffectsUpdate:
#endif
case ImageToLedMappingUpdate:
case ImageUpdate:
case LedColorsUpdate:
case LedsUpdate:
case PrioritiesUpdate:
case SettingsUpdate:
return true;
case EventUpdate:
case InstanceUpdate:
case LogMsgUpdate:
case TokenUpdate:
case VideomodeUpdate:
default:
return false;
}
}
};
class JsonApiSubscription {
public:
JsonApiSubscription()
: cmd(Subscription::Unknown),
isAll(false)
{}
JsonApiSubscription(Subscription::Type cmd, bool isAll)
: cmd(cmd),
isAll(isAll)
{}
Subscription::Type getSubscription() const { return cmd; }
bool isPartOfAll() const { return isAll; }
QString toString() const {
return Subscription::toString(cmd);
}
Subscription::Type cmd;
bool isAll;
};
typedef QMap<QString, JsonApiSubscription> SubscriptionLookupMap;
class ApiSubscriptionRegister {
public:
static const SubscriptionLookupMap& getSubscriptionLookup() {
static const SubscriptionLookupMap subscriptionLookup {
{ {"adjustment-update"}, { Subscription::AdjustmentUpdate, true} },
{ {"components-update"}, { Subscription::ComponentsUpdate, true} },
#if defined(ENABLE_EFFECTENGINE)
{ {"effects-update"}, { Subscription::EffectsUpdate, true} },
#endif
{ {"event-update"}, { Subscription::EventUpdate, true} },
{ {"imageToLedMapping-update"}, { Subscription::ImageToLedMappingUpdate, true} },
{ {"ledcolors-imagestream-update"}, { Subscription::ImageUpdate, false} },
{ {"ledcolors-ledstream-update"}, { Subscription::LedColorsUpdate, false} },
{ {"instance-update"}, { Subscription::InstanceUpdate, true} },
{ {"leds-update"}, { Subscription::LedsUpdate, true} },
{ {"logmsg-update"}, { Subscription::LogMsgUpdate, false} },
{ {"priorities-update"}, { Subscription::PrioritiesUpdate, true} },
{ {"settings-update"}, { Subscription::SettingsUpdate, true} },
{ {"token-update"}, { Subscription::TokenUpdate, true} },
{ {"videomode-update"}, { Subscription::VideomodeUpdate, true} }
};
return subscriptionLookup;
}
static JsonApiSubscription getSubscriptionInfo(const QString& subscription) {
return getSubscriptionLookup().value({subscription});
}
};
#endif // JSONAPISUBSCRIPTION_H

View File

@@ -1,51 +1,82 @@
#pragma once
#include "api/JsonApiSubscription.h"
#include <api/API.h>
#include <events/EventEnum.h>
// qt incl
#include <QObject>
#include <QJsonObject>
#include <QSet>
// components def
#include <utils/Components.h>
// videModes
#include <utils/VideoMode.h>
// settings
#include <utils/settings.h>
// AuthManager
#include <hyperion/AuthManager.h>
#include <hyperion/PriorityMuxer.h>
class Hyperion;
class ComponentRegister;
class PriorityMuxer;
class JsonCB : public QObject
class JsonCallbacks : public QObject
{
Q_OBJECT
public:
JsonCB(QObject* parent);
JsonCallbacks(Logger* log, const QString& peerAddress, QObject* parent);
///
/// @brief Subscribe to future data updates given by cmd
/// @param cmd The cmd which will be subscribed for
/// @param unsubscribe Revert subscription
/// @param cmd The cmd which will be subscribed for
/// @return True on success, false if not found
///
bool subscribeFor(const QString& cmd, bool unsubscribe = false);
bool subscribe(const QString& cmd);
///
/// @brief Subscribe to future data updates given by subscription list
/// @param type Array of subscriptionsm
///
QStringList subscribe(const QJsonArray& subscriptions);
///
/// @brief Subscribe to future data updates given by cmd
/// @param cmd The cmd which will be subscribed to
/// @return True on success, false if not found
///
bool subscribe(Subscription::Type subscription);
///
/// @brief Unsubscribe to future data updates given by cmd
/// @param cmd The cmd which will be unsubscribed
/// @return True on success, false if not found
///
bool unsubscribe(const QString& cmd);
///
/// @brief Unsubscribe to future data updates given by subscription list
/// @param type Array of subscriptions
///
QStringList unsubscribe(const QJsonArray& subscriptions);
///
/// @brief Unsubscribe to future data updates given by cmd
/// @param cmd The cmd which will be subscribed to
/// @return True on success, false if not found
///
bool unsubscribe(Subscription::Type cmd);
///
/// @brief Get all possible commands to subscribe for
/// @param fullList Return all possible commands or those not triggered by API requests (subscriptions="ALL")
/// @return The list of commands
///
QStringList getCommands() { return _availableCommands; };
QStringList getCommands(bool fullList = true) const;
///
/// @brief Get all subscribed commands
/// @return The list of commands
///
QStringList getSubscribedCommands() { return _subscribedCommands; };
QStringList getSubscribedCommands() const;
///
/// @brief Reset subscriptions, disconnect all signals
@@ -124,18 +155,49 @@ private slots:
///
void handleTokenChange(const QVector<AuthManager::AuthDefinition> &def);
///
/// @brief Is called whenever the current Hyperion instance pushes new led raw values (if enabled)
/// @param ledColors The current led colors
///
void handleLedColorUpdate(const std::vector<ColorRgb> &ledColors);
///
/// @brief Is called whenever the current Hyperion instance pushes new image update (if enabled)
/// @param image The current image
///
void handleImageUpdate(const Image<ColorRgb> &image);
///
/// @brief Process and push new log messages from logger (if enabled)
///
void handleLogMessageUpdate(const Logger::T_LOG_MESSAGE &);
///
/// @brief Is called whenever an event is triggert
/// @param image The current event
///
void handleEventUpdate(const Event &event);
private:
/// pointer of Hyperion instance
/// construct callback msg
void doCallback(Subscription::Type cmd, const QVariant& data);
Logger *_log;
Hyperion* _hyperion;
/// The peer address of the client
QString _peerAddress;
/// pointer of comp register
ComponentRegister* _componentRegister;
/// priority muxer instance
PriorityMuxer* _prioMuxer;
/// contains all available commands
QStringList _availableCommands;
/// contains active subscriptions
QStringList _subscribedCommands;
/// construct callback msg
void doCallback(const QString& cmd, const QVariant& data);
QSet<Subscription::Type> _subscribedCommands;
/// flag to determine state of log streaming
bool _islogMsgStreamingActive;
};

43
include/api/JsonInfo.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef JSONINFO_H
#define JSONINFO_H
#include <utils/Logger.h>
#include <hyperion/Hyperion.h>
#include <hyperion/HyperionIManager.h>
#include <QJsonObject>
#include <QJsonArray>
class JsonInfo
{
public:
static QJsonArray getAdjustmentInfo(const Hyperion* hyperion, Logger* log);
static QJsonArray getPrioritiestInfo(const Hyperion* hyperion);
static QJsonArray getPrioritiestInfo(int currentPriority, const PriorityMuxer::InputsMap& activeInputs);
static QJsonArray getEffects(const Hyperion* hyperion);
static QJsonArray getAvailableScreenGrabbers();
static QJsonArray getAvailableVideoGrabbers();
static QJsonArray getAvailableAudioGrabbers();
static QJsonObject getGrabbers(const Hyperion* hyperion);
static QJsonObject getAvailableLedDevices();
static QJsonObject getCecInfo();
static QJsonArray getServices();
static QJsonArray getComponents(const Hyperion* hyperion);
static QJsonArray getInstanceInfo();
static QJsonArray getActiveEffects(const Hyperion* hyperion);
static QJsonArray getActiveColors(const Hyperion* hyperion);
static QJsonArray getTransformationInfo(const Hyperion* hyperion);
static QJsonObject getSystemInfo(const Hyperion* hyperion);
QJsonObject discoverSources (const QString& sourceType, const QJsonObject& params);
private:
template<typename GrabberType>
void discoverGrabber(QJsonArray& inputs, const QJsonObject& params) const;
QJsonArray discoverScreenInputs(const QJsonObject& params) const;
QJsonArray discoverVideoInputs(const QJsonObject& params) const;
QJsonArray discoverAudioInputs(const QJsonObject& params) const;
};
#endif // JSONINFO_H

View File

@@ -2,6 +2,9 @@
#include <QString>
#include <QByteArray>
#include <QJsonObject>
#include <utils/Components.h>
struct ImageCmdData
{

View File

@@ -8,6 +8,11 @@
#include <QDateTime>
#include <QUuid>
namespace hyperion {
const char DEFAULT_USER[] = "Hyperion";
const char DEFAULT_PASSWORD[] = "hyperion";
}
///
/// @brief Authentication table interface
///
@@ -149,10 +154,10 @@ public:
inline bool resetHyperionUser()
{
QVariantMap map;
map["password"] = calcPasswordHashOfUser("Hyperion", "hyperion");
map["password"] = calcPasswordHashOfUser(hyperion::DEFAULT_USER, hyperion::DEFAULT_PASSWORD);
VectorPair cond;
cond.append(CPair("user", "Hyperion"));
cond.append(CPair("user", hyperion::DEFAULT_USER));
return updateRecord(cond, map);
}

View File

@@ -13,7 +13,8 @@ enum class Event
ResumeIdle,
ToggleIdle,
Reload,
Restart
Restart,
Quit
};
inline const char* eventToString(Event event)
@@ -24,6 +25,7 @@ inline const char* eventToString(Event event)
case Event::Resume: return "Resume";
case Event::ToggleSuspend: return "ToggleSuspend";
case Event::Idle: return "Idle";
case Event::Quit: return "Quit";
case Event::ResumeIdle: return "ResumeIdle";
case Event::ToggleIdle: return "ToggleIdle";
case Event::Reload: return "Reload";
@@ -39,6 +41,7 @@ inline Event stringToEvent(const QString& event)
if (event.compare("Resume")==0) return Event::Resume;
if (event.compare("ToggleSuspend")==0) return Event::ToggleSuspend;
if (event.compare("Idle")==0) return Event::Idle;
if (event.compare("Quit")==0) return Event::Quit;
if (event.compare("ResumeIdle")==0) return Event::ResumeIdle;
if (event.compare("ToggleIdle")==0) return Event::ToggleIdle;
if (event.compare("Reload")==0) return Event::Reload;

View File

@@ -29,6 +29,7 @@ public:
public slots:
void suspend(bool sleep);
void lock(bool isLocked);
void quit();
virtual void handleSettingsUpdate(settings::type type, const QJsonDocument& config);
@@ -101,6 +102,7 @@ public:
void handleSignal(int signum);
private:
static OsEventHandlerLinux* getInstance();

View File

@@ -0,0 +1,58 @@
#ifndef GRABBERCONFIG_H
#define GRABBERCONFIG_H
#if defined(ENABLE_MF)
#include <grabber/video/mediafoundation/MFGrabber.h>
#elif defined(ENABLE_V4L2)
#include <grabber/video/v4l2/V4L2Grabber.h>
#endif
#if defined(ENABLE_AUDIO)
#include <grabber/audio/AudioGrabber.h>
#ifdef WIN32
#include <grabber/audio/AudioGrabberWindows.h>
#endif
#ifdef __linux__
#include <grabber/audio/AudioGrabberLinux.h>
#endif
#endif
#ifdef ENABLE_QT
#include <grabber/qt/QtGrabber.h>
#endif
#ifdef ENABLE_DX
#include <grabber/directx/directXGrabber.h>
#endif
#if defined(ENABLE_X11)
#include <grabber/x11/X11Grabber.h>
#endif
#if defined(ENABLE_XCB)
#include <grabber/xcb/XcbGrabber.h>
#endif
#if defined(ENABLE_DX)
#include <grabber/directx/DirectXGrabber.h>
#endif
#if defined(ENABLE_FB)
#include <grabber/framebuffer/FramebufferFrameGrabber.h>
#endif
#if defined(ENABLE_DISPMANX)
#include <grabber/dispmanx/DispmanxFrameGrabber.h>
#endif
#if defined(ENABLE_AMLOGIC)
#include <grabber/amlogic/AmlogicGrabber.h>
#endif
#if defined(ENABLE_OSX)
#include <grabber/osx/OsxFrameGrabber.h>
#endif
#endif // GRABBERCONFIG_H

View File

@@ -3,6 +3,8 @@
#include <utils/Logger.h>
#include <utils/settings.h>
#include <db/AuthTable.h>
//qt
#include <QMap>
#include <QVector>
@@ -41,24 +43,12 @@ public:
///
QString getID() const { return _uuid; }
///
/// @brief Check authorization is required according to the user setting
/// @return True if authorization required else false
///
bool isAuthRequired() const { return _authRequired; }
///
/// @brief Check if authorization is required for local network connections
/// @return True if authorization required else false
///
bool isLocalAuthRequired() const { return _localAuthRequired; }
///
/// @brief Check if authorization is required for local network connections for admin access
/// @return True if authorization required else false
///
bool isLocalAdminAuthRequired() const { return _localAdminAuthRequired; }
///
/// @brief Reset Hyperion user
/// @return True on success else false
@@ -172,7 +162,7 @@ public slots:
/// @param usr the defined user
/// @return The token
///
QString getUserToken(const QString &usr = "Hyperion") const;
QString getUserToken(const QString &usr = hyperion::DEFAULT_USER) const;
///
/// @brief Get all available token entries
@@ -230,15 +220,9 @@ private:
/// All pending requests
QMap<QString, AuthDefinition> _pendingRequests;
/// Reflect state of global auth
bool _authRequired;
/// Reflect state of local auth
bool _localAuthRequired;
/// Reflect state of local admin auth
bool _localAdminAuthRequired;
/// Timer for counting against pendingRequest timeouts
QTimer *_timer;

View File

@@ -67,6 +67,7 @@ class Hyperion : public QObject
Q_OBJECT
public:
/// Type definition of the info structure used by the priority muxer
using InputsMap = PriorityMuxer::InputsMap;
using InputInfo = PriorityMuxer::InputInfo;
///
@@ -107,7 +108,7 @@ public:
///
QString getActiveDeviceType() const;
bool getReadOnlyMode() {return _readOnlyMode; }
bool getReadOnlyMode() const {return _readOnlyMode; }
public slots:
@@ -235,13 +236,13 @@ public slots:
/// @param priority The priority channel of the effect
/// @param timeout The timeout of the effect (after the timout, the effect will be cleared)
int setEffect(const QString &effectName
, const QJsonObject &args
, int priority
, int timeout = PriorityMuxer::ENDLESS
, const QString &pythonScript = ""
, const QString &origin="System"
, const QString &imageData = ""
);
, const QJsonObject &args
, int priority
, int timeout = PriorityMuxer::ENDLESS
, const QString &pythonScript = ""
, const QString &origin="System"
, const QString &imageData = ""
);
/// Get the list of available effects
/// @return The list of available effects
@@ -303,7 +304,14 @@ public slots:
QList<int> getActivePriorities() const;
///
/// Returns the information of a specific priorrity channel
/// Returns the information of all priority channels.
///
/// @return The information fo all priority channels
///
PriorityMuxer::InputsMap getPriorityInfo() const;
///
/// Returns the information of a specific priority channel
///
/// @param[in] priority The priority channel
///
@@ -346,7 +354,7 @@ public slots:
/// @brief Get the component Register
/// return Component register pointer
///
ComponentRegister* getComponentRegister() { return _componentRegister; }
ComponentRegister* getComponentRegister() const { return _componentRegister; }
///
/// @brief Called from components to update their current state. DO NOT CALL FROM USERS

View File

@@ -55,10 +55,16 @@ public slots:
Hyperion* getHyperionInstance(quint8 instance = 0);
///
/// @brief Get instance data of all instaces in db + running state
/// @brief Get instance data of all instances in db + running state
///
QVector<QVariantMap> getInstanceData() const;
///
/// @brief Get all instance indicies of running instances
///
QList<quint8> getRunningInstanceIdx() const;
///
/// @brief Start a Hyperion instance
/// @param instance Instance index

View File

@@ -141,6 +141,13 @@ public:
///
QList<int> getPriorities() const;
///
/// Returns the information of all priority channels.
///
/// @return The information fo all priority channels
///
InputsMap getInputInfo() const;
///
/// Returns the information of a specified priority channel.
/// If a priority is no longer available the _lowestPriorityInfo (255) is returned

View File

@@ -3,6 +3,8 @@
#include <utils/FileUtils.h>
#include <QJsonObject>
#include <QPair>
#include <QStringList>
#include <utils/Logger.h>
namespace JsonUtils {
@@ -14,7 +16,7 @@ namespace JsonUtils {
/// @param[in] ignError Ignore errors during file read (no log output)
/// @return true on success else false
///
bool readFile(const QString& path, QJsonObject& obj, Logger* log, bool ignError=false);
QPair<bool, QStringList> readFile(const QString& path, QJsonObject& obj, Logger* log, bool ignError=false);
///
/// @brief read a schema file and resolve $refs
@@ -33,7 +35,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool parse(const QString& path, const QString& data, QJsonObject& obj, Logger* log);
QPair<bool, QStringList> parse(const QString& path, const QString& data, QJsonObject& obj, Logger* log);
///
/// @brief parse a json QString and get a QJsonArray. Overloaded function
@@ -42,8 +44,8 @@ namespace JsonUtils {
/// @param[out] arr Retuns the parsed QJsonArray
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool parse(const QString& path, const QString& data, QJsonArray& arr, Logger* log);
//
QPair<bool, QStringList> parse(const QString& path, const QString& data, QJsonArray& arr, Logger* log);
///
/// @brief parse a json QString and get a QJsonDocument
@@ -53,7 +55,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool parse(const QString& path, const QString& data, QJsonDocument& doc, Logger* log);
QPair<bool, QStringList> parse(const QString& path, const QString& data, QJsonDocument& doc, Logger* log);
///
/// @brief Validate json data against a schema
@@ -63,7 +65,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool validate(const QString& file, const QJsonObject& json, const QString& schemaPath, Logger* log);
QPair<bool, QStringList> validate(const QString& file, const QJsonObject& json, const QString& schemaPath, Logger* log);
///
/// @brief Validate json data against a schema
@@ -73,7 +75,7 @@ namespace JsonUtils {
/// @param[in] log The logger of the caller to print errors
/// @return true on success else false
///
bool validate(const QString& file, const QJsonObject& json, const QJsonObject& schema, Logger* log);
QPair<bool, QStringList> validate(const QString& file, const QJsonObject& json, const QJsonObject& schema, Logger* log);
///
/// @brief Write json data to file

View File

@@ -47,7 +47,9 @@ private slots:
private:
Logger* _log;
/// True when internet access is allowed
bool _internetAccessAllowed;
bool _isInternetAccessAllowed;
/// True when internet access is restricted by a white list
bool _isInternetAccessRestricted;
/// Whitelisted ip addresses
QList<QHostAddress> _ipWhitelist;

View File

@@ -31,7 +31,9 @@ public:
if (!schemaChecker.validate(configTree).first)
{
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;
return -3;
@@ -61,9 +63,10 @@ public:
if (error.error != QJsonParseError::NoError)
{
// report to the user the failure and their locations in the document.
int errorLine(0), errorColumn(0);
int errorLine(0);
int errorColumn(0);
for( int i=0, count=qMin( error.offset,config.size()); i<count; ++i )
for(long i=0, count=qMin( error.offset,config.size()); i<count; ++i )
{
++errorColumn;
if(config.at(i) == '\n' )