Skip to content

Commit

Permalink
JSON API: retrieve the average LED color of a given instance (#611)
Browse files Browse the repository at this point in the history
  • Loading branch information
awawa-dev authored Aug 3, 2023
1 parent 8b2364c commit da94f8a
Show file tree
Hide file tree
Showing 39 changed files with 1,093 additions and 414 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
- Add support for HD108 led strip, 16/48bits colors #527 (v20 beta 🆕)
- Use optional system libs for compiling #541 (v20 beta 🆕)
- Update mbedtls to 3.4.0 #589 (v20 beta 🆕)
- Add Ubuntu support to HyperHDR and Github Pages APT repository #522 (v20 beta 🆕)
- Add Ubuntu support to HyperHDR and Github Pages APT repository #522 (v20 beta 🆕)
- New JsonAPI method to calculate average color of selected instance #611 (v20 beta 🆕)
- Workaround for critical Rpi udev bug affecting serial ports #583 (v20 beta 🆕)
- Add Arch Linux support #520 (v20 beta 🆕)
- Fix chrome/edge fullscreen detection #519 (v20 beta 🆕)
Expand Down
4 changes: 4 additions & 0 deletions include/api/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ class API : public QObject
///
void stopInstance(quint8 index);

QJsonObject getAverageColor(quint8 index);

//////////////////////////////////
/// AUTH / ADMINISTRATION METHODS
//////////////////////////////////
Expand Down Expand Up @@ -365,6 +367,8 @@ class API : public QObject
///
bool isUserAuthorized(const QString& password);

bool isUserBlocked();

///
/// @brief Test if Hyperhdr has the default PW
/// @return The result
Expand Down
2 changes: 2 additions & 0 deletions include/api/JsonAPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,8 @@ private slots:

void handleSmoothingCommand(const QJsonObject& message, const QString& command, int tan);

void handleCurrentStateCommand(const QJsonObject& message, const QString& command, int tan);

void handleTunnel(const QJsonObject& message, const QString& command, int tan);

///
Expand Down
4 changes: 3 additions & 1 deletion include/base/AuthManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ class AuthManager : public QObject
/// @brief Check if user auth is temporary blocked due to failed attempts
/// @return True on blocked and no further Auth requests will be accepted
///
bool isUserAuthBlocked() const;


///
/// @brief Check if token auth is temporary blocked due to failed attempts
Expand All @@ -92,6 +92,8 @@ public slots:
///
bool isUserAuthorized(const QString& user, const QString& pw);

bool isUserAuthBlocked() const;

///
/// @brief Check if token is authorized
/// @param token The token
Expand Down
2 changes: 2 additions & 0 deletions include/base/HyperHdrIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public slots:
///
bool stopInstance(quint8 inst);

QJsonObject getAverageColor(quint8 index);

///
/// @brief Toggle the state of all HyperHDR instances
/// @param pause If true all instances toggle to pause, else to resume
Expand Down
3 changes: 3 additions & 0 deletions include/base/HyperHdrInstance.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,10 @@ class HyperHdrInstance : public QObject

public slots:

QJsonObject getAverageColor();

void setSmoothing(int time);

void identifyLed(const QJsonObject& params);

bool getReadOnlyMode() { return _readOnlyMode; };
Expand Down
3 changes: 3 additions & 0 deletions include/utils/Logger.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <utils/InternalClock.h>
#include <utils/Macros.h>

// QT includes
#include <QObject>
Expand Down Expand Up @@ -74,6 +75,7 @@ class Logger : public QObject
static void deleteInstance(const QString& name = "");
static void setLogLevel(LogLevel level, const QString& name = "");
static LogLevel getLogLevel(const QString& name = "");
static QString getLastError();

void Message(LogLevel level, const char* sourceFile, const char* func, unsigned int line, const char* fmt, ...);
void setMinLevel(LogLevel level);
Expand All @@ -97,6 +99,7 @@ class Logger : public QObject
static QMutex _mapLock;
static QMap<QString, Logger*> _loggerMap;
static QAtomicInteger<int> GLOBAL_MIN_LOG_LEVEL;
static QString _lastError;

const QString _name;
const QString _appname;
Expand Down
123 changes: 123 additions & 0 deletions include/utils/Macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#pragma once

/* Macros.h
*
* MIT License
*
* Copyright (c) 2023 awawa-dev
*
* Project homesite: https://github.com/awawa-dev/HyperHDR
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

inline void SAFE_CALL_TEST_FUN() {};

#define SAFE_CALL_0_RET(target, method, returnType, result, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (target->thread() != this->thread()) \
QMetaObject::invokeMethod(target, #method, Qt::BlockingQueuedConnection, Q_RETURN_ARG(returnType, result)); \
else \
result = target->method(); \
}

#define SAFE_CALL_1_RET(target, method, returnType, result, p1type, p1value, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (target->thread() != this->thread()) \
QMetaObject::invokeMethod(target, #method, Qt::BlockingQueuedConnection, Q_RETURN_ARG(returnType, result), Q_ARG(p1type, p1value)); \
else \
result = target->method(p1value); \
}

#define SAFE_CALL_2_RET(target, method, returnType, result, p1type, p1value, p2type, p2value, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (target->thread() != this->thread()) \
QMetaObject::invokeMethod(target, #method, Qt::BlockingQueuedConnection, Q_RETURN_ARG(returnType, result), Q_ARG(p1type, p1value), Q_ARG(p2type, p2value)); \
else \
result = target->method(p1value, p2value); \
}

#define SAFE_CALL_3_RET(target, method, returnType, result, p1type, p1value, p2type, p2value, p3type, p3value, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (target->thread() != this->thread()) \
QMetaObject::invokeMethod(target, #method, Qt::BlockingQueuedConnection, Q_RETURN_ARG(returnType, result), Q_ARG(p1type, p1value), Q_ARG(p2type, p2value), Q_ARG(p3type, p3value)); \
else \
result = target->method(p1value, p2value, p3value); \
}

#define SAFE_CALL_4_RET(target, method, returnType, result, p1type, p1value, p2type, p2value, p3type, p3value, p4type, p4value , ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (target->thread() != this->thread()) \
QMetaObject::invokeMethod(target, #method, Qt::BlockingQueuedConnection, Q_RETURN_ARG(returnType, result), Q_ARG(p1type, p1value), Q_ARG(p2type, p2value), Q_ARG(p3type, p3value), Q_ARG(p4type, p4value)); \
else \
result = target->method(p1value, p2value, p3value, p4value); \
}

#define SAFE_CALL_0(target, method, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (true) \
QMetaObject::invokeMethod(target, #method, Qt::QueuedConnection); \
else \
target->method(); \
}

#define SAFE_CALL_1(target, method, p1type, p1value, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (true) \
QMetaObject::invokeMethod(target, #method, Qt::QueuedConnection, Q_ARG(p1type, p1value)); \
else \
target->method(p1value); \
}

#define SAFE_CALL_2(target, method, p1type, p1value, p2type, p2value, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (true) \
QMetaObject::invokeMethod(target, #method, Qt::QueuedConnection, Q_ARG(p1type, p1value), Q_ARG(p2type, p2value)); \
else \
target->method(p1value, p2value); \
}

#define SAFE_CALL_3(target, method, p1type, p1value, p2type, p2value, p3type, p3value, ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (true) \
QMetaObject::invokeMethod(target, #method, Qt::QueuedConnection, Q_ARG(p1type, p1value), Q_ARG(p2type, p2value), Q_ARG(p3type, p3value)); \
else \
target->method(p1value, p2value, p3value); \
}

#define SAFE_CALL_4(target, method, p1type, p1value, p2type, p2value, p3type, p3value, p4type, p4value , ...) \
{ \
SAFE_CALL_TEST_FUN(__VA_ARGS__); \
if (true) \
QMetaObject::invokeMethod(target, #method, Qt::QueuedConnection, Q_ARG(p1type, p1value), Q_ARG(p2type, p2value), Q_ARG(p3type, p3value), Q_ARG(p4type, p4value)); \
else \
target->method(p1value, p2value, p3value, p4value); \
}



6 changes: 5 additions & 1 deletion include/utils/RgbChannelAdjustment.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class RgbChannelAdjustment
/// @param adjustR
/// @param adjustG
/// @param adjustB
RgbChannelAdjustment(quint8 instance, uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, QString channelName);
RgbChannelAdjustment(quint8 instance, uint8_t adjustR, uint8_t adjustG, uint8_t adjustB, QString channelName, bool enabled);

///
/// Transform the given array value
Expand Down Expand Up @@ -63,6 +63,8 @@ class RgbChannelAdjustment

uint8_t correction(uint8_t input) const;

bool isEnabled();

static RgbChannelAdjustment createRgbChannelAdjustment(quint8 instance, const QJsonObject& colorConfig, const QString& channelName, int defaultR, int defaultG, int defaultB);

private:
Expand Down Expand Up @@ -104,4 +106,6 @@ class RgbChannelAdjustment

/// current brightness value
uint8_t _brightness;

bool _enabled;
};
23 changes: 19 additions & 4 deletions sources/api/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,16 +337,24 @@ QVector<QVariantMap> API::getAllInstanceData()
bool API::startInstance(quint8 index, int tan)
{
bool res;
(_instanceManager->thread() != this->thread())
? QMetaObject::invokeMethod(_instanceManager, "startInstance", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, res), Q_ARG(quint8, index), Q_ARG(bool, false), Q_ARG(QObject*, this), Q_ARG(int, tan))
: res = _instanceManager->startInstance(index, false, this, tan);

SAFE_CALL_4_RET(_instanceManager, startInstance, bool, res, quint8, index, bool, false, QObject*, this, int, tan);

return res;
}

void API::stopInstance(quint8 index)
{
QMetaObject::invokeMethod(_instanceManager, "stopInstance", Qt::QueuedConnection, Q_ARG(quint8, index));
SAFE_CALL_1(_instanceManager, stopInstance, quint8, index);
}

QJsonObject API::getAverageColor(quint8 index)
{
QJsonObject res;

SAFE_CALL_1_RET(_instanceManager, getAverageColor, QJsonObject, res, quint8, index);

return res;
}

void API::requestActiveRegister(QObject* callerInstance)
Expand Down Expand Up @@ -557,6 +565,13 @@ bool API::isUserAuthorized(const QString& password)
return res;
}

bool API::isUserBlocked()
{
bool res;
SAFE_CALL_0_RET(_authManager, isUserAuthBlocked, bool, res);
return res;
}

bool API::hasHyperhdrDefaultPw()
{
bool res;
Expand Down
26 changes: 26 additions & 0 deletions sources/api/JSONRPC_schema/schema-current-state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"type":"object",
"required":true,
"properties":{
"command": {
"type" : "string",
"required" : true,
"enum" : ["current-state"]
},
"subcommand" : {
"type" : "string",
"required" : true,
"enum" : ["average-color"]
},
"tan" : {
"type" : "integer"
},
"instance": {
"type": "integer",
"minimum" : 0,
"maximum" : 255,
"required": true
}
},
"additionalProperties": false
}
2 changes: 1 addition & 1 deletion sources/api/JSONRPC_schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"command": {
"type" : "string",
"required" : true,
"enum": [ "color", "tunnel", "smoothing", "benchmark", "lut-install", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "adjustment", "sourceselect", "config", "componentstate", "ledcolors", "load-db", "save-db", "logging", "performance-counters", "lut-calibration", "signal-calibration", "processing", "sysinfo", "videomodehdr", "video-crop", "videomode", "authorize", "instance", "leddevice", "transform", "correction", "temperature", "help", "video-controls" ]
"enum": [ "color", "tunnel", "smoothing", "benchmark", "lut-install", "image", "effect", "create-effect", "delete-effect", "serverinfo", "clear", "clearall", "adjustment", "sourceselect", "config", "componentstate", "current-state", "ledcolors", "load-db", "save-db", "logging", "performance-counters", "lut-calibration", "signal-calibration", "processing", "sysinfo", "videomodehdr", "video-crop", "videomode", "authorize", "instance", "leddevice", "transform", "correction", "temperature", "help", "video-controls" ]
}
}
}
1 change: 1 addition & 0 deletions sources/api/JSONRPC_schemas.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
<file alias="schema-tunnel">JSONRPC_schema/schema-tunnel.json</file>
<file alias="schema-performance-counters">JSONRPC_schema/schema-performance-counters.json</file>
<file alias="schema-smoothing">JSONRPC_schema/schema-smoothing.json</file>
<file alias="schema-current-state">JSONRPC_schema/schema-current-state.json</file>
<!-- The following schemas are derecated but used to ensure backward compatibility with Classic remote control-->
<file alias="schema-transform">JSONRPC_schema/schema-classic.json</file>
<file alias="schema-correction">JSONRPC_schema/schema-classic.json</file>
Expand Down
Loading

0 comments on commit da94f8a

Please sign in to comment.