mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2025-03-01 10:33:28 +00:00
Refactor Hyperion JSON-API (#1727)
This commit is contained in:
parent
94850d890a
commit
cf287f5adb
27
CHANGELOG.md
27
CHANGELOG.md
@ -8,14 +8,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Breaking
|
||||
|
||||
**JSON-API**
|
||||
- Align JSON subscription update elements. `ledcolors-imagestream-update, ledcolors-ledstream-update, logmsg-update` now return data via `data` and not `result
|
||||
|
||||
### Added
|
||||
|
||||
- Support gaps on Matrix Layout (#1696)
|
||||
|
||||
**JSON-API**
|
||||
- New subscription support for event updates, i.e. `Suspend, Resume, Idle, idleResume, Restart, Quit`.
|
||||
- Support direct or multiple instance addressing via single requests (#809)
|
||||
- Support of `serverinfo` subcommands: `getInfo, subscribe, unsubscribe, getSubscriptions, getSubscriptionCommands`
|
||||
- [Overview](https://github.com/hyperion-project/hyperion.ng/blob/API_Auth/doc/development/JSON-API%20_Commands_Overview.md) of API commands and subscription updates
|
||||
|
||||
### Changed
|
||||
|
||||
- Fixed: Cross Site Scripting Vulnerability (CVE-2024-4174, CVE-2024-4175)
|
||||
- Fixed: hyperion-v4l2 taking screenshot failed (#1722)
|
||||
- Nanoleaf: Support new devices and do not restore ExtControl state
|
||||
- Workaround to address Web UI keeps forcing browser to download the html instead (#1692)
|
||||
- Fixed: Kodi Color Calibration, Refactor Wizards (#1674)
|
||||
- Fixed: Token Dialog not closing
|
||||
|
||||
**JSON-API**
|
||||
- Refactored JSON-API to ensure consistent authorization behaviour across sessions and single requests with token authorization.
|
||||
- Provide additional error details with API responses, esp. on JSON parsing, validation or token errors.
|
||||
- Generate random TANs for every API request from the Hyperion UI
|
||||
- Fixed: Handling of IP4 addresses wrapped in IPv6 for external network connections-
|
||||
|
||||
### Removed
|
||||
|
||||
**JSON-API**
|
||||
- Removed ability to enable/disable local admin authorization. All admin commands require authorization, i.e. `authorize-adminRequired` will always be `true`.
|
||||
- Removed `session-updates` subscription
|
||||
- `serverinfo/subscribe` element will be deprecated and replaced by corresponding subcommand
|
||||
|
||||
## [2.0.16](https://github.com/hyperion-project/hyperion.ng/releases/tag/2.0.16) - 2024-01
|
||||
|
||||
### Added
|
||||
|
@ -186,6 +186,7 @@
|
||||
"conf_network_json_intro": "The JSON-RPC-Port of all Hyperion instances, used for remote control.",
|
||||
"conf_network_net_intro": "Network related settings which are applied to all network services.",
|
||||
"conf_network_proto_intro": "The PROTO-Port of all Hyperion instances, used for picture streams (HyperionScreenCap, Kodi Addon, Android Hyperion Grabber, ...)",
|
||||
"conf_network_tok_idhead": "ID",
|
||||
"conf_network_tok_cidhead": "Description",
|
||||
"conf_network_tok_comment_title": "Token description",
|
||||
"conf_network_tok_desc": "Tokens grant other applications access to the Hyperion API, an application can request a token where you need to accept it or you create them on your own below. These tokens are just required when \"API Authorization\" is enabled in network settings.",
|
||||
@ -500,19 +501,16 @@
|
||||
"edt_conf_log_level_expl": "Depending on loglevel you see less or more messages in your log.",
|
||||
"edt_conf_log_level_title": "Log-Level",
|
||||
"edt_conf_net_apiAuth_expl": "Enforce all applications that use the Hyperion API to authenticate themself against Hyperion (Exception: see \"Local API Authentication\"). Higher security, as you control the access and revoke it at any time.",
|
||||
"edt_conf_net_apiAuth_title": "API Authentication",
|
||||
"edt_conf_net_heading_title": "Network",
|
||||
"edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Webinterface from the internet. Disable for higher security.",
|
||||
"edt_conf_net_internetAccessAPI_expl": "Allow access to the Hyperion API/Web Interface from the Internet. Disable for increased security.",
|
||||
"edt_conf_net_internetAccessAPI_title": "Internet API Access",
|
||||
"edt_conf_net_ipWhitelist_expl": "You can whitelist IP addresses instead allowing all connections from internet to connect to the Hyperion API/Webinterface.",
|
||||
"edt_conf_net_ipWhitelist_title": "Whitelisted IP's",
|
||||
"edt_conf_net_ipWhitelist_expl": "Define whitelisted IP addresses from which API requests from the Internet are allowed. All other external connections will be denied.",
|
||||
"edt_conf_net_ipWhitelist_title": "Whitelisted IP addresses",
|
||||
"edt_conf_net_ip_itemtitle": "IP",
|
||||
"edt_conf_net_localAdminAuth_expl": "When enabled, administration access from your local network needs a password.",
|
||||
"edt_conf_net_localAdminAuth_title": "Local Admin API Authentication",
|
||||
"edt_conf_net_localApiAuth_expl": "When enabled, connections from your home network needs to authenticate themselves against Hyperion with a token.",
|
||||
"edt_conf_net_localApiAuth_expl": "When disabled, API authorisation via password or token is not required for local connections. The exception is administrative commands.",
|
||||
"edt_conf_net_localApiAuth_title": "Local API Authentication",
|
||||
"edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict the access to the API through the internet to certain IP's.",
|
||||
"edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP's",
|
||||
"edt_conf_net_restirctedInternetAccessAPI_expl": "You can restrict API requests over the Internet to only those IP addresses on the whitelist.",
|
||||
"edt_conf_net_restirctedInternetAccessAPI_title": "Restrict to IP addresses",
|
||||
"edt_conf_os_events_lockEnable_title": "Listen to lock events",
|
||||
"edt_conf_os_events_lockEnable_expl": "Listen to screen lock/unlock events",
|
||||
"edt_conf_os_events_suspendEnable_title": "Listen to suspend events",
|
||||
|
@ -73,26 +73,30 @@ $(document).ready(function () {
|
||||
//End language selection
|
||||
|
||||
$(window.hyperion).on("cmd-authorize-tokenRequest cmd-authorize-getPendingTokenRequests", function (event) {
|
||||
var val = event.response.info;
|
||||
if (Array.isArray(event.response.info)) {
|
||||
if (event.response.info.length == 0) {
|
||||
return
|
||||
}
|
||||
val = event.response.info[0]
|
||||
if (val.comment == '')
|
||||
$('#modal_dialog').modal('hide');
|
||||
}
|
||||
|
||||
showInfoDialog("grantToken", $.i18n('conf_network_tok_grantT'), $.i18n('conf_network_tok_grantMsg') + '<br><span style="font-weight:bold">App: ' + val.comment + '</span><br><span style="font-weight:bold">Code: ' + val.id + '</span>')
|
||||
$("#tok_grant_acc").off().on('click', function () {
|
||||
tokenList.push(val)
|
||||
// forward event, in case we need to rebuild the list now
|
||||
$(window.hyperion).trigger({ type: "build-token-list" });
|
||||
requestHandleTokenRequest(val.id, true)
|
||||
});
|
||||
$("#tok_deny_acc").off().on('click', function () {
|
||||
requestHandleTokenRequest(val.id, false)
|
||||
});
|
||||
if (event.response && event.response.info !== undefined) {
|
||||
var val = event.response.info;
|
||||
|
||||
if (Array.isArray(event.response.info)) {
|
||||
if (event.response.info.length == 0) {
|
||||
return
|
||||
}
|
||||
val = event.response.info[0]
|
||||
if (val.comment == '')
|
||||
$('#modal_dialog').modal('hide');
|
||||
}
|
||||
|
||||
showInfoDialog("grantToken", $.i18n('conf_network_tok_grantT'), $.i18n('conf_network_tok_grantMsg') + '<br><span style="font-weight:bold">App: ' + val.comment + '</span><br><span style="font-weight:bold">Code: ' + val.id + '</span>')
|
||||
$("#tok_grant_acc").off().on('click', function () {
|
||||
tokenList.push(val)
|
||||
// forward event, in case we need to rebuild the list now
|
||||
$(window.hyperion).trigger({ type: "build-token-list" });
|
||||
requestHandleTokenRequest(val.id, true)
|
||||
});
|
||||
$("#tok_deny_acc").off().on('click', function () {
|
||||
requestHandleTokenRequest(val.id, false)
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$(window.hyperion).one("cmd-authorize-getTokenList", function (event) {
|
||||
@ -186,21 +190,12 @@ $(document).ready(function () {
|
||||
}
|
||||
});
|
||||
|
||||
$(window.hyperion).on("cmd-authorize-adminRequired", function (event) {
|
||||
//Check if a admin login is required.
|
||||
//If yes: check if default pw is set. If no: go ahead to get server config and render page
|
||||
if (event.response.info.adminRequired === true)
|
||||
requestRequiresDefaultPasswortChange();
|
||||
else
|
||||
requestServerConfigSchema();
|
||||
});
|
||||
|
||||
$(window.hyperion).on("error", function (event) {
|
||||
//If we are getting an error "No Authorization" back with a set loginToken we will forward to new Login (Token is expired.
|
||||
//e.g.: hyperiond was started new in the meantime)
|
||||
if (event.reason == "No Authorization" && getStorage("loginToken")) {
|
||||
removeStorage("loginToken");
|
||||
requestRequiresAdminAuth();
|
||||
requestRequiresDefaultPasswortChange();
|
||||
}
|
||||
else if (event.reason == "Selected Hyperion instance isn't running") {
|
||||
//Switch to default instance
|
||||
@ -211,7 +206,7 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
$(window.hyperion).on("open", function (event) {
|
||||
requestRequiresAdminAuth();
|
||||
requestRequiresDefaultPasswortChange();
|
||||
});
|
||||
|
||||
$(window.hyperion).on("ready", function (event) {
|
||||
|
@ -3,10 +3,13 @@ var createdCont = false;
|
||||
var isScroll = true;
|
||||
|
||||
performTranslation();
|
||||
requestLoggingStop();
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
window.addEventListener('hashchange', function(event) {
|
||||
requestLoggingStop();
|
||||
});
|
||||
|
||||
requestLoggingStart();
|
||||
|
||||
$('#conf_cont').append(createOptPanel('fa-reorder', $.i18n("edt_conf_log_heading_title"), 'editor_container', 'btn_submit'));
|
||||
@ -178,9 +181,9 @@ $(document).ready(function () {
|
||||
if (!window.loggingHandlerInstalled) {
|
||||
window.loggingHandlerInstalled = true;
|
||||
|
||||
$(window.hyperion).on("cmd-logging-update", function (event) {
|
||||
$(window.hyperion).on("cmd-logmsg-update", function (event) {
|
||||
|
||||
var messages = (event.response.result.messages);
|
||||
var messages = (event.response.data.messages);
|
||||
|
||||
if (messages.length != 0) {
|
||||
if (!createdCont) {
|
||||
|
@ -213,13 +213,13 @@ $(document).ready(function () {
|
||||
for (var key in tokenList) {
|
||||
var lastUse = (tokenList[key].last_use) ? tokenList[key].last_use : "-";
|
||||
var btn = '<button id="tok' + tokenList[key].id + '" type="button" class="btn btn-danger">' + $.i18n('general_btn_delete') + '</button>';
|
||||
$('.tktbody').append(createTableRow([tokenList[key].comment, lastUse, btn], false, true));
|
||||
$('.tktbody').append(createTableRow([tokenList[key].id, tokenList[key].comment, lastUse, btn], false, true));
|
||||
$('#tok' + tokenList[key].id).off().on('click', handleDeleteToken);
|
||||
}
|
||||
}
|
||||
|
||||
createTable('tkthead', 'tktbody', 'tktable');
|
||||
$('.tkthead').html(createTableRow([$.i18n('conf_network_tok_cidhead'), $.i18n('conf_network_tok_lastuse'), $.i18n('general_btn_delete')], true, true));
|
||||
$('.tkthead').html(createTableRow([$.i18n('conf_network_tok_idhead'), $.i18n('conf_network_tok_cidhead'), $.i18n('conf_network_tok_lastuse'), $.i18n('general_btn_delete')], true, true));
|
||||
buildTokenList();
|
||||
|
||||
function handleDeleteToken(e) {
|
||||
|
@ -177,6 +177,7 @@ function sendToHyperion(command, subcommand, msg)
|
||||
else
|
||||
msg = "";
|
||||
|
||||
window.wsTan = Math.floor(Math.random() * 1000)
|
||||
window.websocket.send('{"command":"'+command+'", "tan":'+window.wsTan+subcommand+msg+'}');
|
||||
}
|
||||
|
||||
@ -187,7 +188,7 @@ function sendToHyperion(command, subcommand, msg)
|
||||
// data: The json data as Object
|
||||
// tan: The optional tan, default 1. If the tan is -1, we skip global response error handling
|
||||
// Returns data of response or false if timeout
|
||||
async function sendAsyncToHyperion (command, subcommand, data, tan = 1) {
|
||||
async function sendAsyncToHyperion (command, subcommand, data, tan = Math.floor(Math.random() * 1000) ) {
|
||||
let obj = { command, tan }
|
||||
if (subcommand) {Object.assign(obj, {subcommand})}
|
||||
if (data) { Object.assign(obj, data) }
|
||||
@ -486,38 +487,38 @@ async function requestLedDeviceDiscovery(type, params)
|
||||
{
|
||||
let data = { ledDeviceType: type, params: params };
|
||||
|
||||
return sendAsyncToHyperion("leddevice", "discover", data, Math.floor(Math.random() * 1000) );
|
||||
return sendAsyncToHyperion("leddevice", "discover", data);
|
||||
}
|
||||
|
||||
async function requestLedDeviceProperties(type, params)
|
||||
{
|
||||
let data = { ledDeviceType: type, params: params };
|
||||
|
||||
return sendAsyncToHyperion("leddevice", "getProperties", data, Math.floor(Math.random() * 1000));
|
||||
return sendAsyncToHyperion("leddevice", "getProperties", data);
|
||||
}
|
||||
|
||||
function requestLedDeviceIdentification(type, params)
|
||||
{
|
||||
let data = { ledDeviceType: type, params: params };
|
||||
|
||||
return sendAsyncToHyperion("leddevice", "identify", data, Math.floor(Math.random() * 1000));
|
||||
return sendAsyncToHyperion("leddevice", "identify", data);
|
||||
}
|
||||
|
||||
async function requestLedDeviceAddAuthorization(type, params) {
|
||||
let data = { ledDeviceType: type, params: params };
|
||||
|
||||
return sendAsyncToHyperion("leddevice", "addAuthorization", data, Math.floor(Math.random() * 1000));
|
||||
return sendAsyncToHyperion("leddevice", "addAuthorization", data);
|
||||
}
|
||||
|
||||
async function requestInputSourcesDiscovery(type, params) {
|
||||
let data = { sourceType: type, params: params };
|
||||
|
||||
return sendAsyncToHyperion("inputsource", "discover", data, Math.floor(Math.random() * 1000));
|
||||
return sendAsyncToHyperion("inputsource", "discover", data);
|
||||
}
|
||||
|
||||
async function requestServiceDiscovery(type, params) {
|
||||
let data = { serviceType: type, params: params };
|
||||
|
||||
return sendAsyncToHyperion("service", "discover", data, Math.floor(Math.random() * 1000));
|
||||
return sendAsyncToHyperion("service", "discover", data);
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ $(document).ready(function () {
|
||||
$("body").get(0).style.setProperty("--background-var", "none");
|
||||
}
|
||||
else {
|
||||
printLedsToCanvas(event.response.result.leds)
|
||||
printLedsToCanvas(event.response.data.leds)
|
||||
$("body").get(0).style.setProperty("--background-var", "url(" + ($('#leds_preview_canv')[0]).toDataURL("image/jpg") + ") no-repeat top left");
|
||||
}
|
||||
});
|
||||
@ -275,7 +275,7 @@ $(document).ready(function () {
|
||||
}
|
||||
}
|
||||
else {
|
||||
var imageData = (event.response.result.image);
|
||||
var imageData = (event.response.data.image);
|
||||
|
||||
var image = new Image();
|
||||
image.onload = function () {
|
||||
|
@ -319,9 +319,9 @@ function showInfoDialog(type, header, message) {
|
||||
});
|
||||
|
||||
$(document).on('click', '[data-dismiss-modal]', function () {
|
||||
var target = $(this).attr('data-dismiss-modal');
|
||||
$.find(target).modal('hide');
|
||||
});
|
||||
var target = $(this).data('dismiss-modal');
|
||||
$($.find(target)).modal('hide');
|
||||
});
|
||||
}
|
||||
|
||||
function createHintH(type, text, container) {
|
||||
|
@ -220,9 +220,7 @@
|
||||
"internetAccessAPI": false,
|
||||
"restirctedInternetAccessAPI": false,
|
||||
"ipWhitelist": [],
|
||||
"apiAuth": true,
|
||||
"localApiAuth": false,
|
||||
"localAdminAuth": true
|
||||
"localApiAuth": false
|
||||
},
|
||||
|
||||
"ledConfig": {
|
||||
|
122
doc/development/JSON-API _Commands_Overview.md
Normal file
122
doc/development/JSON-API _Commands_Overview.md
Normal file
@ -0,0 +1,122 @@
|
||||
# JSON-API Commands Overview
|
||||
|
||||
## Commands & Sub-Commands
|
||||
|
||||
List of commands and related sub-commands which can be used via JSON-API requests.
|
||||
|
||||
_Authorization (via password or bearer token)_
|
||||
|
||||
**No** - No authorization required<br>
|
||||
**Yes** - Authorization required, but can be disabled for local network calls<br>
|
||||
**Admin**: Authorization is always required
|
||||
|
||||
_Instance specific_
|
||||
|
||||
**Yes** - A specific instance can be addressed<br>
|
||||
**Multi** - Multiple instances can be addressed via one request<br>
|
||||
**No** - The command is not instance related
|
||||
|
||||
_http/s Support_
|
||||
|
||||
**Yes** - Command can be used by individual http/s requests<br>
|
||||
**No** - Applies only to WebSocket or http/s sessions
|
||||
|
||||
| Command | Sub-Command | Authorization | Instance specific | http/s Support |
|
||||
|:---------------|:------------------------|:--------------|:------------------|:---------------|
|
||||
| adjustment | - | Yes | Multi | Yes |
|
||||
| authorize | adminRequired | No | No | Yes |
|
||||
| authorize | answerRequest | Admin | No | No |
|
||||
| authorize | createToken | Admin | No | No |
|
||||
| authorize | deleteToken | Admin | No | Yes |
|
||||
| authorize | getPendingTokenRequests | Admin | No | No |
|
||||
| authorize | getTokenList | Admin | No | Yes |
|
||||
| authorize | login | No | No | No |
|
||||
| authorize | logout | No | No | No |
|
||||
| authorize | newPassword | Admin | No | Yes |
|
||||
| authorize | newPasswordRequired | No | No | Yes |
|
||||
| authorize | renameToken | Admin | No | Yes |
|
||||
| authorize | requestToken | No | No | Yes |
|
||||
| authorize | tokenRequired | No | No | Yes |
|
||||
| clear | - | Yes | Multi | Yes |
|
||||
| clearall | - | Yes | Multi | Yes |
|
||||
| color | - | Yes | Multi | Yes |
|
||||
| componentstate | - | Yes | Multi | Yes |
|
||||
| config | getconfig | Admin | Yes | Yes |
|
||||
| config | getschema | Admin | Yes | Yes |
|
||||
| config | reload | Admin | Yes | Yes |
|
||||
| config | restoreconfig | Admin | Yes | Yes |
|
||||
| config | setconfig | Admin | Yes | Yes |
|
||||
| correction | - | Yes | Yes | Yes |
|
||||
| create-effect | - | Yes | Yes | Yes |
|
||||
| delete-effect | - | Yes | Yes | Yes |
|
||||
| effect | - | Yes | Multi | Yes |
|
||||
| image | - | Yes | Multi | Yes |
|
||||
| inputsource | discover | Yes | No | Yes |
|
||||
| inputsource | getProperties | Yes | No | Yes |
|
||||
| instance | createInstance | Admin | No | Yes |
|
||||
| instance | deleteInstance | Admin | No | Yes |
|
||||
| instance | saveName | Admin | No | Yes |
|
||||
| instance | startInstance | Yes | No | Yes |
|
||||
| instance | stopInstance | Yes | No | Yes |
|
||||
| instance | switchTo | Yes | No | Yes |
|
||||
| ledcolors | imagestream-start | Yes | Yes | Yes |
|
||||
| ledcolors | imagestream-stop | Yes | Yes | Yes |
|
||||
| ledcolors | ledstream-start | Yes | Yes | Yes |
|
||||
| ledcolors | ledstream-stop | Yes | Yes | Yes |
|
||||
| leddevice | addAuthorization | Yes | Yes | Yes |
|
||||
| leddevice | discover | Yes | Yes | Yes |
|
||||
| leddevice | getProperties | Yes | Yes | Yes |
|
||||
| leddevice | identify | Yes | Yes | Yes |
|
||||
| logging | start | Yes | No | Yes |
|
||||
| logging | stop | Yes | No | Yes |
|
||||
| processing | - | Yes | Multi | Yes |
|
||||
| serverinfo | - | Yes | Yes | Yes |
|
||||
| serverinfo | getInfo | Yes | Yes | Yes |
|
||||
| serverinfo | subscribe | Yes | Yes | No |
|
||||
| serverinfo | unsubscribe | Yes | Yes | No |
|
||||
| serverinfo | getSubscriptions | Yes | Yes | No |
|
||||
| serverinfo | getSubscriptionCommands | No | No | No |
|
||||
| service | discover | Yes | No | Yes |
|
||||
| sourceselect | - | Yes | Multi | Yes |
|
||||
| sysinfo | - | Yes | No | Yes |
|
||||
| system | restart | Yes | No | Yes |
|
||||
| system | resume | Yes | No | Yes |
|
||||
| system | suspend | Yes | No | Yes |
|
||||
| system | toggleSuspend | Yes | No | Yes |
|
||||
| system | idle | Yes | No | Yes |
|
||||
| system | toggleIdle | Yes | No | Yes |
|
||||
| temperature | - | Yes | Yes | Yes |
|
||||
| transform | - | Yes | Yes | Yes |
|
||||
| videomode | - | Yes | No | Yes |
|
||||
|
||||
## Subscription updates
|
||||
|
||||
List of updates which can be subscribed to via the `serverinfo/subscribe`request.
|
||||
|
||||
_Instance specific_
|
||||
|
||||
**Yes** - A specific instance can be addressed<br>
|
||||
**No** - The command is not instance related
|
||||
|
||||
_in "all"_
|
||||
|
||||
**Yes** - Updates are subscribed using "all" as the command<br>
|
||||
**No** - Subscription is only triggered via JSON-API request
|
||||
|
||||
| Subscription Command | Instance specific | in "all" |
|
||||
|:-----------------------------|:------------------|:---------|
|
||||
| adjustment-update | Yes | Yes |
|
||||
| components-update | Yes | Yes |
|
||||
| effects-update | Yes | Yes |
|
||||
| event-update | No | Yes |
|
||||
| imageToLedMapping-update | Yes | Yes |
|
||||
| instance-update | Yes | Yes |
|
||||
| ledcolors-imagestream-update | Yes | No |
|
||||
| ledcolors-ledstream-update | Yes | No |
|
||||
| leds-update | Yes | Yes |
|
||||
| logmsg-update | No | No |
|
||||
| priorities-update | Yes | Yes |
|
||||
| settings-update | Yes | Yes |
|
||||
| token-update | No | Yes |
|
||||
| videomode-update | No | Yes |
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
332
include/api/JsonApiCommand.h
Normal file
332
include/api/JsonApiCommand.h
Normal 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
|
135
include/api/JsonApiSubscription.h
Normal file
135
include/api/JsonApiSubscription.h
Normal 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
|
@ -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
43
include/api/JsonInfo.h
Normal 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
|
@ -2,6 +2,9 @@
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include <utils/Components.h>
|
||||
|
||||
struct ImageCmdData
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
||||
|
58
include/grabber/GrabberConfig.h
Normal file
58
include/grabber/GrabberConfig.h
Normal 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
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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' )
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include <api/API.h>
|
||||
|
||||
// stl includes
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
|
||||
// Qt includes
|
||||
#include <QResource>
|
||||
@ -27,90 +25,91 @@
|
||||
// ledmapping int <> string transform methods
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
// api includes
|
||||
#include <api/JsonCB.h>
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
// Constants
|
||||
namespace {
|
||||
|
||||
const int IMAGE_HEIGHT_MAX = 2000;
|
||||
const int IMAGE_WIDTH_MAX = 2000;
|
||||
const int IMAGE_SCALE = 2000;
|
||||
}
|
||||
|
||||
API::API(Logger *log, bool localConnection, QObject *parent)
|
||||
: QObject(parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
qRegisterMetaType<int64_t>("int64_t");
|
||||
qRegisterMetaType<VideoMode>("VideoMode");
|
||||
qRegisterMetaType<std::map<int, registerData>>("std::map<int,registerData>");
|
||||
|
||||
// Init
|
||||
_log = log;
|
||||
_authManager = AuthManager::getInstance();
|
||||
// Init
|
||||
_log = log;
|
||||
_authManager = AuthManager::getInstance();
|
||||
_instanceManager = HyperionIManager::getInstance();
|
||||
_localConnection = localConnection;
|
||||
_localConnection = localConnection;
|
||||
|
||||
_authorized = false;
|
||||
_adminAuthorized = false;
|
||||
_authorized = false;
|
||||
_adminAuthorized = false;
|
||||
|
||||
_currInstanceIndex = 0;
|
||||
_currInstanceIndex = 0;
|
||||
|
||||
// connect to possible token responses that has been requested
|
||||
connect(_authManager, &AuthManager::tokenResponse, [=] (bool success, QObject *caller, const QString &token, const QString &comment, const QString &id, const int &tan)
|
||||
{
|
||||
if (this == caller)
|
||||
emit onTokenResponse(success, token, comment, id, tan);
|
||||
});
|
||||
// connect to possible token responses that has been requested
|
||||
connect(_authManager, &AuthManager::tokenResponse, this, [=] (bool success, const QObject *caller, const QString &token, const QString &comment, const QString &tokenId, const int &tan)
|
||||
{
|
||||
if (this == caller)
|
||||
{
|
||||
emit onTokenResponse(success, token, comment, tokenId, tan);
|
||||
}
|
||||
});
|
||||
|
||||
// connect to possible startInstance responses that has been requested
|
||||
connect(_instanceManager, &HyperionIManager::startInstanceResponse, [=] (QObject *caller, const int &tan)
|
||||
{
|
||||
if (this == caller)
|
||||
emit onStartInstanceResponse(tan);
|
||||
});
|
||||
connect(_instanceManager, &HyperionIManager::startInstanceResponse, this, [=] (const QObject *caller, const int &tan)
|
||||
{
|
||||
if (this == caller)
|
||||
{
|
||||
emit onStartInstanceResponse(tan);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void API::init()
|
||||
{
|
||||
_hyperion = _instanceManager->getHyperionInstance(0);
|
||||
_authorized = false;
|
||||
|
||||
bool apiAuthRequired = _authManager->isAuthRequired();
|
||||
|
||||
// For security we block external connections if default PW is set
|
||||
if (!_localConnection && API::hasHyperionDefaultPw())
|
||||
{
|
||||
emit forceClose();
|
||||
}
|
||||
// if this is localConnection and network allows unauth locals, set authorized flag
|
||||
if (apiAuthRequired && _localConnection)
|
||||
// For security we block external connections, if default PW is set
|
||||
if (!_localConnection && API::hasHyperionDefaultPw())
|
||||
{
|
||||
_authorized = !_authManager->isLocalAuthRequired();
|
||||
Warning(_log, "Non local network connect attempt identified, but default Hyperion passwort set! - Reject connection.");
|
||||
emit forceClose();
|
||||
}
|
||||
|
||||
// admin access is allowed, when the connection is local and the option for local admin isn't set. Con: All local connections get full access
|
||||
if (_localConnection)
|
||||
{
|
||||
_adminAuthorized = !_authManager->isLocalAdminAuthRequired();
|
||||
// just in positive direction
|
||||
if (_adminAuthorized)
|
||||
// if this is localConnection and network allows unauth locals
|
||||
if ( _localConnection && !_authManager->isLocalAuthRequired())
|
||||
{
|
||||
_authorized = true;
|
||||
}
|
||||
|
||||
// // admin access is only allowed after login via user & password or via authorization via token.
|
||||
_adminAuthorized = false;
|
||||
}
|
||||
|
||||
void API::setColor(int priority, const std::vector<uint8_t> &ledColors, int timeout_ms, const QString &origin, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
if (ledColors.size() % 3 == 0)
|
||||
{
|
||||
std::vector<ColorRgb> fledColors;
|
||||
for (unsigned i = 0; i < ledColors.size(); i += 3)
|
||||
{
|
||||
_authorized = true;
|
||||
fledColors.emplace_back(ColorRgb{ledColors[i], ledColors[i + 1], ledColors[i + 2]});
|
||||
}
|
||||
}
|
||||
QMetaObject::invokeMethod(_hyperion, "setColor", Qt::QueuedConnection, Q_ARG(int, priority), Q_ARG(std::vector<ColorRgb>, fledColors), Q_ARG(int, timeout_ms), Q_ARG(QString, origin));
|
||||
}
|
||||
}
|
||||
|
||||
void API::setColor(int priority, const std::vector<uint8_t> &ledColors, int timeout_ms, const QString &origin, hyperion::Components callerComp)
|
||||
bool API::setImage(ImageCmdData &data, hyperion::Components comp, QString &replyMsg, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
std::vector<ColorRgb> fledColors;
|
||||
if (ledColors.size() % 3 == 0)
|
||||
{
|
||||
for (unsigned i = 0; i < ledColors.size(); i += 3)
|
||||
{
|
||||
fledColors.emplace_back(ColorRgb{ledColors[i], ledColors[i + 1], ledColors[i + 2]});
|
||||
}
|
||||
QMetaObject::invokeMethod(_hyperion, "setColor", Qt::QueuedConnection, Q_ARG(int, priority), Q_ARG(std::vector<ColorRgb>, fledColors), Q_ARG(int, timeout_ms), Q_ARG(QString, origin));
|
||||
}
|
||||
}
|
||||
|
||||
bool API::setImage(ImageCmdData &data, hyperion::Components comp, QString &replyMsg, hyperion::Components callerComp)
|
||||
{
|
||||
// truncate name length
|
||||
data.imgName.truncate(16);
|
||||
// truncate name length
|
||||
data.imgName.truncate(16);
|
||||
|
||||
if (!data.format.isEmpty())
|
||||
{
|
||||
@ -128,424 +127,475 @@ bool API::setImage(ImageCmdData &data, hyperion::Components comp, QString &reply
|
||||
}
|
||||
|
||||
QImage img = QImage::fromData(data.data, QSTRING_CSTR(data.format));
|
||||
if (img.isNull())
|
||||
{
|
||||
if (img.isNull())
|
||||
{
|
||||
replyMsg = "Failed to parse picture, the file might be corrupted or content does not match the given format [" + data.format + "]";
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// check for requested scale
|
||||
if (data.scale > 24)
|
||||
{
|
||||
if (img.height() > data.scale)
|
||||
{
|
||||
img = img.scaledToHeight(data.scale);
|
||||
}
|
||||
if (img.width() > data.scale)
|
||||
{
|
||||
img = img.scaledToWidth(data.scale);
|
||||
}
|
||||
}
|
||||
// check for requested scale
|
||||
if (data.scale > 24)
|
||||
{
|
||||
if (img.height() > data.scale)
|
||||
{
|
||||
img = img.scaledToHeight(data.scale);
|
||||
}
|
||||
if (img.width() > data.scale)
|
||||
{
|
||||
img = img.scaledToWidth(data.scale);
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to force a scale
|
||||
if (img.width() > 2000 || img.height() > 2000)
|
||||
{
|
||||
data.scale = 2000;
|
||||
if (img.height() > data.scale)
|
||||
{
|
||||
img = img.scaledToHeight(data.scale);
|
||||
}
|
||||
if (img.width() > data.scale)
|
||||
{
|
||||
img = img.scaledToWidth(data.scale);
|
||||
}
|
||||
}
|
||||
// check if we need to force a scale
|
||||
if (img.width() > IMAGE_WIDTH_MAX || img.height() > IMAGE_HEIGHT_MAX)
|
||||
{
|
||||
data.scale = IMAGE_SCALE;
|
||||
if (img.height() > data.scale)
|
||||
{
|
||||
img = img.scaledToHeight(data.scale);
|
||||
}
|
||||
if (img.width() > data.scale)
|
||||
{
|
||||
img = img.scaledToWidth(data.scale);
|
||||
}
|
||||
}
|
||||
|
||||
data.width = img.width();
|
||||
data.height = img.height();
|
||||
data.width = img.width();
|
||||
data.height = img.height();
|
||||
|
||||
// extract image
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
data.data.clear();
|
||||
data.data.reserve(img.width() * img.height() * 3);
|
||||
for (int i = 0; i < img.height(); ++i)
|
||||
{
|
||||
const QRgb *scanline = reinterpret_cast<const QRgb *>(img.scanLine(i));
|
||||
for (int j = 0; j < img.width(); ++j)
|
||||
{
|
||||
data.data.append((char)qRed(scanline[j]));
|
||||
data.data.append((char)qGreen(scanline[j]));
|
||||
data.data.append((char)qBlue(scanline[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check consistency of the size of the received data
|
||||
if (data.data.size() != data.width * data.height * 3)
|
||||
{
|
||||
replyMsg = "Size of image data does not match with the width and height";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// extract image
|
||||
img = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
||||
data.data.clear();
|
||||
data.data.reserve(static_cast<int>(img.width() * img.height() * 3));
|
||||
for (int i = 0; i < img.height(); ++i)
|
||||
{
|
||||
const QRgb *scanline = reinterpret_cast<const QRgb *>(img.scanLine(i));
|
||||
for (int j = 0; j < img.width(); ++j)
|
||||
{
|
||||
data.data.append(static_cast<char>(qRed(scanline[j])));
|
||||
data.data.append(static_cast<char>(qGreen(scanline[j])));
|
||||
data.data.append(static_cast<char>(qBlue(scanline[j])));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// check consistency of the size of the received data
|
||||
if (static_cast<size_t>(data.data.size()) != static_cast<size_t>(data.width) * static_cast<size_t>(data.height) * 3)
|
||||
{
|
||||
replyMsg = "Size of image data does not match with the width and height";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// copy image
|
||||
Image<ColorRgb> image(data.width, data.height);
|
||||
memcpy(image.memptr(), data.data.data(), data.data.size());
|
||||
// copy image
|
||||
Image<ColorRgb> image(data.width, data.height);
|
||||
memcpy(image.memptr(), data.data.data(), static_cast<size_t>(data.data.size()));
|
||||
|
||||
QMetaObject::invokeMethod(_hyperion, "registerInput", Qt::QueuedConnection, Q_ARG(int, data.priority), Q_ARG(hyperion::Components, comp), Q_ARG(QString, data.origin), Q_ARG(QString, data.imgName));
|
||||
QMetaObject::invokeMethod(_hyperion, "setInputImage", Qt::QueuedConnection, Q_ARG(int, data.priority), Q_ARG(Image<ColorRgb>, image), Q_ARG(int64_t, data.duration));
|
||||
QMetaObject::invokeMethod(_hyperion, "registerInput", Qt::QueuedConnection, Q_ARG(int, data.priority), Q_ARG(hyperion::Components, comp), Q_ARG(QString, data.origin), Q_ARG(QString, data.imgName));
|
||||
QMetaObject::invokeMethod(_hyperion, "setInputImage", Qt::QueuedConnection, Q_ARG(int, data.priority), Q_ARG(Image<ColorRgb>, image), Q_ARG(int64_t, data.duration));
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool API::clearPriority(int priority, QString &replyMsg, hyperion::Components callerComp)
|
||||
bool API::clearPriority(int priority, QString &replyMsg, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
if (priority < 0 || (priority > 0 && priority < 254))
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "clear", Qt::QueuedConnection, Q_ARG(int, priority));
|
||||
}
|
||||
else
|
||||
{
|
||||
replyMsg = QString("Priority %1 is not allowed to be cleared").arg(priority);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
if (priority < 0 || (priority > 0 && priority < PriorityMuxer::BG_PRIORITY))
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "clear", Qt::QueuedConnection, Q_ARG(int, priority));
|
||||
}
|
||||
else
|
||||
{
|
||||
replyMsg = QString("Priority %1 is not allowed to be cleared").arg(priority);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool API::setComponentState(const QString &comp, bool &compState, QString &replyMsg, hyperion::Components callerComp)
|
||||
bool API::setComponentState(const QString &comp, bool &compState, QString &replyMsg, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
Components component = stringToComponent(comp);
|
||||
Components component = stringToComponent(comp);
|
||||
|
||||
if (component != COMP_INVALID)
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "compStateChangeRequest", Qt::QueuedConnection, Q_ARG(hyperion::Components, component), Q_ARG(bool, compState));
|
||||
return true;
|
||||
}
|
||||
replyMsg = QString("Unknown component name: %1").arg(comp);
|
||||
return false;
|
||||
if (component != COMP_INVALID)
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "compStateChangeRequest", Qt::QueuedConnection, Q_ARG(hyperion::Components, component), Q_ARG(bool, compState));
|
||||
return true;
|
||||
}
|
||||
replyMsg = QString("Unknown component name: %1").arg(comp);
|
||||
return false;
|
||||
}
|
||||
|
||||
void API::setLedMappingType(int type, hyperion::Components callerComp)
|
||||
void API::setLedMappingType(int type, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setLedMappingType", Qt::QueuedConnection, Q_ARG(int, type));
|
||||
QMetaObject::invokeMethod(_hyperion, "setLedMappingType", Qt::QueuedConnection, Q_ARG(int, type));
|
||||
}
|
||||
|
||||
void API::setVideoMode(VideoMode mode, hyperion::Components callerComp)
|
||||
void API::setVideoMode(VideoMode mode, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setVideoMode", Qt::QueuedConnection, Q_ARG(VideoMode, mode));
|
||||
QMetaObject::invokeMethod(_hyperion, "setVideoMode", Qt::QueuedConnection, Q_ARG(VideoMode, mode));
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
bool API::setEffect(const EffectCmdData &dat, hyperion::Components callerComp)
|
||||
bool API::setEffect(const EffectCmdData &dat, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
int res;
|
||||
if (!dat.args.isEmpty())
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, res), Q_ARG(QString, dat.effectName), Q_ARG(QJsonObject, dat.args), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.pythonScript), Q_ARG(QString, dat.origin), Q_ARG(QString, dat.data));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, res), Q_ARG(QString, dat.effectName), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.origin));
|
||||
}
|
||||
int isStarted;
|
||||
if (!dat.args.isEmpty())
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, isStarted), Q_ARG(QString, dat.effectName), Q_ARG(QJsonObject, dat.args), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.pythonScript), Q_ARG(QString, dat.origin), Q_ARG(QString, dat.data));
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, isStarted), Q_ARG(QString, dat.effectName), Q_ARG(int, dat.priority), Q_ARG(int, dat.duration), Q_ARG(QString, dat.origin));
|
||||
}
|
||||
|
||||
return res >= 0;
|
||||
return isStarted >= 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
void API::setSourceAutoSelect(bool state, hyperion::Components callerComp)
|
||||
void API::setSourceAutoSelect(bool state, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setSourceAutoSelect", Qt::QueuedConnection, Q_ARG(bool, state));
|
||||
QMetaObject::invokeMethod(_hyperion, "setSourceAutoSelect", Qt::QueuedConnection, Q_ARG(bool, state));
|
||||
}
|
||||
|
||||
void API::setVisiblePriority(int priority, hyperion::Components callerComp)
|
||||
void API::setVisiblePriority(int priority, hyperion::Components /*callerComp*/)
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "setVisiblePriority", Qt::QueuedConnection, Q_ARG(int, priority));
|
||||
QMetaObject::invokeMethod(_hyperion, "setVisiblePriority", Qt::QueuedConnection, Q_ARG(int, priority));
|
||||
}
|
||||
|
||||
void API::registerInput(int priority, hyperion::Components component, const QString &origin, const QString &owner, hyperion::Components callerComp)
|
||||
{
|
||||
if (_activeRegisters.count(priority))
|
||||
_activeRegisters.erase(priority);
|
||||
if (_activeRegisters.count(priority) != 0)
|
||||
{
|
||||
_activeRegisters.erase(priority);
|
||||
}
|
||||
|
||||
_activeRegisters.insert({priority, registerData{component, origin, owner, callerComp}});
|
||||
_activeRegisters.insert({priority, registerData{component, origin, owner, callerComp}});
|
||||
|
||||
QMetaObject::invokeMethod(_hyperion, "registerInput", Qt::QueuedConnection, Q_ARG(int, priority), Q_ARG(hyperion::Components, component), Q_ARG(QString, origin), Q_ARG(QString, owner));
|
||||
QMetaObject::invokeMethod(_hyperion, "registerInput", Qt::QueuedConnection, Q_ARG(int, priority), Q_ARG(hyperion::Components, component), Q_ARG(QString, origin), Q_ARG(QString, owner));
|
||||
}
|
||||
|
||||
void API::unregisterInput(int priority)
|
||||
{
|
||||
if (_activeRegisters.count(priority))
|
||||
_activeRegisters.erase(priority);
|
||||
if (_activeRegisters.count(priority) != 0)
|
||||
{
|
||||
_activeRegisters.erase(priority);
|
||||
}
|
||||
}
|
||||
|
||||
bool API::setHyperionInstance(quint8 inst)
|
||||
{
|
||||
if (_currInstanceIndex == inst)
|
||||
return true;
|
||||
bool isRunning;
|
||||
QMetaObject::invokeMethod(_instanceManager, "IsInstanceRunning", Qt::DirectConnection, Q_RETURN_ARG(bool, isRunning), Q_ARG(quint8, inst));
|
||||
if (!isRunning)
|
||||
return false;
|
||||
if (_currInstanceIndex == inst)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
disconnect(_hyperion, 0, this, 0);
|
||||
QMetaObject::invokeMethod(_instanceManager, "getHyperionInstance", Qt::DirectConnection, Q_RETURN_ARG(Hyperion *, _hyperion), Q_ARG(quint8, inst));
|
||||
_currInstanceIndex = inst;
|
||||
return true;
|
||||
bool isRunning;
|
||||
QMetaObject::invokeMethod(_instanceManager, "IsInstanceRunning", Qt::DirectConnection, Q_RETURN_ARG(bool, isRunning), Q_ARG(quint8, inst));
|
||||
if (!isRunning)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
disconnect(_hyperion, nullptr, this, nullptr);
|
||||
QMetaObject::invokeMethod(_instanceManager, "getHyperionInstance", Qt::DirectConnection, Q_RETURN_ARG(Hyperion *, _hyperion), Q_ARG(quint8, inst));
|
||||
_currInstanceIndex = inst;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool API::isHyperionEnabled()
|
||||
{
|
||||
int res;
|
||||
QMetaObject::invokeMethod(_hyperion, "isComponentEnabled", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, res), Q_ARG(hyperion::Components, hyperion::COMP_ALL));
|
||||
return res > 0;
|
||||
int isEnabled;
|
||||
QMetaObject::invokeMethod(_hyperion, "isComponentEnabled", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, isEnabled), Q_ARG(hyperion::Components, hyperion::COMP_ALL));
|
||||
return isEnabled > 0;
|
||||
}
|
||||
|
||||
QVector<QVariantMap> API::getAllInstanceData()
|
||||
QVector<QVariantMap> API::getAllInstanceData() const
|
||||
{
|
||||
QVector<QVariantMap> vec;
|
||||
QMetaObject::invokeMethod(_instanceManager, "getInstanceData", Qt::DirectConnection, Q_RETURN_ARG(QVector<QVariantMap>, vec));
|
||||
return vec;
|
||||
QVector<QVariantMap> vec;
|
||||
QMetaObject::invokeMethod(_instanceManager, "getInstanceData", Qt::DirectConnection, Q_RETURN_ARG(QVector<QVariantMap>, vec));
|
||||
return vec;
|
||||
}
|
||||
|
||||
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);
|
||||
bool isStarted;
|
||||
(_instanceManager->thread() != this->thread())
|
||||
? QMetaObject::invokeMethod(_instanceManager, "startInstance", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isStarted), Q_ARG(quint8, index), Q_ARG(bool, false), Q_ARG(QObject*, this), Q_ARG(int, tan))
|
||||
: isStarted = _instanceManager->startInstance(index, false, this, tan);
|
||||
|
||||
return res;
|
||||
return isStarted;
|
||||
}
|
||||
|
||||
void API::stopInstance(quint8 index)
|
||||
{
|
||||
QMetaObject::invokeMethod(_instanceManager, "stopInstance", Qt::QueuedConnection, Q_ARG(quint8, index));
|
||||
QMetaObject::invokeMethod(_instanceManager, "stopInstance", Qt::QueuedConnection, Q_ARG(quint8, index));
|
||||
}
|
||||
|
||||
bool API::deleteInstance(quint8 index, QString &replyMsg)
|
||||
{
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QMetaObject::invokeMethod(_instanceManager, "deleteInstance", Qt::QueuedConnection, Q_ARG(quint8, index));
|
||||
return true;
|
||||
}
|
||||
replyMsg = NO_AUTH;
|
||||
return false;
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QMetaObject::invokeMethod(_instanceManager, "deleteInstance", Qt::QueuedConnection, Q_ARG(quint8, index));
|
||||
return true;
|
||||
}
|
||||
replyMsg = NO_AUTHORIZATION;
|
||||
return false;
|
||||
}
|
||||
|
||||
QString API::createInstance(const QString &name)
|
||||
{
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
bool success;
|
||||
QMetaObject::invokeMethod(_instanceManager, "createInstance", Qt::DirectConnection, Q_RETURN_ARG(bool, success), Q_ARG(QString, name));
|
||||
if (!success)
|
||||
return QString("Instance name '%1' is already in use").arg(name);
|
||||
|
||||
return "";
|
||||
}
|
||||
return NO_AUTH;
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
bool success;
|
||||
QMetaObject::invokeMethod(_instanceManager, "createInstance", Qt::DirectConnection, Q_RETURN_ARG(bool, success), Q_ARG(QString, name));
|
||||
if (!success)
|
||||
{
|
||||
return QString("Instance name '%1' is already in use").arg(name);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
return NO_AUTHORIZATION;
|
||||
}
|
||||
|
||||
QString API::setInstanceName(quint8 index, const QString &name)
|
||||
{
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QMetaObject::invokeMethod(_instanceManager, "saveName", Qt::QueuedConnection, Q_ARG(quint8, index), Q_ARG(QString, name));
|
||||
return "";
|
||||
}
|
||||
return NO_AUTH;
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QMetaObject::invokeMethod(_instanceManager, "saveName", Qt::QueuedConnection, Q_ARG(quint8, index), Q_ARG(QString, name));
|
||||
return "";
|
||||
}
|
||||
return NO_AUTHORIZATION;
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
QString API::deleteEffect(const QString &name)
|
||||
{
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QString res;
|
||||
QMetaObject::invokeMethod(_hyperion, "deleteEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, res), Q_ARG(QString, name));
|
||||
return res;
|
||||
}
|
||||
return NO_AUTH;
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QString res;
|
||||
QMetaObject::invokeMethod(_hyperion, "deleteEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, res), Q_ARG(QString, name));
|
||||
return res;
|
||||
}
|
||||
return NO_AUTHORIZATION;
|
||||
}
|
||||
|
||||
QString API::saveEffect(const QJsonObject &data)
|
||||
{
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QString res;
|
||||
QMetaObject::invokeMethod(_hyperion, "saveEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, res), Q_ARG(QJsonObject, data));
|
||||
return res;
|
||||
}
|
||||
return NO_AUTH;
|
||||
if (_adminAuthorized)
|
||||
{
|
||||
QString res;
|
||||
QMetaObject::invokeMethod(_hyperion, "saveEffect", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, res), Q_ARG(QJsonObject, data));
|
||||
return res;
|
||||
}
|
||||
return NO_AUTHORIZATION;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool API::saveSettings(const QJsonObject &data)
|
||||
{
|
||||
bool rc = true;
|
||||
if (!_adminAuthorized)
|
||||
bool isSaved {true};
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
rc = false;
|
||||
isSaved = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "saveSettings", Qt::DirectConnection, Q_RETURN_ARG(bool, rc), Q_ARG(QJsonObject, data), Q_ARG(bool, true));
|
||||
QMetaObject::invokeMethod(_hyperion, "saveSettings", Qt::DirectConnection, Q_RETURN_ARG(bool, isSaved), Q_ARG(QJsonObject, data), Q_ARG(bool, true));
|
||||
}
|
||||
return rc;
|
||||
return isSaved;
|
||||
}
|
||||
|
||||
bool API::restoreSettings(const QJsonObject &data)
|
||||
{
|
||||
bool rc = true;
|
||||
bool isRestored {true};
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
rc = false;
|
||||
isRestored = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(_hyperion, "restoreSettings", Qt::DirectConnection, Q_RETURN_ARG(bool, rc), Q_ARG(QJsonObject, data), Q_ARG(bool, true));
|
||||
QMetaObject::invokeMethod(_hyperion, "restoreSettings", Qt::DirectConnection, Q_RETURN_ARG(bool, isRestored), Q_ARG(QJsonObject, data), Q_ARG(bool, true));
|
||||
}
|
||||
return rc;
|
||||
return isRestored;
|
||||
}
|
||||
|
||||
bool API::updateHyperionPassword(const QString &password, const QString &newPassword)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return false;
|
||||
bool res;
|
||||
QMetaObject::invokeMethod(_authManager, "updateUserPassword", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, res), Q_ARG(QString, "Hyperion"), Q_ARG(QString, password), Q_ARG(QString, newPassword));
|
||||
return res;
|
||||
bool isPwUpdated {true};
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
isPwUpdated = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
QMetaObject::invokeMethod(_authManager, "updateUserPassword", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isPwUpdated), Q_ARG(QString, DEFAULT_USER), Q_ARG(QString, password), Q_ARG(QString, newPassword));
|
||||
}
|
||||
return isPwUpdated;
|
||||
}
|
||||
|
||||
QString API::createToken(const QString &comment, AuthManager::AuthDefinition &def)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return NO_AUTH;
|
||||
if (comment.isEmpty())
|
||||
return "comment is empty";
|
||||
QMetaObject::invokeMethod(_authManager, "createToken", Qt::BlockingQueuedConnection, Q_RETURN_ARG(AuthManager::AuthDefinition, def), Q_ARG(QString, comment));
|
||||
return "";
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
return NO_AUTHORIZATION;
|
||||
}
|
||||
|
||||
if (comment.isEmpty())
|
||||
{
|
||||
return "Missing token comment";
|
||||
}
|
||||
QMetaObject::invokeMethod(_authManager, "createToken", Qt::BlockingQueuedConnection, Q_RETURN_ARG(AuthManager::AuthDefinition, def), Q_ARG(QString, comment));
|
||||
return "";
|
||||
}
|
||||
|
||||
QString API::renameToken(const QString &id, const QString &comment)
|
||||
QString API::renameToken(const QString &tokenId, const QString &comment)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return NO_AUTH;
|
||||
if (comment.isEmpty() || id.isEmpty())
|
||||
return "Empty comment or id";
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
return NO_AUTHORIZATION;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(_authManager, "renameToken", Qt::QueuedConnection, Q_ARG(QString, id), Q_ARG(QString, comment));
|
||||
return "";
|
||||
if (comment.isEmpty())
|
||||
{
|
||||
return "Missing token comment";
|
||||
}
|
||||
|
||||
if (tokenId.isEmpty()) {
|
||||
return "Missing token id";
|
||||
}
|
||||
|
||||
bool isTokenRenamed {false};
|
||||
QMetaObject::invokeMethod(_authManager, "renameToken", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isTokenRenamed), Q_ARG(QString, tokenId), Q_ARG(QString, comment));
|
||||
|
||||
return (!isTokenRenamed) ? "Token does not exist" : "";
|
||||
}
|
||||
|
||||
QString API::deleteToken(const QString &id)
|
||||
QString API::deleteToken(const QString &tokenId)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return NO_AUTH;
|
||||
if (id.isEmpty())
|
||||
return "Empty id";
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
return NO_AUTHORIZATION;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(_authManager, "deleteToken", Qt::QueuedConnection, Q_ARG(QString, id));
|
||||
return "";
|
||||
if (tokenId.isEmpty())
|
||||
{
|
||||
return "Missing token id";
|
||||
}
|
||||
|
||||
bool isTokenDeleted {false};
|
||||
QMetaObject::invokeMethod(_authManager, "deleteToken", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isTokenDeleted), Q_ARG(QString, tokenId));
|
||||
|
||||
return (!isTokenDeleted) ? "Token does not exist" : "";
|
||||
}
|
||||
|
||||
void API::setNewTokenRequest(const QString &comment, const QString &id, const int &tan)
|
||||
void API::setNewTokenRequest(const QString &comment, const QString &tokenId, const int &tan)
|
||||
{
|
||||
QMetaObject::invokeMethod(_authManager, "setNewTokenRequest", Qt::QueuedConnection, Q_ARG(QObject *, this), Q_ARG(QString, comment), Q_ARG(QString, id), Q_ARG(int, tan));
|
||||
QMetaObject::invokeMethod(_authManager, "setNewTokenRequest", Qt::QueuedConnection, Q_ARG(QObject *, this), Q_ARG(QString, comment), Q_ARG(QString, tokenId), Q_ARG(int, tan));
|
||||
}
|
||||
|
||||
void API::cancelNewTokenRequest(const QString &comment, const QString &id)
|
||||
void API::cancelNewTokenRequest(const QString &comment, const QString &tokenId)
|
||||
{
|
||||
QMetaObject::invokeMethod(_authManager, "cancelNewTokenRequest", Qt::QueuedConnection, Q_ARG(QObject *, this), Q_ARG(QString, comment), Q_ARG(QString, id));
|
||||
QMetaObject::invokeMethod(_authManager, "cancelNewTokenRequest", Qt::QueuedConnection, Q_ARG(QObject *, this), Q_ARG(QString, comment), Q_ARG(QString, tokenId));
|
||||
}
|
||||
|
||||
bool API::handlePendingTokenRequest(const QString &id, bool accept)
|
||||
bool API::handlePendingTokenRequest(const QString &tokenId, bool accept)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return false;
|
||||
QMetaObject::invokeMethod(_authManager, "handlePendingTokenRequest", Qt::QueuedConnection, Q_ARG(QString, id), Q_ARG(bool, accept));
|
||||
return true;
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QMetaObject::invokeMethod(_authManager, "handlePendingTokenRequest", Qt::QueuedConnection, Q_ARG(QString, tokenId), Q_ARG(bool, accept));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool API::getTokenList(QVector<AuthManager::AuthDefinition> &def)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return false;
|
||||
QMetaObject::invokeMethod(_authManager, "getTokenList", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVector<AuthManager::AuthDefinition>, def));
|
||||
return true;
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QMetaObject::invokeMethod(_authManager, "getTokenList", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVector<AuthManager::AuthDefinition>, def));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool API::getPendingTokenRequests(QVector<AuthManager::AuthDefinition> &map)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return false;
|
||||
QMetaObject::invokeMethod(_authManager, "getPendingRequests", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVector<AuthManager::AuthDefinition>, map));
|
||||
return true;
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QMetaObject::invokeMethod(_authManager, "getPendingRequests", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QVector<AuthManager::AuthDefinition>, map));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool API::isUserTokenAuthorized(const QString &userToken)
|
||||
{
|
||||
bool res;
|
||||
QMetaObject::invokeMethod(_authManager, "isUserTokenAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, res), Q_ARG(QString, "Hyperion"), Q_ARG(QString, userToken));
|
||||
if (res)
|
||||
{
|
||||
_authorized = true;
|
||||
_adminAuthorized = true;
|
||||
// Listen for ADMIN ACCESS protected signals
|
||||
connect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest, Qt::UniqueConnection);
|
||||
}
|
||||
return res;
|
||||
QMetaObject::invokeMethod(_authManager, "isUserTokenAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, _authorized), Q_ARG(QString, DEFAULT_USER), Q_ARG(QString, userToken));
|
||||
_adminAuthorized = _authorized;
|
||||
|
||||
if (_authorized)
|
||||
{
|
||||
// Listen for ADMIN ACCESS protected signals
|
||||
connect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest);
|
||||
}
|
||||
return _authorized;
|
||||
}
|
||||
|
||||
bool API::getUserToken(QString &userToken)
|
||||
{
|
||||
if (!_adminAuthorized)
|
||||
return false;
|
||||
QMetaObject::invokeMethod(_authManager, "getUserToken", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, userToken));
|
||||
return true;
|
||||
if (!_adminAuthorized)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
QMetaObject::invokeMethod(_authManager, "getUserToken", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, userToken));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool API::isTokenAuthorized(const QString &token)
|
||||
{
|
||||
(_authManager->thread() != this->thread())
|
||||
? QMetaObject::invokeMethod(_authManager, "isTokenAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, _authorized), Q_ARG(QString, token))
|
||||
: _authorized = _authManager->isTokenAuthorized(token);
|
||||
? QMetaObject::invokeMethod(_authManager, "isTokenAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, _authorized), Q_ARG(QString, token))
|
||||
: _authorized = _authManager->isTokenAuthorized(token);
|
||||
_adminAuthorized = _authorized;
|
||||
|
||||
return _authorized;
|
||||
return _authorized;
|
||||
}
|
||||
|
||||
bool API::isUserAuthorized(const QString &password)
|
||||
{
|
||||
bool res;
|
||||
QMetaObject::invokeMethod(_authManager, "isUserAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, res), Q_ARG(QString, "Hyperion"), Q_ARG(QString, password));
|
||||
if (res)
|
||||
{
|
||||
_authorized = true;
|
||||
_adminAuthorized = true;
|
||||
// Listen for ADMIN ACCESS protected signals
|
||||
connect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest, Qt::UniqueConnection);
|
||||
}
|
||||
return res;
|
||||
bool isUserAuthorized;
|
||||
QMetaObject::invokeMethod(_authManager, "isUserAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isUserAuthorized), Q_ARG(QString, DEFAULT_USER), Q_ARG(QString, password));
|
||||
if (isUserAuthorized)
|
||||
{
|
||||
_authorized = true;
|
||||
_adminAuthorized = true;
|
||||
|
||||
// Listen for ADMIN ACCESS protected signals
|
||||
connect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest);
|
||||
}
|
||||
else
|
||||
{
|
||||
disconnect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest);
|
||||
}
|
||||
return isUserAuthorized;
|
||||
}
|
||||
|
||||
bool API::hasHyperionDefaultPw()
|
||||
{
|
||||
bool res;
|
||||
QMetaObject::invokeMethod(_authManager, "isUserAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, res), Q_ARG(QString, "Hyperion"), Q_ARG(QString, "hyperion"));
|
||||
return res;
|
||||
bool isDefaultPassort;
|
||||
QMetaObject::invokeMethod(_authManager, "isUserAuthorized", Qt::BlockingQueuedConnection, Q_RETURN_ARG(bool, isDefaultPassort), Q_ARG(QString, DEFAULT_USER), Q_ARG(QString, DEFAULT_PASSWORD));
|
||||
return isDefaultPassort;
|
||||
}
|
||||
|
||||
void API::logout()
|
||||
{
|
||||
_authorized = false;
|
||||
_adminAuthorized = false;
|
||||
// Stop listenig for ADMIN ACCESS protected signals
|
||||
disconnect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest);
|
||||
stopDataConnectionss();
|
||||
}
|
||||
|
||||
void API::stopDataConnectionss()
|
||||
{
|
||||
_authorized = false;
|
||||
_adminAuthorized = false;
|
||||
// Stop listenig for ADMIN ACCESS protected signals
|
||||
disconnect(_authManager, &AuthManager::newPendingTokenRequest, this, &API::onPendingTokenRequest);
|
||||
stopDataConnections();
|
||||
}
|
||||
|
@ -2,10 +2,14 @@ add_library(hyperion-api
|
||||
${CMAKE_SOURCE_DIR}/include/api/apiStructs.h
|
||||
${CMAKE_SOURCE_DIR}/include/api/API.h
|
||||
${CMAKE_SOURCE_DIR}/include/api/JsonAPI.h
|
||||
${CMAKE_SOURCE_DIR}/include/api/JsonCB.h
|
||||
${CMAKE_SOURCE_DIR}/include/api/JsonCallbacks.h
|
||||
${CMAKE_SOURCE_DIR}/include/api/JsonApiCommand.h
|
||||
${CMAKE_SOURCE_DIR}/include/api/JsonApiSubscription.h
|
||||
${CMAKE_SOURCE_DIR}/include/api/JsonInfo.h
|
||||
${CMAKE_SOURCE_DIR}/libsrc/api/JsonAPI.cpp
|
||||
${CMAKE_SOURCE_DIR}/libsrc/api/API.cpp
|
||||
${CMAKE_SOURCE_DIR}/libsrc/api/JsonCB.cpp
|
||||
${CMAKE_SOURCE_DIR}/libsrc/api/JsonCallbacks.cpp
|
||||
${CMAKE_SOURCE_DIR}/libsrc/api/JsonInfo.cpp
|
||||
${CMAKE_SOURCE_DIR}/libsrc/api/JSONRPC_schemas.qrc
|
||||
)
|
||||
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["adjustment"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["clear"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["clearall"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
}
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["color"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -9,6 +9,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["componentstate"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -12,6 +12,11 @@
|
||||
"required" : true,
|
||||
"enum" : ["getconfig","getschema","setconfig","restoreconfig","reload"]
|
||||
},
|
||||
"instance" : {
|
||||
"type" : "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,6 +7,11 @@
|
||||
"required" : true,
|
||||
"enum" : ["create-effect"]
|
||||
},
|
||||
"instance" : {
|
||||
"type" : "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -8,6 +8,11 @@
|
||||
"required" : true,
|
||||
"enum" : ["delete-effect"]
|
||||
},
|
||||
"instance" : {
|
||||
"type" : "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["effect"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["image"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,21 +7,18 @@
|
||||
"required" : true,
|
||||
"enum" : ["ledcolors"]
|
||||
},
|
||||
"instance" : {
|
||||
"type" : "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"subcommand": {
|
||||
"type" : "string",
|
||||
"required" : true,
|
||||
"enum" : ["ledstream-stop","ledstream-start","testled","imagestream-start","imagestream-stop"]
|
||||
},
|
||||
"oneshot": {
|
||||
"type" : "bool"
|
||||
},
|
||||
"interval": {
|
||||
"type" : "integer",
|
||||
"required" : false,
|
||||
"minimum": 50
|
||||
"enum" : ["ledstream-stop","ledstream-start","imagestream-start","imagestream-stop"]
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -7,6 +7,9 @@
|
||||
"required" : true,
|
||||
"enum" : ["leddevice"]
|
||||
},
|
||||
"instance" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["processing"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
@ -7,6 +7,25 @@
|
||||
"required" : true,
|
||||
"enum" : ["serverinfo"]
|
||||
},
|
||||
"subcommand": {
|
||||
"type": "string",
|
||||
"enum": ["getInfo", "subscribe", "unsubscribe", "getSubscriptions", "getSubscriptionCommands"]
|
||||
},
|
||||
"instance" : {
|
||||
"type" : "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 255
|
||||
},
|
||||
"data": {
|
||||
"type": ["null", "array"],
|
||||
"properties": {
|
||||
"subscriptions": {
|
||||
"type": "array",
|
||||
"items": {}
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"subscribe" : {
|
||||
"type" : "array"
|
||||
},
|
||||
|
@ -7,6 +7,12 @@
|
||||
"required" : true,
|
||||
"enum" : ["sourceselect"]
|
||||
},
|
||||
"instance" : {
|
||||
"type": "array",
|
||||
"required": false,
|
||||
"items" : {},
|
||||
"minItems": 1
|
||||
},
|
||||
"tan" : {
|
||||
"type" : "integer"
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,416 +0,0 @@
|
||||
// proj incl
|
||||
#include <api/JsonCB.h>
|
||||
|
||||
// hyperion
|
||||
#include <hyperion/Hyperion.h>
|
||||
|
||||
// HyperionIManager
|
||||
#include <hyperion/HyperionIManager.h>
|
||||
// components
|
||||
|
||||
#include <hyperion/ComponentRegister.h>
|
||||
// priorityMuxer
|
||||
|
||||
#include <hyperion/PriorityMuxer.h>
|
||||
|
||||
// utils
|
||||
#include <utils/ColorSys.h>
|
||||
|
||||
// qt
|
||||
#include <QDateTime>
|
||||
#include <QVariant>
|
||||
|
||||
// Image to led map helper
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
JsonCB::JsonCB(QObject* parent)
|
||||
: QObject(parent)
|
||||
, _hyperion(nullptr)
|
||||
, _componentRegister(nullptr)
|
||||
, _prioMuxer(nullptr)
|
||||
{
|
||||
_availableCommands << "components-update" << "priorities-update" << "imageToLedMapping-update"
|
||||
<< "adjustment-update" << "videomode-update" << "settings-update" << "leds-update" << "instance-update" << "token-update";
|
||||
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
_availableCommands << "effects-update";
|
||||
#endif
|
||||
|
||||
qRegisterMetaType<PriorityMuxer::InputsMap>("InputsMap");
|
||||
}
|
||||
|
||||
bool JsonCB::subscribeFor(const QString& type, bool unsubscribe)
|
||||
{
|
||||
if(!_availableCommands.contains(type))
|
||||
return false;
|
||||
|
||||
if(unsubscribe)
|
||||
_subscribedCommands.removeAll(type);
|
||||
else
|
||||
_subscribedCommands << type;
|
||||
|
||||
if(type == "components-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCB::handleComponentState);
|
||||
else
|
||||
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCB::handleComponentState, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
if(type == "priorities-update")
|
||||
{
|
||||
if (unsubscribe)
|
||||
disconnect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCB::handlePriorityUpdate);
|
||||
else
|
||||
connect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCB::handlePriorityUpdate, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
if(type == "imageToLedMapping-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCB::handleImageToLedsMappingChange);
|
||||
else
|
||||
connect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCB::handleImageToLedsMappingChange, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
if(type == "adjustment-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCB::handleAdjustmentChange);
|
||||
else
|
||||
connect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCB::handleAdjustmentChange, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
if(type == "videomode-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(_hyperion, &Hyperion::newVideoMode, this, &JsonCB::handleVideoModeChange);
|
||||
else
|
||||
connect(_hyperion, &Hyperion::newVideoMode, this, &JsonCB::handleVideoModeChange, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
if(type == "effects-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCB::handleEffectListChange);
|
||||
else
|
||||
connect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCB::handleEffectListChange, Qt::UniqueConnection);
|
||||
}
|
||||
#endif
|
||||
|
||||
if(type == "settings-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(_hyperion, &Hyperion::settingsChanged, this, &JsonCB::handleSettingsChange);
|
||||
else
|
||||
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCB::handleSettingsChange, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
if(type == "leds-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(_hyperion, &Hyperion::settingsChanged, this, &JsonCB::handleLedsConfigChange);
|
||||
else
|
||||
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCB::handleLedsConfigChange, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
|
||||
if(type == "instance-update")
|
||||
{
|
||||
if(unsubscribe)
|
||||
disconnect(HyperionIManager::getInstance(), &HyperionIManager::change, this, &JsonCB::handleInstanceChange);
|
||||
else
|
||||
connect(HyperionIManager::getInstance(), &HyperionIManager::change, this, &JsonCB::handleInstanceChange, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
if (type == "token-update")
|
||||
{
|
||||
if (unsubscribe)
|
||||
disconnect(AuthManager::getInstance(), &AuthManager::tokenChange, this, &JsonCB::handleTokenChange);
|
||||
else
|
||||
connect(AuthManager::getInstance(), &AuthManager::tokenChange, this, &JsonCB::handleTokenChange, Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JsonCB::resetSubscriptions()
|
||||
{
|
||||
for(const auto & entry : getSubscribedCommands())
|
||||
{
|
||||
subscribeFor(entry, true);
|
||||
}
|
||||
}
|
||||
|
||||
void JsonCB::setSubscriptionsTo(Hyperion* hyperion)
|
||||
{
|
||||
assert(hyperion);
|
||||
|
||||
// get current subs
|
||||
QStringList currSubs(getSubscribedCommands());
|
||||
|
||||
// stop subs
|
||||
resetSubscriptions();
|
||||
|
||||
// update pointer
|
||||
_hyperion = hyperion;
|
||||
_componentRegister = _hyperion->getComponentRegister();
|
||||
_prioMuxer = _hyperion->getMuxerInstance();
|
||||
|
||||
// re-apply subs
|
||||
for(const auto & entry : currSubs)
|
||||
{
|
||||
subscribeFor(entry);
|
||||
}
|
||||
}
|
||||
|
||||
void JsonCB::doCallback(const QString& cmd, const QVariant& data)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj["instance"] = _hyperion->getInstanceIndex();
|
||||
obj["command"] = cmd;
|
||||
|
||||
if (data.userType() == QMetaType::QJsonArray)
|
||||
obj["data"] = data.toJsonArray();
|
||||
else
|
||||
obj["data"] = data.toJsonObject();
|
||||
|
||||
emit newCallback(obj);
|
||||
}
|
||||
|
||||
void JsonCB::handleComponentState(hyperion::Components comp, bool state)
|
||||
{
|
||||
QJsonObject data;
|
||||
data["name"] = componentToIdString(comp);
|
||||
data["enabled"] = state;
|
||||
|
||||
doCallback("components-update", QVariant(data));
|
||||
}
|
||||
|
||||
void JsonCB::handlePriorityUpdate(int currentPriority, const PriorityMuxer::InputsMap& activeInputs)
|
||||
{
|
||||
QJsonObject data;
|
||||
QJsonArray priorities;
|
||||
uint64_t now = QDateTime::currentMSecsSinceEpoch();
|
||||
QList<int> activePriorities = activeInputs.keys();
|
||||
|
||||
activePriorities.removeAll(PriorityMuxer::LOWEST_PRIORITY);
|
||||
|
||||
for (int priority : std::as_const(activePriorities)) {
|
||||
|
||||
const Hyperion::InputInfo& priorityInfo = activeInputs[priority];
|
||||
|
||||
QJsonObject item;
|
||||
item["priority"] = priority;
|
||||
|
||||
if (priorityInfo.timeoutTime_ms > 0 )
|
||||
{
|
||||
item["duration_ms"] = int(priorityInfo.timeoutTime_ms - now);
|
||||
}
|
||||
|
||||
// owner has optional informations to the component
|
||||
if(!priorityInfo.owner.isEmpty())
|
||||
{
|
||||
item["owner"] = priorityInfo.owner;
|
||||
}
|
||||
|
||||
item["componentId"] = QString(hyperion::componentToIdString(priorityInfo.componentId));
|
||||
item["origin"] = priorityInfo.origin;
|
||||
item["active"] = (priorityInfo.timeoutTime_ms >= -1);
|
||||
item["visible"] = (priority == currentPriority);
|
||||
|
||||
if(priorityInfo.componentId == hyperion::COMP_COLOR && !priorityInfo.ledColors.empty())
|
||||
{
|
||||
QJsonObject LEDcolor;
|
||||
|
||||
// add RGB Value to Array
|
||||
QJsonArray RGBValue;
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->red);
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->green);
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->blue);
|
||||
LEDcolor.insert("RGB", RGBValue);
|
||||
|
||||
uint16_t Hue;
|
||||
float Saturation;
|
||||
float Luminace;
|
||||
|
||||
// add HSL Value to Array
|
||||
QJsonArray HSLValue;
|
||||
ColorSys::rgb2hsl(priorityInfo.ledColors.begin()->red,
|
||||
priorityInfo.ledColors.begin()->green,
|
||||
priorityInfo.ledColors.begin()->blue,
|
||||
Hue, Saturation, Luminace);
|
||||
|
||||
HSLValue.append(Hue);
|
||||
HSLValue.append(Saturation);
|
||||
HSLValue.append(Luminace);
|
||||
LEDcolor.insert("HSL", HSLValue);
|
||||
|
||||
item["value"] = LEDcolor;
|
||||
}
|
||||
priorities.append(item);
|
||||
}
|
||||
|
||||
data["priorities"] = priorities;
|
||||
data["priorities_autoselect"] = _hyperion->sourceAutoSelectEnabled();
|
||||
|
||||
doCallback("priorities-update", QVariant(data));
|
||||
}
|
||||
|
||||
void JsonCB::handleImageToLedsMappingChange(int mappingType)
|
||||
{
|
||||
QJsonObject data;
|
||||
data["imageToLedMappingType"] = ImageProcessor::mappingTypeToStr(mappingType);
|
||||
|
||||
doCallback("imageToLedMapping-update", QVariant(data));
|
||||
}
|
||||
|
||||
void JsonCB::handleAdjustmentChange()
|
||||
{
|
||||
QJsonArray adjustmentArray;
|
||||
for (const QString& adjustmentId : _hyperion->getAdjustmentIds())
|
||||
{
|
||||
const ColorAdjustment * colorAdjustment = _hyperion->getAdjustment(adjustmentId);
|
||||
if (colorAdjustment == nullptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QJsonObject adjustment;
|
||||
adjustment["id"] = adjustmentId;
|
||||
|
||||
QJsonArray whiteAdjust;
|
||||
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentR());
|
||||
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentG());
|
||||
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentB());
|
||||
adjustment.insert("white", whiteAdjust);
|
||||
|
||||
QJsonArray redAdjust;
|
||||
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentR());
|
||||
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentG());
|
||||
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentB());
|
||||
adjustment.insert("red", redAdjust);
|
||||
|
||||
QJsonArray greenAdjust;
|
||||
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentR());
|
||||
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentG());
|
||||
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentB());
|
||||
adjustment.insert("green", greenAdjust);
|
||||
|
||||
QJsonArray blueAdjust;
|
||||
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentR());
|
||||
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentG());
|
||||
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentB());
|
||||
adjustment.insert("blue", blueAdjust);
|
||||
|
||||
QJsonArray cyanAdjust;
|
||||
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentR());
|
||||
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentG());
|
||||
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentB());
|
||||
adjustment.insert("cyan", cyanAdjust);
|
||||
|
||||
QJsonArray magentaAdjust;
|
||||
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentR());
|
||||
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentG());
|
||||
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentB());
|
||||
adjustment.insert("magenta", magentaAdjust);
|
||||
|
||||
QJsonArray yellowAdjust;
|
||||
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentR());
|
||||
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentG());
|
||||
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentB());
|
||||
adjustment.insert("yellow", yellowAdjust);
|
||||
|
||||
adjustment["backlightThreshold"] = colorAdjustment->_rgbTransform.getBacklightThreshold();
|
||||
adjustment["backlightColored"] = colorAdjustment->_rgbTransform.getBacklightColored();
|
||||
adjustment["brightness"] = colorAdjustment->_rgbTransform.getBrightness();
|
||||
adjustment["brightnessCompensation"] = colorAdjustment->_rgbTransform.getBrightnessCompensation();
|
||||
adjustment["gammaRed"] = colorAdjustment->_rgbTransform.getGammaR();
|
||||
adjustment["gammaGreen"] = colorAdjustment->_rgbTransform.getGammaG();
|
||||
adjustment["gammaBlue"] = colorAdjustment->_rgbTransform.getGammaB();
|
||||
|
||||
adjustmentArray.append(adjustment);
|
||||
}
|
||||
|
||||
doCallback("adjustment-update", QVariant(adjustmentArray));
|
||||
}
|
||||
|
||||
void JsonCB::handleVideoModeChange(VideoMode mode)
|
||||
{
|
||||
QJsonObject data;
|
||||
data["videomode"] = QString(videoMode2String(mode));
|
||||
doCallback("videomode-update", QVariant(data));
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
void JsonCB::handleEffectListChange()
|
||||
{
|
||||
QJsonArray effectList;
|
||||
QJsonObject effects;
|
||||
const std::list<EffectDefinition> & effectsDefinitions = _hyperion->getEffects();
|
||||
for (const EffectDefinition & effectDefinition : effectsDefinitions)
|
||||
{
|
||||
QJsonObject effect;
|
||||
effect["name"] = effectDefinition.name;
|
||||
effect["file"] = effectDefinition.file;
|
||||
effect["script"] = effectDefinition.script;
|
||||
effect["args"] = effectDefinition.args;
|
||||
effectList.append(effect);
|
||||
};
|
||||
effects["effects"] = effectList;
|
||||
doCallback("effects-update", QVariant(effects));
|
||||
}
|
||||
#endif
|
||||
|
||||
void JsonCB::handleSettingsChange(settings::type type, const QJsonDocument& data)
|
||||
{
|
||||
QJsonObject dat;
|
||||
if(data.isObject())
|
||||
dat[typeToString(type)] = data.object();
|
||||
else
|
||||
dat[typeToString(type)] = data.array();
|
||||
|
||||
doCallback("settings-update", QVariant(dat));
|
||||
}
|
||||
|
||||
void JsonCB::handleLedsConfigChange(settings::type type, const QJsonDocument& data)
|
||||
{
|
||||
if(type == settings::LEDS)
|
||||
{
|
||||
QJsonObject dat;
|
||||
dat[typeToString(type)] = data.array();
|
||||
doCallback("leds-update", QVariant(dat));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonCB::handleInstanceChange()
|
||||
{
|
||||
QJsonArray arr;
|
||||
|
||||
for(const auto & entry : HyperionIManager::getInstance()->getInstanceData())
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert("friendly_name", entry["friendly_name"].toString());
|
||||
obj.insert("instance", entry["instance"].toInt());
|
||||
obj.insert("running", entry["running"].toBool());
|
||||
arr.append(obj);
|
||||
}
|
||||
doCallback("instance-update", QVariant(arr));
|
||||
}
|
||||
|
||||
void JsonCB::handleTokenChange(const QVector<AuthManager::AuthDefinition> &def)
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (const auto &entry : def)
|
||||
{
|
||||
QJsonObject sub;
|
||||
sub["comment"] = entry.comment;
|
||||
sub["id"] = entry.id;
|
||||
sub["last_use"] = entry.lastUse;
|
||||
arr.push_back(sub);
|
||||
}
|
||||
doCallback("token-update", QVariant(arr));
|
||||
}
|
459
libsrc/api/JsonCallbacks.cpp
Normal file
459
libsrc/api/JsonCallbacks.cpp
Normal file
@ -0,0 +1,459 @@
|
||||
#include <api/JsonCallbacks.h>
|
||||
#include <api/JsonInfo.h>
|
||||
#include <api/JsonApiSubscription.h>
|
||||
|
||||
#include <hyperion/Hyperion.h>
|
||||
#include <hyperion/HyperionIManager.h>
|
||||
#include <events/EventHandler.h>
|
||||
#include <hyperion/ComponentRegister.h>
|
||||
#include <hyperion/PriorityMuxer.h>
|
||||
#include <utils/ColorSys.h>
|
||||
#include <hyperion/ImageProcessor.h>
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QVariant>
|
||||
#include <QImage>
|
||||
#include <QBuffer>
|
||||
|
||||
using namespace hyperion;
|
||||
|
||||
JsonCallbacks::JsonCallbacks(Logger *log, const QString& peerAddress, QObject* parent)
|
||||
: QObject(parent)
|
||||
, _log (log)
|
||||
, _hyperion(nullptr)
|
||||
, _peerAddress (peerAddress)
|
||||
, _componentRegister(nullptr)
|
||||
, _prioMuxer(nullptr)
|
||||
, _islogMsgStreamingActive(false)
|
||||
{
|
||||
qRegisterMetaType<PriorityMuxer::InputsMap>("InputsMap");
|
||||
}
|
||||
|
||||
bool JsonCallbacks::subscribe(const Subscription::Type cmd)
|
||||
{
|
||||
switch (cmd) {
|
||||
case Subscription::AdjustmentUpdate:
|
||||
connect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCallbacks::handleAdjustmentChange);
|
||||
break;
|
||||
case Subscription::ComponentsUpdate:
|
||||
connect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCallbacks::handleComponentState);
|
||||
break;
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
case Subscription::EffectsUpdate:
|
||||
connect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCallbacks::handleEffectListChange);
|
||||
break;
|
||||
#endif
|
||||
case Subscription::EventUpdate:
|
||||
connect(EventHandler::getInstance().data(), &EventHandler::signalEvent, this, &JsonCallbacks::handleEventUpdate);
|
||||
break;
|
||||
case Subscription::ImageToLedMappingUpdate:
|
||||
connect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCallbacks::handleImageToLedsMappingChange);
|
||||
break;
|
||||
case Subscription::ImageUpdate:
|
||||
connect(_hyperion, &Hyperion::currentImage, this, &JsonCallbacks::handleImageUpdate);
|
||||
break;
|
||||
case Subscription::InstanceUpdate:
|
||||
connect(HyperionIManager::getInstance(), &HyperionIManager::change, this, &JsonCallbacks::handleInstanceChange);
|
||||
break;
|
||||
case Subscription::LedColorsUpdate:
|
||||
connect(_hyperion, &Hyperion::rawLedColors, this, &JsonCallbacks::handleLedColorUpdate);
|
||||
break;
|
||||
case Subscription::LedsUpdate:
|
||||
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleLedsConfigChange);
|
||||
break;
|
||||
case Subscription::LogMsgUpdate:
|
||||
if (!_islogMsgStreamingActive)
|
||||
{
|
||||
handleLogMessageUpdate (Logger::T_LOG_MESSAGE{}); // needed to trigger log sending
|
||||
_islogMsgStreamingActive = true;
|
||||
Debug(_log, "log streaming activated for client %s", _peerAddress.toStdString().c_str());
|
||||
}
|
||||
connect(LoggerManager::getInstance().data(), &LoggerManager::newLogMessage, this, &JsonCallbacks::handleLogMessageUpdate);
|
||||
break;
|
||||
case Subscription::PrioritiesUpdate:
|
||||
connect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCallbacks::handlePriorityUpdate);
|
||||
break;
|
||||
case Subscription::SettingsUpdate:
|
||||
connect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleSettingsChange);
|
||||
break;
|
||||
case Subscription::TokenUpdate:
|
||||
connect(AuthManager::getInstance(), &AuthManager::tokenChange, this, &JsonCallbacks::handleTokenChange, Qt::AutoConnection);
|
||||
break;
|
||||
case Subscription::VideomodeUpdate:
|
||||
connect(_hyperion, &Hyperion::newVideoMode, this, &JsonCallbacks::handleVideoModeChange);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
_subscribedCommands.insert(cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonCallbacks::subscribe(const QString& cmd)
|
||||
{
|
||||
JsonApiSubscription subscription = ApiSubscriptionRegister::getSubscriptionInfo(cmd);
|
||||
if (subscription.cmd == Subscription::Unknown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return subscribe(subscription.cmd);
|
||||
}
|
||||
|
||||
QStringList JsonCallbacks::subscribe(const QJsonArray& subscriptions)
|
||||
{
|
||||
QJsonArray subsArr;
|
||||
if (subscriptions.contains("all"))
|
||||
{
|
||||
for (const auto& entry : getCommands(false))
|
||||
{
|
||||
subsArr.append(entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
subsArr = subscriptions;
|
||||
}
|
||||
|
||||
QStringList invalidSubscriptions;
|
||||
for (auto it = subsArr.begin(); it != subsArr.end(); ++it)
|
||||
{
|
||||
const QJsonValue& entry = *it;
|
||||
if (!subscribe(entry.toString()))
|
||||
{
|
||||
invalidSubscriptions.append(entry.toString());
|
||||
}
|
||||
}
|
||||
return invalidSubscriptions;
|
||||
}
|
||||
|
||||
bool JsonCallbacks::unsubscribe(const Subscription::Type cmd)
|
||||
{
|
||||
_subscribedCommands.remove(cmd);
|
||||
|
||||
switch (cmd) {
|
||||
case Subscription::AdjustmentUpdate:
|
||||
disconnect(_hyperion, &Hyperion::adjustmentChanged, this, &JsonCallbacks::handleAdjustmentChange);
|
||||
break;
|
||||
case Subscription::ComponentsUpdate:
|
||||
disconnect(_componentRegister, &ComponentRegister::updatedComponentState, this, &JsonCallbacks::handleComponentState);
|
||||
break;
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
case Subscription::EffectsUpdate:
|
||||
disconnect(_hyperion, &Hyperion::effectListUpdated, this, &JsonCallbacks::handleEffectListChange);
|
||||
break;
|
||||
#endif
|
||||
case Subscription::EventUpdate:
|
||||
disconnect(EventHandler::getInstance().data(), &EventHandler::signalEvent, this, &JsonCallbacks::handleEventUpdate);
|
||||
break;
|
||||
case Subscription::ImageToLedMappingUpdate:
|
||||
disconnect(_hyperion, &Hyperion::imageToLedsMappingChanged, this, &JsonCallbacks::handleImageToLedsMappingChange);
|
||||
break;
|
||||
case Subscription::ImageUpdate:
|
||||
disconnect(_hyperion, &Hyperion::currentImage, this, &JsonCallbacks::handleImageUpdate);
|
||||
break;
|
||||
case Subscription::InstanceUpdate:
|
||||
disconnect(HyperionIManager::getInstance(), &HyperionIManager::change, this, &JsonCallbacks::handleInstanceChange);
|
||||
break;
|
||||
case Subscription::LedColorsUpdate:
|
||||
disconnect(_hyperion, &Hyperion::rawLedColors, this, &JsonCallbacks::handleLedColorUpdate);
|
||||
break;
|
||||
case Subscription::LedsUpdate:
|
||||
disconnect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleLedsConfigChange);
|
||||
break;
|
||||
case Subscription::LogMsgUpdate:
|
||||
disconnect(LoggerManager::getInstance().data(), &LoggerManager::newLogMessage, this, &JsonCallbacks::handleLogMessageUpdate);
|
||||
if (_islogMsgStreamingActive)
|
||||
{
|
||||
_islogMsgStreamingActive = false;
|
||||
Debug(_log, "log streaming deactivated for client %s", _peerAddress.toStdString().c_str());
|
||||
}
|
||||
break;
|
||||
case Subscription::PrioritiesUpdate:
|
||||
disconnect(_prioMuxer, &PriorityMuxer::prioritiesChanged, this, &JsonCallbacks::handlePriorityUpdate);
|
||||
break;
|
||||
case Subscription::SettingsUpdate:
|
||||
disconnect(_hyperion, &Hyperion::settingsChanged, this, &JsonCallbacks::handleSettingsChange);
|
||||
break;
|
||||
case Subscription::TokenUpdate:
|
||||
disconnect(AuthManager::getInstance(), &AuthManager::tokenChange, this, &JsonCallbacks::handleTokenChange);
|
||||
break;
|
||||
case Subscription::VideomodeUpdate:
|
||||
disconnect(_hyperion, &Hyperion::newVideoMode, this, &JsonCallbacks::handleVideoModeChange);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonCallbacks::unsubscribe(const QString& cmd)
|
||||
{
|
||||
JsonApiSubscription subscription = ApiSubscriptionRegister::getSubscriptionInfo(cmd);
|
||||
if (subscription.cmd == Subscription::Unknown)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return unsubscribe(subscription.cmd);
|
||||
}
|
||||
|
||||
QStringList JsonCallbacks::unsubscribe(const QJsonArray& subscriptions)
|
||||
{
|
||||
QJsonArray subsArr;
|
||||
if (subscriptions.contains("all"))
|
||||
{
|
||||
for (const auto& entry : getCommands(false))
|
||||
{
|
||||
subsArr.append(entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
subsArr = subscriptions;
|
||||
}
|
||||
|
||||
QStringList invalidSubscriptions;
|
||||
for (auto it = subsArr.begin(); it != subsArr.end(); ++it)
|
||||
{
|
||||
const QJsonValue& entry = *it;
|
||||
if (!unsubscribe(entry.toString()))
|
||||
{
|
||||
invalidSubscriptions.append(entry.toString());
|
||||
}
|
||||
}
|
||||
return invalidSubscriptions;
|
||||
}
|
||||
|
||||
void JsonCallbacks::resetSubscriptions()
|
||||
{
|
||||
const QSet<Subscription::Type> currentSubscriptions = _subscribedCommands;
|
||||
for (QSet<Subscription::Type>::const_iterator it = currentSubscriptions.constBegin(); it != currentSubscriptions.constEnd(); ++it)
|
||||
{
|
||||
unsubscribe(*it);
|
||||
}
|
||||
}
|
||||
|
||||
void JsonCallbacks::setSubscriptionsTo(Hyperion* hyperion)
|
||||
{
|
||||
assert(hyperion);
|
||||
|
||||
// get current subs
|
||||
const QSet<Subscription::Type> currSubs(_subscribedCommands);
|
||||
|
||||
// stop subs
|
||||
resetSubscriptions();
|
||||
|
||||
// update pointer
|
||||
_hyperion = hyperion;
|
||||
_componentRegister = _hyperion->getComponentRegister();
|
||||
_prioMuxer = _hyperion->getMuxerInstance();
|
||||
|
||||
// re-apply subs
|
||||
for(const auto & entry : currSubs)
|
||||
{
|
||||
subscribe(entry);
|
||||
}
|
||||
}
|
||||
|
||||
QStringList JsonCallbacks::getCommands(bool fullList) const
|
||||
{
|
||||
QStringList commands;
|
||||
for (JsonApiSubscription subscription : ApiSubscriptionRegister::getSubscriptionLookup())
|
||||
{
|
||||
if (fullList || subscription.isAll)
|
||||
{
|
||||
commands << Subscription::toString(subscription.cmd);
|
||||
}
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
||||
QStringList JsonCallbacks::getSubscribedCommands() const
|
||||
{
|
||||
QStringList commands;
|
||||
for (Subscription::Type cmd : _subscribedCommands)
|
||||
{
|
||||
commands << Subscription::toString(cmd);
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
||||
void JsonCallbacks::doCallback(Subscription::Type cmd, const QVariant& data)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj["command"] = Subscription::toString(cmd);
|
||||
|
||||
if (Subscription::isInstanceSpecific(cmd))
|
||||
{
|
||||
obj["instance"] = _hyperion->getInstanceIndex();
|
||||
}
|
||||
|
||||
if (data.userType() == QMetaType::QJsonArray) {
|
||||
obj["data"] = data.toJsonArray();
|
||||
} else {
|
||||
obj["data"] = data.toJsonObject();
|
||||
}
|
||||
|
||||
emit newCallback(obj);
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleComponentState(hyperion::Components comp, bool state)
|
||||
{
|
||||
QJsonObject data;
|
||||
data["name"] = componentToIdString(comp);
|
||||
data["enabled"] = state;
|
||||
|
||||
doCallback(Subscription::ComponentsUpdate, QVariant(data));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handlePriorityUpdate(int currentPriority, const PriorityMuxer::InputsMap& activeInputs)
|
||||
{
|
||||
QJsonObject data;
|
||||
data["priorities"] = JsonInfo::getPrioritiestInfo(currentPriority, activeInputs);
|
||||
data["priorities_autoselect"] = _hyperion->sourceAutoSelectEnabled();
|
||||
|
||||
doCallback(Subscription::PrioritiesUpdate, QVariant(data));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleImageToLedsMappingChange(int mappingType)
|
||||
{
|
||||
QJsonObject data;
|
||||
data["imageToLedMappingType"] = ImageProcessor::mappingTypeToStr(mappingType);
|
||||
|
||||
doCallback(Subscription::ImageToLedMappingUpdate, QVariant(data));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleAdjustmentChange()
|
||||
{
|
||||
doCallback(Subscription::AdjustmentUpdate, JsonInfo::getAdjustmentInfo(_hyperion,_log));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleVideoModeChange(VideoMode mode)
|
||||
{
|
||||
QJsonObject data;
|
||||
data["videomode"] = QString(videoMode2String(mode));
|
||||
doCallback(Subscription::VideomodeUpdate, QVariant(data));
|
||||
}
|
||||
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
void JsonCallbacks::handleEffectListChange()
|
||||
{
|
||||
QJsonObject effects;
|
||||
effects["effects"] = JsonInfo::getEffects(_hyperion);
|
||||
doCallback(Subscription::EffectsUpdate, QVariant(effects));
|
||||
}
|
||||
#endif
|
||||
|
||||
void JsonCallbacks::handleSettingsChange(settings::type type, const QJsonDocument& data)
|
||||
{
|
||||
QJsonObject dat;
|
||||
if(data.isObject()) {
|
||||
dat[typeToString(type)] = data.object();
|
||||
} else {
|
||||
dat[typeToString(type)] = data.array();
|
||||
}
|
||||
|
||||
doCallback(Subscription::SettingsUpdate, QVariant(dat));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleLedsConfigChange(settings::type type, const QJsonDocument& data)
|
||||
{
|
||||
if(type == settings::LEDS)
|
||||
{
|
||||
QJsonObject dat;
|
||||
dat[typeToString(type)] = data.array();
|
||||
doCallback(Subscription::LedsUpdate, QVariant(dat));
|
||||
}
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleInstanceChange()
|
||||
{
|
||||
doCallback(Subscription::InstanceUpdate, JsonInfo::getInstanceInfo());
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleTokenChange(const QVector<AuthManager::AuthDefinition> &def)
|
||||
{
|
||||
QJsonArray arr;
|
||||
for (const auto &entry : def)
|
||||
{
|
||||
QJsonObject sub;
|
||||
sub["comment"] = entry.comment;
|
||||
sub["id"] = entry.id;
|
||||
sub["last_use"] = entry.lastUse;
|
||||
arr.push_back(sub);
|
||||
}
|
||||
doCallback(Subscription::TokenUpdate, QVariant(arr));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleLedColorUpdate(const std::vector<ColorRgb> &ledColors)
|
||||
{
|
||||
QJsonObject result;
|
||||
QJsonArray leds;
|
||||
|
||||
for (const auto &color : ledColors)
|
||||
{
|
||||
leds << QJsonValue(color.red) << QJsonValue(color.green) << QJsonValue(color.blue);
|
||||
}
|
||||
result["leds"] = leds;
|
||||
|
||||
doCallback(Subscription::LedColorsUpdate, QVariant(result));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleImageUpdate(const Image<ColorRgb> &image)
|
||||
{
|
||||
QImage jpgImage(reinterpret_cast<const uchar*>(image.memptr()), image.width(), image.height(), qsizetype(3) * image.width(), QImage::Format_RGB888);
|
||||
QByteArray byteArray;
|
||||
QBuffer buffer(&byteArray);
|
||||
buffer.open(QIODevice::WriteOnly);
|
||||
jpgImage.save(&buffer, "jpg");
|
||||
|
||||
QJsonObject result;
|
||||
result["image"] = "data:image/jpg;base64," + QString(byteArray.toBase64());
|
||||
|
||||
doCallback(Subscription::ImageUpdate, QVariant(result));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleLogMessageUpdate(const Logger::T_LOG_MESSAGE &msg)
|
||||
{
|
||||
QJsonObject result;
|
||||
QJsonObject message;
|
||||
QJsonArray messageArray;
|
||||
|
||||
if (!_islogMsgStreamingActive)
|
||||
{
|
||||
_islogMsgStreamingActive = true;
|
||||
QMetaObject::invokeMethod(LoggerManager::getInstance().data(), "getLogMessageBuffer",
|
||||
Qt::DirectConnection,
|
||||
Q_RETURN_ARG(QJsonArray, messageArray),
|
||||
Q_ARG(Logger::LogLevel, _log->getLogLevel()));
|
||||
}
|
||||
else
|
||||
{
|
||||
message["loggerName"] = msg.loggerName;
|
||||
message["loggerSubName"] = msg.loggerSubName;
|
||||
message["function"] = msg.function;
|
||||
message["line"] = QString::number(msg.line);
|
||||
message["fileName"] = msg.fileName;
|
||||
message["message"] = msg.message;
|
||||
message["levelString"] = msg.levelString;
|
||||
message["utime"] = QString::number(msg.utime);
|
||||
|
||||
messageArray.append(message);
|
||||
}
|
||||
result.insert("messages", messageArray);
|
||||
|
||||
doCallback(Subscription::LogMsgUpdate, QVariant(result));
|
||||
}
|
||||
|
||||
void JsonCallbacks::handleEventUpdate(const Event &event)
|
||||
{
|
||||
QJsonObject result;
|
||||
|
||||
result["event"] = eventToString(event);
|
||||
|
||||
doCallback(Subscription::EventUpdate, QVariant(result));
|
||||
}
|
||||
|
620
libsrc/api/JsonInfo.cpp
Normal file
620
libsrc/api/JsonInfo.cpp
Normal file
@ -0,0 +1,620 @@
|
||||
#include <api/JsonInfo.h>
|
||||
#include <api/API.h>
|
||||
|
||||
#include <utils/ColorSys.h>
|
||||
#include <hyperion/GrabberWrapper.h>
|
||||
#include <leddevice/LedDeviceWrapper.h>
|
||||
#include <utils/SysInfo.h>
|
||||
#include <hyperion/AuthManager.h>
|
||||
#include <QCoreApplication>
|
||||
#include <QApplication>
|
||||
|
||||
#include <HyperionConfig.h> // Required to determine the cmake options
|
||||
|
||||
#include <hyperion/GrabberWrapper.h>
|
||||
#include <grabber/GrabberConfig.h>
|
||||
|
||||
|
||||
QJsonArray JsonInfo::getAdjustmentInfo(const Hyperion* hyperion, Logger* log)
|
||||
{
|
||||
QJsonArray adjustmentArray;
|
||||
for (const QString &adjustmentId : hyperion->getAdjustmentIds())
|
||||
{
|
||||
const ColorAdjustment *colorAdjustment = hyperion->getAdjustment(adjustmentId);
|
||||
if (colorAdjustment == nullptr)
|
||||
{
|
||||
Error(log, "Incorrect color adjustment id: %s", QSTRING_CSTR(adjustmentId));
|
||||
continue;
|
||||
}
|
||||
|
||||
QJsonObject adjustment;
|
||||
adjustment["id"] = adjustmentId;
|
||||
|
||||
QJsonArray whiteAdjust;
|
||||
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentR());
|
||||
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentG());
|
||||
whiteAdjust.append(colorAdjustment->_rgbWhiteAdjustment.getAdjustmentB());
|
||||
adjustment.insert("white", whiteAdjust);
|
||||
|
||||
QJsonArray redAdjust;
|
||||
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentR());
|
||||
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentG());
|
||||
redAdjust.append(colorAdjustment->_rgbRedAdjustment.getAdjustmentB());
|
||||
adjustment.insert("red", redAdjust);
|
||||
|
||||
QJsonArray greenAdjust;
|
||||
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentR());
|
||||
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentG());
|
||||
greenAdjust.append(colorAdjustment->_rgbGreenAdjustment.getAdjustmentB());
|
||||
adjustment.insert("green", greenAdjust);
|
||||
|
||||
QJsonArray blueAdjust;
|
||||
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentR());
|
||||
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentG());
|
||||
blueAdjust.append(colorAdjustment->_rgbBlueAdjustment.getAdjustmentB());
|
||||
adjustment.insert("blue", blueAdjust);
|
||||
|
||||
QJsonArray cyanAdjust;
|
||||
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentR());
|
||||
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentG());
|
||||
cyanAdjust.append(colorAdjustment->_rgbCyanAdjustment.getAdjustmentB());
|
||||
adjustment.insert("cyan", cyanAdjust);
|
||||
|
||||
QJsonArray magentaAdjust;
|
||||
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentR());
|
||||
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentG());
|
||||
magentaAdjust.append(colorAdjustment->_rgbMagentaAdjustment.getAdjustmentB());
|
||||
adjustment.insert("magenta", magentaAdjust);
|
||||
|
||||
QJsonArray yellowAdjust;
|
||||
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentR());
|
||||
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentG());
|
||||
yellowAdjust.append(colorAdjustment->_rgbYellowAdjustment.getAdjustmentB());
|
||||
adjustment.insert("yellow", yellowAdjust);
|
||||
|
||||
adjustment["backlightThreshold"] = colorAdjustment->_rgbTransform.getBacklightThreshold();
|
||||
adjustment["backlightColored"] = colorAdjustment->_rgbTransform.getBacklightColored();
|
||||
adjustment["brightness"] = colorAdjustment->_rgbTransform.getBrightness();
|
||||
adjustment["brightnessCompensation"] = colorAdjustment->_rgbTransform.getBrightnessCompensation();
|
||||
adjustment["gammaRed"] = colorAdjustment->_rgbTransform.getGammaR();
|
||||
adjustment["gammaGreen"] = colorAdjustment->_rgbTransform.getGammaG();
|
||||
adjustment["gammaBlue"] = colorAdjustment->_rgbTransform.getGammaB();
|
||||
|
||||
adjustment["saturationGain"] = colorAdjustment->_okhsvTransform.getSaturationGain();
|
||||
adjustment["brightnessGain"] = colorAdjustment->_okhsvTransform.getBrightnessGain();
|
||||
|
||||
adjustmentArray.append(adjustment);
|
||||
}
|
||||
return adjustmentArray;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getPrioritiestInfo(const Hyperion* hyperion)
|
||||
{
|
||||
return getPrioritiestInfo(hyperion->getCurrentPriority(), hyperion->getPriorityInfo());
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getPrioritiestInfo(int currentPriority, const PriorityMuxer::InputsMap& activeInputs)
|
||||
{
|
||||
QJsonArray priorities;
|
||||
int64_t now = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
QList<int> activePriorities = activeInputs.keys();
|
||||
activePriorities.removeAll(PriorityMuxer::LOWEST_PRIORITY);
|
||||
|
||||
for(int priority : std::as_const(activePriorities))
|
||||
{
|
||||
const PriorityMuxer::InputInfo priorityInfo = activeInputs.value(priority);
|
||||
|
||||
QJsonObject item;
|
||||
item["priority"] = priority;
|
||||
|
||||
if (priorityInfo.timeoutTime_ms > 0 )
|
||||
{
|
||||
item["duration_ms"] = int(priorityInfo.timeoutTime_ms - now);
|
||||
}
|
||||
|
||||
// owner has optional informations to the component
|
||||
if (!priorityInfo.owner.isEmpty())
|
||||
{
|
||||
item["owner"] = priorityInfo.owner;
|
||||
}
|
||||
|
||||
item["componentId"] = QString(hyperion::componentToIdString(priorityInfo.componentId));
|
||||
item["origin"] = priorityInfo.origin;
|
||||
item["active"] = (priorityInfo.timeoutTime_ms >= -1);
|
||||
item["visible"] = (priority == currentPriority);
|
||||
|
||||
if (priorityInfo.componentId == hyperion::COMP_COLOR && !priorityInfo.ledColors.empty())
|
||||
{
|
||||
QJsonObject LEDcolor;
|
||||
|
||||
// add RGB Value to Array
|
||||
QJsonArray RGBValue;
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->red);
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->green);
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->blue);
|
||||
LEDcolor.insert("RGB", RGBValue);
|
||||
|
||||
uint16_t Hue;
|
||||
float Saturation;
|
||||
float Luminace;
|
||||
|
||||
// add HSL Value to Array
|
||||
QJsonArray HSLValue;
|
||||
ColorSys::rgb2hsl(priorityInfo.ledColors.begin()->red,
|
||||
priorityInfo.ledColors.begin()->green,
|
||||
priorityInfo.ledColors.begin()->blue,
|
||||
Hue, Saturation, Luminace);
|
||||
|
||||
HSLValue.append(static_cast<double>(Hue));
|
||||
HSLValue.append(static_cast<double>(Saturation));
|
||||
HSLValue.append(static_cast<double>(Luminace));
|
||||
LEDcolor.insert("HSL", HSLValue);
|
||||
|
||||
item["value"] = LEDcolor;
|
||||
}
|
||||
|
||||
(priority == currentPriority)
|
||||
? priorities.prepend(item)
|
||||
: priorities.append(item);
|
||||
}
|
||||
return priorities;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getEffects(const Hyperion* hyperion)
|
||||
{
|
||||
QJsonArray effects;
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
// collect effect info
|
||||
|
||||
const std::list<EffectDefinition> &effectsDefinitions = hyperion->getEffects();
|
||||
for (const EffectDefinition &effectDefinition : effectsDefinitions)
|
||||
{
|
||||
QJsonObject effect;
|
||||
effect["name"] = effectDefinition.name;
|
||||
effect["file"] = effectDefinition.file;
|
||||
effect["script"] = effectDefinition.script;
|
||||
effect["args"] = effectDefinition.args;
|
||||
effects.append(effect);
|
||||
}
|
||||
#endif
|
||||
return effects;
|
||||
}
|
||||
|
||||
QJsonObject JsonInfo::getAvailableLedDevices()
|
||||
{
|
||||
// get available led devices
|
||||
QJsonObject ledDevices;
|
||||
QJsonArray availableLedDevices;
|
||||
for (const auto& dev : LedDeviceWrapper::getDeviceMap())
|
||||
{
|
||||
availableLedDevices.append(dev.first);
|
||||
}
|
||||
|
||||
ledDevices["available"] = availableLedDevices;
|
||||
|
||||
return ledDevices;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getAvailableScreenGrabbers()
|
||||
{
|
||||
QJsonArray availableScreenGrabbers;
|
||||
for (const auto& grabber : GrabberWrapper::availableGrabbers(GrabberTypeFilter::SCREEN))
|
||||
{
|
||||
availableScreenGrabbers.append(grabber);
|
||||
}
|
||||
return availableScreenGrabbers;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getAvailableVideoGrabbers()
|
||||
{
|
||||
QJsonArray availableVideoGrabbers;
|
||||
for (const auto& grabber : GrabberWrapper::availableGrabbers(GrabberTypeFilter::VIDEO))
|
||||
{
|
||||
availableVideoGrabbers.append(grabber);
|
||||
}
|
||||
return availableVideoGrabbers;
|
||||
}
|
||||
QJsonArray JsonInfo::getAvailableAudioGrabbers()
|
||||
{
|
||||
QJsonArray availableAudioGrabbers;
|
||||
for (const auto& grabber : GrabberWrapper::availableGrabbers(GrabberTypeFilter::AUDIO))
|
||||
{
|
||||
availableAudioGrabbers.append(grabber);
|
||||
}
|
||||
return availableAudioGrabbers;
|
||||
}
|
||||
|
||||
QJsonObject JsonInfo::getGrabbers(const Hyperion* hyperion)
|
||||
{
|
||||
QJsonObject grabbers;
|
||||
// SCREEN
|
||||
QJsonObject screenGrabbers;
|
||||
if (GrabberWrapper::getInstance() != nullptr)
|
||||
{
|
||||
const QStringList activeGrabbers = GrabberWrapper::getInstance()->getActive(hyperion->getInstanceIndex(), GrabberTypeFilter::SCREEN);
|
||||
QJsonArray activeGrabberNames;
|
||||
for (const auto& grabberName : activeGrabbers)
|
||||
{
|
||||
activeGrabberNames.append(grabberName);
|
||||
}
|
||||
|
||||
screenGrabbers["active"] = activeGrabberNames;
|
||||
}
|
||||
screenGrabbers["available"] = getAvailableScreenGrabbers();
|
||||
|
||||
// VIDEO
|
||||
QJsonObject videoGrabbers;
|
||||
if (GrabberWrapper::getInstance() != nullptr)
|
||||
{
|
||||
const QStringList activeGrabbers = GrabberWrapper::getInstance()->getActive(hyperion->getInstanceIndex(), GrabberTypeFilter::VIDEO);
|
||||
QJsonArray activeGrabberNames;
|
||||
for (const auto& grabberName : activeGrabbers)
|
||||
{
|
||||
activeGrabberNames.append(grabberName);
|
||||
}
|
||||
|
||||
videoGrabbers["active"] = activeGrabberNames;
|
||||
}
|
||||
videoGrabbers["available"] = getAvailableVideoGrabbers();
|
||||
|
||||
// AUDIO
|
||||
QJsonObject audioGrabbers;
|
||||
if (GrabberWrapper::getInstance() != nullptr)
|
||||
{
|
||||
const QStringList activeGrabbers = GrabberWrapper::getInstance()->getActive(hyperion->getInstanceIndex(), GrabberTypeFilter::AUDIO);
|
||||
|
||||
QJsonArray activeGrabberNames;
|
||||
for (const auto& grabberName : activeGrabbers)
|
||||
{
|
||||
activeGrabberNames.append(grabberName);
|
||||
}
|
||||
|
||||
audioGrabbers["active"] = activeGrabberNames;
|
||||
}
|
||||
audioGrabbers["available"] = getAvailableAudioGrabbers() ;
|
||||
|
||||
grabbers.insert("screen", screenGrabbers);
|
||||
grabbers.insert("video", videoGrabbers);
|
||||
grabbers.insert("audio", audioGrabbers);
|
||||
|
||||
return grabbers;
|
||||
}
|
||||
|
||||
QJsonObject JsonInfo::getCecInfo()
|
||||
{
|
||||
QJsonObject cecInfo;
|
||||
#if defined(ENABLE_CEC)
|
||||
cecInfo["enabled"] = true;
|
||||
#else
|
||||
cecInfo["enabled"] = false;
|
||||
#endif
|
||||
return cecInfo;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getServices()
|
||||
{
|
||||
// get available services
|
||||
QJsonArray services;
|
||||
|
||||
#if defined(ENABLE_BOBLIGHT_SERVER)
|
||||
services.append("boblight");
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_CEC)
|
||||
services.append("cec");
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
services.append("effectengine");
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_FORWARDER)
|
||||
services.append("forwarder");
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_FLATBUF_SERVER)
|
||||
services.append("flatbuffer");
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_PROTOBUF_SERVER)
|
||||
services.append("protobuffer");
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_MDNS)
|
||||
services.append("mDNS");
|
||||
#endif
|
||||
services.append("SSDP");
|
||||
|
||||
if (!getAvailableScreenGrabbers().isEmpty() || !getAvailableVideoGrabbers().isEmpty() || services.contains("flatbuffer") || services.contains("protobuffer"))
|
||||
{
|
||||
services.append("borderdetection");
|
||||
}
|
||||
return services;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getComponents(const Hyperion* hyperion)
|
||||
{
|
||||
// get available components
|
||||
QJsonArray component;
|
||||
std::map<hyperion::Components, bool> components = hyperion->getComponentRegister()->getRegister();
|
||||
for (auto comp : components)
|
||||
{
|
||||
QJsonObject item;
|
||||
item["name"] = QString::fromStdString(hyperion::componentToIdString(comp.first));
|
||||
item["enabled"] = comp.second;
|
||||
|
||||
component.append(item);
|
||||
}
|
||||
return component;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getInstanceInfo()
|
||||
{
|
||||
QJsonArray instanceInfo;
|
||||
for (const auto &entry : HyperionIManager::getInstance()->getInstanceData())
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj.insert("friendly_name", entry["friendly_name"].toString());
|
||||
obj.insert("instance", entry["instance"].toInt());
|
||||
obj.insert("running", entry["running"].toBool());
|
||||
instanceInfo.append(obj);
|
||||
}
|
||||
return instanceInfo;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getTransformationInfo(const Hyperion* hyperion)
|
||||
{
|
||||
// TRANSFORM INFORMATION (DEFAULT VALUES)
|
||||
QJsonArray transformArray;
|
||||
for (const QString &transformId : hyperion->getAdjustmentIds())
|
||||
{
|
||||
QJsonObject transform;
|
||||
QJsonArray blacklevel;
|
||||
QJsonArray whitelevel;
|
||||
QJsonArray gamma;
|
||||
QJsonArray threshold;
|
||||
|
||||
transform["id"] = transformId;
|
||||
transform["saturationGain"] = 1.0;
|
||||
transform["brightnessGain"] = 1.0;
|
||||
transform["saturationLGain"] = 1.0;
|
||||
transform["luminanceGain"] = 1.0;
|
||||
transform["luminanceMinimum"] = 0.0;
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
blacklevel.append(0.0);
|
||||
whitelevel.append(1.0);
|
||||
gamma.append(2.50);
|
||||
threshold.append(0.0);
|
||||
}
|
||||
|
||||
transform.insert("blacklevel", blacklevel);
|
||||
transform.insert("whitelevel", whitelevel);
|
||||
transform.insert("gamma", gamma);
|
||||
transform.insert("threshold", threshold);
|
||||
|
||||
transformArray.append(transform);
|
||||
}
|
||||
return transformArray;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getActiveEffects(const Hyperion* hyperion)
|
||||
{
|
||||
// ACTIVE EFFECT INFO
|
||||
QJsonArray activeEffects;
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
for (const ActiveEffectDefinition &activeEffectDefinition : hyperion->getActiveEffects())
|
||||
{
|
||||
if (activeEffectDefinition.priority != PriorityMuxer::LOWEST_PRIORITY - 1)
|
||||
{
|
||||
QJsonObject activeEffect;
|
||||
activeEffect["script"] = activeEffectDefinition.script;
|
||||
activeEffect["name"] = activeEffectDefinition.name;
|
||||
activeEffect["priority"] = activeEffectDefinition.priority;
|
||||
activeEffect["timeout"] = activeEffectDefinition.timeout;
|
||||
activeEffect["args"] = activeEffectDefinition.args;
|
||||
activeEffects.append(activeEffect);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return activeEffects;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::getActiveColors(const Hyperion* hyperion)
|
||||
{
|
||||
// ACTIVE STATIC LED COLOR
|
||||
QJsonArray activeLedColors;
|
||||
const Hyperion::InputInfo &priorityInfo = hyperion->getPriorityInfo(hyperion->getCurrentPriority());
|
||||
if (priorityInfo.componentId == hyperion::COMP_COLOR && !priorityInfo.ledColors.empty())
|
||||
{
|
||||
// check if LED Color not Black (0,0,0)
|
||||
if ((priorityInfo.ledColors.begin()->red +
|
||||
priorityInfo.ledColors.begin()->green +
|
||||
priorityInfo.ledColors.begin()->blue !=
|
||||
0))
|
||||
{
|
||||
QJsonObject LEDcolor;
|
||||
|
||||
// add RGB Value to Array
|
||||
QJsonArray RGBValue;
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->red);
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->green);
|
||||
RGBValue.append(priorityInfo.ledColors.begin()->blue);
|
||||
LEDcolor.insert("RGB Value", RGBValue);
|
||||
|
||||
uint16_t Hue;
|
||||
float Saturation;
|
||||
float Luminace;
|
||||
|
||||
// add HSL Value to Array
|
||||
QJsonArray HSLValue;
|
||||
ColorSys::rgb2hsl(priorityInfo.ledColors.begin()->red,
|
||||
priorityInfo.ledColors.begin()->green,
|
||||
priorityInfo.ledColors.begin()->blue,
|
||||
Hue, Saturation, Luminace);
|
||||
|
||||
HSLValue.append(static_cast<double>(Hue));
|
||||
HSLValue.append(static_cast<double>(Saturation));
|
||||
HSLValue.append(static_cast<double>(Luminace));
|
||||
LEDcolor.insert("HSL Value", HSLValue);
|
||||
|
||||
activeLedColors.append(LEDcolor);
|
||||
}
|
||||
}
|
||||
return activeLedColors;
|
||||
}
|
||||
|
||||
QJsonObject JsonInfo::getSystemInfo(const Hyperion* hyperion)
|
||||
{
|
||||
QJsonObject info;
|
||||
|
||||
SysInfo::HyperionSysInfo data = SysInfo::get();
|
||||
QJsonObject systemInfo;
|
||||
systemInfo["kernelType"] = data.kernelType;
|
||||
systemInfo["kernelVersion"] = data.kernelVersion;
|
||||
systemInfo["architecture"] = data.architecture;
|
||||
systemInfo["cpuModelName"] = data.cpuModelName;
|
||||
systemInfo["cpuModelType"] = data.cpuModelType;
|
||||
systemInfo["cpuHardware"] = data.cpuHardware;
|
||||
systemInfo["cpuRevision"] = data.cpuRevision;
|
||||
systemInfo["wordSize"] = data.wordSize;
|
||||
systemInfo["productType"] = data.productType;
|
||||
systemInfo["productVersion"] = data.productVersion;
|
||||
systemInfo["prettyName"] = data.prettyName;
|
||||
systemInfo["hostName"] = data.hostName;
|
||||
systemInfo["domainName"] = data.domainName;
|
||||
systemInfo["isUserAdmin"] = data.isUserAdmin;
|
||||
systemInfo["qtVersion"] = data.qtVersion;
|
||||
#if defined(ENABLE_EFFECTENGINE)
|
||||
systemInfo["pyVersion"] = data.pyVersion;
|
||||
#endif
|
||||
info["system"] = systemInfo;
|
||||
|
||||
QJsonObject hyperionInfo;
|
||||
hyperionInfo["version"] = QString(HYPERION_VERSION);
|
||||
hyperionInfo["build"] = QString(HYPERION_BUILD_ID);
|
||||
hyperionInfo["gitremote"] = QString(HYPERION_GIT_REMOTE);
|
||||
hyperionInfo["time"] = QString(__DATE__ " " __TIME__);
|
||||
hyperionInfo["id"] = AuthManager::getInstance()->getID();
|
||||
hyperionInfo["rootPath"] = HyperionIManager::getInstance()->getRootPath();
|
||||
hyperionInfo["readOnlyMode"] = hyperion->getReadOnlyMode();
|
||||
|
||||
QCoreApplication* app = QCoreApplication::instance();
|
||||
hyperionInfo["isGuiMode"] = qobject_cast<QApplication*>(app) != nullptr;
|
||||
|
||||
info["hyperion"] = hyperionInfo;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
QJsonObject JsonInfo::discoverSources(const QString& sourceType, const QJsonObject& params)
|
||||
{
|
||||
QJsonObject inputSourcesDiscovered;
|
||||
inputSourcesDiscovered.insert("sourceType", sourceType);
|
||||
|
||||
if (sourceType == "video") {
|
||||
QJsonArray videoInputs = discoverVideoInputs(params);
|
||||
inputSourcesDiscovered["video_sources"] = videoInputs;
|
||||
} else if (sourceType == "audio") {
|
||||
QJsonArray audioInputs = discoverAudioInputs(params);
|
||||
inputSourcesDiscovered["audio_sources"] = audioInputs;
|
||||
} else if (sourceType == "screen") {
|
||||
QJsonArray screenInputs = discoverScreenInputs(params);
|
||||
inputSourcesDiscovered["video_sources"] = screenInputs;
|
||||
}
|
||||
|
||||
return inputSourcesDiscovered;
|
||||
}
|
||||
|
||||
template<typename GrabberType>
|
||||
void JsonInfo::discoverGrabber(QJsonArray& inputs, const QJsonObject& params) const
|
||||
{
|
||||
GrabberType grabber;
|
||||
QJsonValue discoveryResult = grabber.discover(params);
|
||||
|
||||
if (discoveryResult.isArray())
|
||||
{
|
||||
inputs = discoveryResult.toArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!discoveryResult.toObject().isEmpty())
|
||||
{
|
||||
inputs.append(discoveryResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::discoverVideoInputs(const QJsonObject& params) const
|
||||
{
|
||||
QJsonArray videoInputs;
|
||||
|
||||
#ifdef ENABLE_V4L2
|
||||
discoverGrabber<V4L2Grabber>(videoInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_MF
|
||||
discoverGrabber<MFGrabber>(videoInputs, params);
|
||||
#endif
|
||||
|
||||
return videoInputs;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::discoverAudioInputs(const QJsonObject& params) const
|
||||
{
|
||||
QJsonArray audioInputs;
|
||||
|
||||
#ifdef ENABLE_AUDIO
|
||||
#ifdef WIN32
|
||||
discoverGrabber<AudioGrabberWindows>(audioInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef __linux__audioInputs
|
||||
discoverGrabber<AudioGrabberLinux>(audioInputs, params);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
return audioInputs;
|
||||
}
|
||||
|
||||
QJsonArray JsonInfo::discoverScreenInputs(const QJsonObject& params) const
|
||||
{
|
||||
QJsonArray screenInputs;
|
||||
|
||||
#ifdef ENABLE_QT
|
||||
discoverGrabber<QtGrabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DX
|
||||
discoverGrabber<DirectXGrabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_X11
|
||||
discoverGrabber<X11Grabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_XCB
|
||||
discoverGrabber<XcbGrabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_FB) && !defined(ENABLE_AMLOGIC)
|
||||
discoverGrabber<FramebufferFrameGrabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DISPMANX
|
||||
discoverGrabber<DispmanxFrameGrabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_AMLOGIC
|
||||
discoverGrabber<AmlogicGrabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_OSX
|
||||
discoverGrabber<OsxFrameGrabber>(screenInputs, params);
|
||||
#endif
|
||||
|
||||
return screenInputs;
|
||||
}
|
@ -103,7 +103,7 @@ QString EffectFileHandler::saveEffect(const QJsonObject& message)
|
||||
|
||||
if (it != effectsSchemas.end())
|
||||
{
|
||||
if (!JsonUtils::validate("EffectFileHandler", message["args"].toObject(), it->schemaFile, _log))
|
||||
if (!JsonUtils::validate("EffectFileHandler", message["args"].toObject(), it->schemaFile, _log).first)
|
||||
{
|
||||
return "Error during arg validation against schema, please consult the Hyperion Log";
|
||||
}
|
||||
@ -298,12 +298,12 @@ bool EffectFileHandler::loadEffectDefinition(const QString& path, const QString&
|
||||
|
||||
// Read and parse the effect json config file
|
||||
QJsonObject configEffect;
|
||||
if (!JsonUtils::readFile(fileName, configEffect, _log)) {
|
||||
if (!JsonUtils::readFile(fileName, configEffect, _log).first) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate effect config with effect schema(path)
|
||||
if (!JsonUtils::validate(fileName, configEffect, ":effect-schema", _log)) {
|
||||
if (!JsonUtils::validate(fileName, configEffect, ":effect-schema", _log).first) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -335,7 +335,7 @@ bool EffectFileHandler::loadEffectSchema(const QString& path, const QString& sch
|
||||
{
|
||||
// Read and parse the effect schema file
|
||||
QJsonObject schemaEffect;
|
||||
if (!JsonUtils::readFile(schemaFilePath, schemaEffect, _log))
|
||||
if (!JsonUtils::readFile(schemaFilePath, schemaEffect, _log).first)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ void EventHandler::handleEvent(Event event)
|
||||
{
|
||||
QObject *senderObj = QObject::sender();
|
||||
QString senderObjectClass;
|
||||
if (senderObj)
|
||||
if (senderObj != nullptr)
|
||||
{
|
||||
senderObjectClass = senderObj->metaObject()->className();
|
||||
} else
|
||||
@ -179,13 +179,19 @@ void EventHandler::handleEvent(Event event)
|
||||
break;
|
||||
|
||||
case Event::Reload:
|
||||
emit signalEvent(Event::Reload);
|
||||
Process::restartHyperion(10);
|
||||
break;
|
||||
|
||||
case Event::Restart:
|
||||
emit signalEvent(Event::Restart);
|
||||
Process::restartHyperion(11);
|
||||
break;
|
||||
|
||||
case Event::Quit:
|
||||
emit signalEvent(Event::Quit);
|
||||
break;
|
||||
|
||||
default:
|
||||
Error(_log,"Unkonwn Event '%d' received", event);
|
||||
break;
|
||||
|
@ -35,7 +35,7 @@ OsEventHandlerBase::OsEventHandlerBase()
|
||||
_log = Logger::getInstance("EVENTS-OS");
|
||||
|
||||
QCoreApplication* app = QCoreApplication::instance();
|
||||
if (!qobject_cast<QApplication*>(app))
|
||||
if (qobject_cast<QApplication*>(app) == nullptr)
|
||||
{
|
||||
_isService = true;
|
||||
}
|
||||
@ -46,6 +46,7 @@ OsEventHandlerBase::OsEventHandlerBase()
|
||||
|
||||
OsEventHandlerBase::~OsEventHandlerBase()
|
||||
{
|
||||
quit();
|
||||
QObject::disconnect(this, &OsEventHandlerBase::signalEvent, EventHandler::getInstance().data(), &EventHandler::handleEvent);
|
||||
|
||||
OsEventHandlerBase::unregisterLockHandler();
|
||||
@ -130,6 +131,11 @@ void OsEventHandlerBase::lock(bool isLocked)
|
||||
}
|
||||
}
|
||||
|
||||
void OsEventHandlerBase::quit()
|
||||
{
|
||||
emit signalEvent(Event::Quit);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
OsEventHandlerWindows* OsEventHandlerWindows::getInstance()
|
||||
|
@ -15,7 +15,6 @@ AuthManager::AuthManager(QObject *parent, bool readonlyMode)
|
||||
, _authTable(new AuthTable("", this, readonlyMode))
|
||||
, _metaTable(new MetaTable(this, readonlyMode))
|
||||
, _pendingRequests()
|
||||
, _authRequired(true)
|
||||
, _timer(new QTimer(this))
|
||||
, _authBlockTimer(new QTimer(this))
|
||||
{
|
||||
@ -36,13 +35,13 @@ AuthManager::AuthManager(QObject *parent, bool readonlyMode)
|
||||
connect(_authBlockTimer, &QTimer::timeout, this, &AuthManager::checkAuthBlockTimeout);
|
||||
|
||||
// init with default user and password
|
||||
if (!_authTable->userExist("Hyperion"))
|
||||
if (!_authTable->userExist(hyperion::DEFAULT_USER))
|
||||
{
|
||||
_authTable->createUser("Hyperion", "hyperion");
|
||||
_authTable->createUser(hyperion::DEFAULT_USER, hyperion::DEFAULT_PASSWORD);
|
||||
}
|
||||
|
||||
// update Hyperion user token on startup
|
||||
_authTable->setUserToken("Hyperion");
|
||||
_authTable->setUserToken(hyperion::DEFAULT_USER);
|
||||
}
|
||||
|
||||
AuthManager::AuthDefinition AuthManager::createToken(const QString &comment)
|
||||
@ -201,6 +200,8 @@ QVector<AuthManager::AuthDefinition> AuthManager::getPendingRequests() const
|
||||
def.comment = entry.comment;
|
||||
def.id = entry.id;
|
||||
def.timeoutTime = entry.timeoutTime - QDateTime::currentMSecsSinceEpoch();
|
||||
def.tan = entry.tan;
|
||||
def.caller = nullptr;
|
||||
finalVec.append(def);
|
||||
}
|
||||
return finalVec;
|
||||
@ -208,20 +209,26 @@ QVector<AuthManager::AuthDefinition> AuthManager::getPendingRequests() const
|
||||
|
||||
bool AuthManager::renameToken(const QString &id, const QString &comment)
|
||||
{
|
||||
if (_authTable->renameToken(id, comment))
|
||||
if (_authTable->idExist(id))
|
||||
{
|
||||
emit tokenChange(getTokenList());
|
||||
return true;
|
||||
if (_authTable->renameToken(id, comment))
|
||||
{
|
||||
emit tokenChange(getTokenList());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AuthManager::deleteToken(const QString &id)
|
||||
{
|
||||
if (_authTable->deleteToken(id))
|
||||
if (_authTable->idExist(id))
|
||||
{
|
||||
emit tokenChange(getTokenList());
|
||||
return true;
|
||||
if (_authTable->deleteToken(id))
|
||||
{
|
||||
emit tokenChange(getTokenList());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -231,9 +238,7 @@ void AuthManager::handleSettingsUpdate(settings::type type, const QJsonDocument
|
||||
if (type == settings::NETWORK)
|
||||
{
|
||||
const QJsonObject &obj = config.object();
|
||||
_authRequired = obj["apiAuth"].toBool(true);
|
||||
_localAuthRequired = obj["localApiAuth"].toBool(false);
|
||||
_localAdminAuthRequired = obj["localAdminAuth"].toBool(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -550,6 +550,11 @@ QList<int> Hyperion::getActivePriorities() const
|
||||
return _muxer->getPriorities();
|
||||
}
|
||||
|
||||
Hyperion::InputsMap Hyperion::getPriorityInfo() const
|
||||
{
|
||||
return _muxer->getInputInfo();
|
||||
}
|
||||
|
||||
Hyperion::InputInfo Hyperion::getPriorityInfo(int priority) const
|
||||
{
|
||||
return _muxer->getInputInfo(priority);
|
||||
|
@ -45,6 +45,11 @@ QVector<QVariantMap> HyperionIManager::getInstanceData() const
|
||||
return instances;
|
||||
}
|
||||
|
||||
QList<quint8> HyperionIManager::getRunningInstanceIdx() const
|
||||
{
|
||||
return _runningInstances.keys();
|
||||
}
|
||||
|
||||
void HyperionIManager::startAll()
|
||||
{
|
||||
for(const auto & entry : _instanceTable->getAllInstances(true))
|
||||
|
@ -128,6 +128,11 @@ bool PriorityMuxer::hasPriority(int priority) const
|
||||
return (priority == PriorityMuxer::LOWEST_PRIORITY) ? true : _activeInputs.contains(priority);
|
||||
}
|
||||
|
||||
PriorityMuxer::InputsMap PriorityMuxer::getInputInfo() const
|
||||
{
|
||||
return _activeInputs;
|
||||
}
|
||||
|
||||
PriorityMuxer::InputInfo PriorityMuxer::getInputInfo(int priority) const
|
||||
{
|
||||
auto elemIt = _activeInputs.constFind(priority);
|
||||
|
@ -52,7 +52,7 @@ SettingsManager::SettingsManager(quint8 instance, QObject* parent, bool readonly
|
||||
|
||||
// get default config
|
||||
QJsonObject defaultConfig;
|
||||
if (!JsonUtils::readFile(":/hyperion_default.config", defaultConfig, _log))
|
||||
if (!JsonUtils::readFile(":/hyperion_default.config", defaultConfig, _log).first)
|
||||
{
|
||||
throw std::runtime_error("Failed to read default config");
|
||||
}
|
||||
|
@ -4,26 +4,13 @@
|
||||
"required" : true,
|
||||
"properties" :
|
||||
{
|
||||
"apiAuth" :
|
||||
{
|
||||
"type" : "boolean",
|
||||
"title" : "edt_conf_net_apiAuth_title",
|
||||
"required" : true,
|
||||
"default" : true,
|
||||
"propertyOrder" : 1
|
||||
},
|
||||
"internetAccessAPI" :
|
||||
{
|
||||
"type" : "boolean",
|
||||
"title" : "edt_conf_net_internetAccessAPI_title",
|
||||
"required" : true,
|
||||
"default" : false,
|
||||
"options": {
|
||||
"dependencies": {
|
||||
"apiAuth": true
|
||||
}
|
||||
},
|
||||
"propertyOrder" : 2
|
||||
"propertyOrder" : 1
|
||||
},
|
||||
"restirctedInternetAccessAPI" :
|
||||
{
|
||||
@ -36,7 +23,7 @@
|
||||
"internetAccessAPI": true
|
||||
}
|
||||
},
|
||||
"propertyOrder" : 3
|
||||
"propertyOrder" : 2
|
||||
},
|
||||
"ipWhitelist" :
|
||||
{
|
||||
@ -53,7 +40,7 @@
|
||||
"restirctedInternetAccessAPI": true
|
||||
}
|
||||
},
|
||||
"propertyOrder" : 4
|
||||
"propertyOrder" : 3
|
||||
},
|
||||
"localApiAuth" :
|
||||
{
|
||||
@ -66,15 +53,7 @@
|
||||
"apiAuth": true
|
||||
}
|
||||
},
|
||||
"propertyOrder" : 5
|
||||
},
|
||||
"localAdminAuth" :
|
||||
{
|
||||
"type" : "boolean",
|
||||
"title" : "edt_conf_net_localAdminAuth_title",
|
||||
"required" : true,
|
||||
"default" : true,
|
||||
"propertyOrder" : 5
|
||||
"propertyOrder" : 4
|
||||
}
|
||||
},
|
||||
"additionalProperties" : false
|
||||
|
@ -193,11 +193,17 @@ QJsonObject LedDeviceWrapper::getLedDeviceSchemas()
|
||||
}
|
||||
|
||||
QJsonObject schema;
|
||||
if(!JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LEDDEVICE")))
|
||||
QPair<bool, QStringList> parsingResult = JsonUtils::parse(schemaPath, data, schema, Logger::getInstance("LEDDEVICE"));
|
||||
if (!parsingResult.first)
|
||||
{
|
||||
throw std::runtime_error("ERROR: JSON schema wrong of file: " + item.toStdString());
|
||||
QStringList errorList = parsingResult.second;
|
||||
for (const auto& errorMessage : errorList) {
|
||||
Debug(Logger::getInstance("LEDDEVICE"), "JSON parse error: %s ", QSTRING_CSTR(errorMessage));
|
||||
}
|
||||
throw std::runtime_error("ERROR: JSON schema is wrong for file: " + item.toStdString());
|
||||
}
|
||||
|
||||
|
||||
schemaJson = schema;
|
||||
schemaJson["title"] = QString("edt_dev_spec_header_title");
|
||||
|
||||
|
@ -8,25 +8,26 @@
|
||||
#include <QRegularExpression>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonParseError>
|
||||
#include <QStringList>
|
||||
|
||||
namespace JsonUtils {
|
||||
|
||||
bool readFile(const QString& path, QJsonObject& obj, Logger* log, bool ignError)
|
||||
QPair<bool, QStringList> readFile(const QString& path, QJsonObject& obj, Logger* log, bool ignError)
|
||||
{
|
||||
QString data;
|
||||
if(!FileUtils::readFile(path, data, log, ignError))
|
||||
return false;
|
||||
{
|
||||
return qMakePair(false, QStringList(QString("Error reading file: %1").arg(path)));
|
||||
}
|
||||
|
||||
if(!parse(path, data, obj, log))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
QPair<bool, QStringList> parsingResult = JsonUtils::parse(path, data, obj, log);
|
||||
return parsingResult;
|
||||
}
|
||||
|
||||
bool readSchema(const QString& path, QJsonObject& obj, Logger* log)
|
||||
{
|
||||
QJsonObject schema;
|
||||
if(!readFile(path, schema, log))
|
||||
if(!readFile(path, schema, log).first)
|
||||
return false;
|
||||
|
||||
if(!resolveRefs(schema, obj, log))
|
||||
@ -35,80 +36,89 @@ namespace JsonUtils {
|
||||
return true;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
QJsonDocument doc;
|
||||
if(!parse(path, data, doc, log))
|
||||
return false;
|
||||
|
||||
QPair<bool, QStringList> parsingResult = JsonUtils::parse(path, data, doc, log);
|
||||
obj = doc.object();
|
||||
return true;
|
||||
return parsingResult;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
QJsonDocument doc;
|
||||
if(!parse(path, data, doc, log))
|
||||
return false;
|
||||
|
||||
QPair<bool, QStringList> parsingResult = JsonUtils::parse(path, data, doc, log);
|
||||
arr = doc.array();
|
||||
return true;
|
||||
return parsingResult;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
//remove Comments in data
|
||||
QString cleanData = data;
|
||||
QStringList errorList;
|
||||
|
||||
QJsonParseError error;
|
||||
doc = QJsonDocument::fromJson(cleanData.toUtf8(), &error);
|
||||
doc = QJsonDocument::fromJson(data.toUtf8(), &error);
|
||||
|
||||
if (error.error != QJsonParseError::NoError)
|
||||
{
|
||||
// report to the user the failure and their locations in the document.
|
||||
int errorLine(0), errorColumn(0);
|
||||
int errorLine = 1;
|
||||
int errorColumn = 1;
|
||||
|
||||
for( int i=0, count=qMin( error.offset,cleanData.size()); i<count; ++i )
|
||||
int lastNewlineIndex = data.lastIndexOf("\n", error.offset - 1);
|
||||
if (lastNewlineIndex != -1)
|
||||
{
|
||||
++errorColumn;
|
||||
if(data.at(i) == '\n' )
|
||||
{
|
||||
errorColumn = 0;
|
||||
++errorLine;
|
||||
}
|
||||
errorColumn = error.offset - lastNewlineIndex ;
|
||||
}
|
||||
Error(log, "Failed to parse json data from %s: Error: %s at Line: %i, Column: %i, Data: '%s'", QSTRING_CSTR(path), QSTRING_CSTR(error.errorString()), errorLine, errorColumn, QSTRING_CSTR(data));
|
||||
return false;
|
||||
errorLine += data.left(error.offset).count('\n');
|
||||
|
||||
const QString errorMessage = QString("JSON parse error: %1, line: %2, column: %3, Data: '%4'")
|
||||
.arg(error.errorString())
|
||||
.arg(errorLine)
|
||||
.arg(errorColumn)
|
||||
.arg(data);
|
||||
errorList.push_back(errorMessage);
|
||||
Error(log, "%s", QSTRING_CSTR(errorMessage));
|
||||
|
||||
return qMakePair(false, errorList);
|
||||
}
|
||||
return true;
|
||||
return qMakePair(true, errorList);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// get the schema data
|
||||
QJsonObject schema;
|
||||
if(!readFile(schemaPath, schema, log))
|
||||
return false;
|
||||
|
||||
if(!validate(file, json, schema, log))
|
||||
return false;
|
||||
return true;
|
||||
QPair<bool, QStringList> readResult = readFile(schemaPath, schema, log);
|
||||
if(!readResult.first)
|
||||
{
|
||||
return readResult;
|
||||
}
|
||||
|
||||
QPair<bool, QStringList> validationResult = validate(file, json, schema, log);
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
QStringList errorList;
|
||||
|
||||
QJsonSchemaChecker schemaChecker;
|
||||
schemaChecker.setSchema(schema);
|
||||
if (!schemaChecker.validate(json).first)
|
||||
{
|
||||
const QStringList & errors = schemaChecker.getMessages();
|
||||
for (auto & error : errors)
|
||||
const QStringList &errors = schemaChecker.getMessages();
|
||||
for (const auto& error : errors)
|
||||
{
|
||||
Error(log, "While validating schema against json data of '%s':%s", QSTRING_CSTR(file), QSTRING_CSTR(error));
|
||||
QString errorMessage = QString("JSON parse error: %1")
|
||||
.arg(error);
|
||||
errorList.push_back(errorMessage);
|
||||
Error(log, "%s", QSTRING_CSTR(errorMessage));
|
||||
}
|
||||
return false;
|
||||
return qMakePair(false, errorList);
|
||||
}
|
||||
return true;
|
||||
return qMakePair(true, errorList);
|
||||
}
|
||||
|
||||
bool write(const QString& filename, const QJsonObject& json, Logger* log)
|
||||
|
@ -1,13 +1,15 @@
|
||||
#include <utils/NetOrigin.h>
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QNetworkInterface>
|
||||
|
||||
NetOrigin* NetOrigin::instance = nullptr;
|
||||
|
||||
NetOrigin::NetOrigin(QObject* parent, Logger* log)
|
||||
: QObject(parent)
|
||||
, _log(log)
|
||||
, _internetAccessAllowed(false)
|
||||
, _isInternetAccessAllowed(false)
|
||||
, _isInternetAccessRestricted(false)
|
||||
, _ipWhitelist()
|
||||
{
|
||||
NetOrigin::instance = this;
|
||||
@ -15,37 +17,73 @@ NetOrigin::NetOrigin(QObject* parent, Logger* log)
|
||||
|
||||
bool NetOrigin::accessAllowed(const QHostAddress& address, const QHostAddress& local) const
|
||||
{
|
||||
if(_internetAccessAllowed)
|
||||
return true;
|
||||
bool isAllowed {false};
|
||||
|
||||
if(_ipWhitelist.contains(address)) // v4 and v6
|
||||
return true;
|
||||
|
||||
if(!isLocalAddress(address, local))
|
||||
if(isLocalAddress(address, local))
|
||||
{
|
||||
Warning(_log,"Client connection with IP address '%s' has been rejected! It's not whitelisted, access denied.",QSTRING_CSTR(address.toString()));
|
||||
return false;
|
||||
isAllowed = true;
|
||||
}
|
||||
return true;
|
||||
else
|
||||
{
|
||||
if(_isInternetAccessAllowed)
|
||||
{
|
||||
if (!_isInternetAccessRestricted)
|
||||
{
|
||||
isAllowed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const QHostAddress &listAddress : _ipWhitelist)
|
||||
{
|
||||
if (address.isEqual(listAddress))
|
||||
{
|
||||
isAllowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
WarningIf(!isAllowed, _log,"Client connection from IP address '%s' has been rejected! It's not whitelisted.",QSTRING_CSTR(address.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return isAllowed;
|
||||
}
|
||||
|
||||
bool NetOrigin::isLocalAddress(const QHostAddress& address, const QHostAddress& local) const
|
||||
|
||||
bool NetOrigin::isLocalAddress(const QHostAddress& ipAddress, const QHostAddress& /*local*/) const
|
||||
{
|
||||
if(address.protocol() == QAbstractSocket::IPv4Protocol)
|
||||
QHostAddress address = ipAddress;
|
||||
|
||||
if (address.isLoopback() || address.isLinkLocal())
|
||||
{
|
||||
if(!address.isInSubnet(local, 24)) // 255.255.255.xxx; IPv4 0-32
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Convert to IPv4 to check, if an IPv6 address is an IPv4 mapped address
|
||||
QHostAddress ipv4Address(address.toIPv4Address());
|
||||
if (ipv4Address != QHostAddress::AnyIPv4) // ipv4Address is not "0.0.0.0"
|
||||
{
|
||||
address = ipv4Address;
|
||||
}
|
||||
|
||||
QList<QNetworkInterface> allInterfaces = QNetworkInterface::allInterfaces();
|
||||
for (const QNetworkInterface &networkInterface : allInterfaces) {
|
||||
QList<QNetworkAddressEntry> addressEntries = networkInterface.addressEntries();
|
||||
for (const QNetworkAddressEntry &localNetworkAddressEntry : addressEntries) {
|
||||
QHostAddress localIP = localNetworkAddressEntry.ip();
|
||||
|
||||
if(localIP.protocol() != QAbstractSocket::NetworkLayerProtocol::IPv4Protocol)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isInSubnet = address.isInSubnet(localIP, localNetworkAddressEntry.prefixLength());
|
||||
if (isInSubnet)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(address.protocol() == QAbstractSocket::IPv6Protocol)
|
||||
{
|
||||
if(!address.isInSubnet(local, 64)) // 2001:db8:abcd:0012:XXXX:XXXX:XXXX:XXXX; IPv6 0-128
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void NetOrigin::handleSettingsUpdate(settings::type type, const QJsonDocument& config)
|
||||
@ -53,16 +91,19 @@ void NetOrigin::handleSettingsUpdate(settings::type type, const QJsonDocument& c
|
||||
if(type == settings::NETWORK)
|
||||
{
|
||||
const QJsonObject& obj = config.object();
|
||||
_internetAccessAllowed = obj["internetAccessAPI"].toBool(false);
|
||||
_isInternetAccessAllowed = obj["internetAccessAPI"].toBool(false);
|
||||
_isInternetAccessRestricted = obj["restirctedInternetAccessAPI"].toBool(false);
|
||||
const QJsonArray arr = obj["ipWhitelist"].toArray();
|
||||
|
||||
const QJsonArray& arr = obj["ipWhitelist"].toArray();
|
||||
_ipWhitelist.clear();
|
||||
_ipWhitelist.clear();
|
||||
|
||||
for(const auto& e : arr)
|
||||
for(const auto& item : std::as_const(arr))
|
||||
{
|
||||
const QString& entry = e.toString("");
|
||||
const QString& entry = item.toString("");
|
||||
if(entry.isEmpty())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QHostAddress host(entry);
|
||||
if(host.isNull())
|
||||
|
@ -125,7 +125,7 @@ void JsonConnection::setEffect(const QString &effectName, const QString & effect
|
||||
if (effectArgs.size() > 0)
|
||||
{
|
||||
QJsonObject effObj;
|
||||
if(!JsonUtils::parse("hyperion-remote-args", effectArgs, effObj, _log))
|
||||
if(!JsonUtils::parse("hyperion-remote-args", effectArgs, effObj, _log).first)
|
||||
{
|
||||
throw std::runtime_error("Error in effect arguments, abort");
|
||||
}
|
||||
@ -160,7 +160,7 @@ void JsonConnection::createEffect(const QString &effectName, const QString &effe
|
||||
if (effectArgs.size() > 0)
|
||||
{
|
||||
QJsonObject effObj;
|
||||
if(!JsonUtils::parse("hyperion-remote-args", effectScript, effObj, _log))
|
||||
if(!JsonUtils::parse("hyperion-remote-args", effectScript, effObj, _log).first)
|
||||
{
|
||||
throw std::runtime_error("Error in effect arguments, abort");
|
||||
}
|
||||
@ -440,7 +440,7 @@ void JsonConnection::setConfig(const QString &jsonString)
|
||||
if (jsonString.size() > 0)
|
||||
{
|
||||
QJsonObject configObj;
|
||||
if(!JsonUtils::parse("hyperion-remote-args", jsonString, configObj, _log))
|
||||
if(!JsonUtils::parse("hyperion-remote-args", jsonString, configObj, _log).first)
|
||||
{
|
||||
throw std::runtime_error("Error in configSet arguments, abort");
|
||||
}
|
||||
|
@ -231,7 +231,7 @@ int main(int argc, char** argv)
|
||||
|
||||
ScreenshotHandler handler("screenshot.png", signalDetectionOffset);
|
||||
QObject::connect(&grabber, SIGNAL(newFrame(Image<ColorRgb>)), &handler, SLOT(receiveImage(Image<ColorRgb>)));
|
||||
grabber.prepare();
|
||||
grabber.prepare();
|
||||
grabber.start();
|
||||
QCoreApplication::exec();
|
||||
grabber.stop();
|
||||
|
@ -84,10 +84,8 @@ void SysTray::createTrayIcon()
|
||||
|
||||
restartAction = new QAction(tr("&Restart"), this);
|
||||
restartAction->setIcon(QPixmap(":/restart.svg"));
|
||||
connect(restartAction, &QAction::triggered, this , [=](){ Process::restartHyperion(12); });
|
||||
connect(restartAction, &QAction::triggered, this , [=](){ emit signalEvent(Event::Restart); });
|
||||
|
||||
|
||||
// TODO: Check if can be done with SystemEvents
|
||||
suspendAction = new QAction(tr("&Suspend"), this);
|
||||
suspendAction->setIcon(QPixmap(":/suspend.svg"));
|
||||
connect(suspendAction, &QAction::triggered, this, [this]() { emit signalEvent(Event::Suspend); });
|
||||
@ -129,7 +127,9 @@ void SysTray::createTrayIcon()
|
||||
|
||||
// add seperator if custom effects exists
|
||||
if (!_trayIconEfxMenu->isEmpty())
|
||||
{
|
||||
_trayIconEfxMenu->addSeparator();
|
||||
}
|
||||
|
||||
// build in effects
|
||||
for (const auto &efx : efxs)
|
||||
|
Loading…
x
Reference in New Issue
Block a user