From 5e3bc2acbd8faa4b133b7702f7f0ba5b2765a6fe Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 20 Oct 2019 00:34:21 +0200 Subject: [PATCH 01/22] Drop JsonTypes class by distributing logic to json handlers This is required in order to be able to be more flexible in registering new types/methods. --- libnymea-core/jsonrpc/actionhandler.cpp | 93 +- libnymea-core/jsonrpc/actionhandler.h | 2 +- .../jsonrpc/configurationhandler.cpp | 408 +-- libnymea-core/jsonrpc/configurationhandler.h | 16 +- libnymea-core/jsonrpc/devicehandler.cpp | 947 +++++-- libnymea-core/jsonrpc/devicehandler.h | 27 +- libnymea-core/jsonrpc/eventhandler.cpp | 53 +- libnymea-core/jsonrpc/eventhandler.h | 6 +- libnymea-core/jsonrpc/jsonhandler.cpp | 354 --- libnymea-core/jsonrpc/jsonhandler.h | 126 - libnymea-core/jsonrpc/jsonrpcserver.cpp | 369 +-- libnymea-core/jsonrpc/jsonrpcserver.h | 7 +- libnymea-core/jsonrpc/jsontypes.cpp | 2392 ----------------- libnymea-core/jsonrpc/jsontypes.h | 292 -- libnymea-core/jsonrpc/jsonvalidator.cpp | 223 ++ libnymea-core/jsonrpc/jsonvalidator.h | 49 + libnymea-core/jsonrpc/logginghandler.cpp | 202 +- libnymea-core/jsonrpc/logginghandler.h | 8 +- .../jsonrpc/networkmanagerhandler.cpp | 227 +- libnymea-core/jsonrpc/networkmanagerhandler.h | 10 +- libnymea-core/jsonrpc/ruleshandler.cpp | 789 +++++- libnymea-core/jsonrpc/ruleshandler.h | 37 +- libnymea-core/jsonrpc/statehandler.cpp | 31 +- libnymea-core/jsonrpc/statehandler.h | 4 +- libnymea-core/jsonrpc/systemhandler.cpp | 224 +- libnymea-core/jsonrpc/systemhandler.h | 8 +- libnymea-core/jsonrpc/tagshandler.cpp | 117 +- libnymea-core/jsonrpc/tagshandler.h | 10 +- libnymea-core/libnymea-core.pro | 6 +- libnymea-core/logging/logentry.cpp | 12 +- libnymea/devices/pluginmetadata.cpp | 32 + libnymea/jsonrpc/jsonhandler.cpp | 134 + libnymea/jsonrpc/jsonhandler.h | 99 + libnymea/jsonrpc/jsonreply.cpp | 123 + libnymea/jsonrpc/jsonreply.h | 62 + libnymea/libnymea.pro | 4 + plugins/mock/devicepluginmock.json | 2 +- plugins/mock/plugininfo.h | 4 +- tests/auto/actions/testactions.cpp | 5 +- .../configurations/testconfigurations.cpp | 5 + tests/auto/devices/testdevices.cpp | 8 +- tests/auto/events/testevents.cpp | 2 +- tests/auto/jsonrpc/testjsonrpc.cpp | 13 +- tests/auto/logging/testlogging.cpp | 79 +- tests/auto/rules/testrules.cpp | 68 +- tests/auto/states/teststates.cpp | 2 +- tests/auto/tags/testtags.cpp | 6 + tests/auto/timemanager/testtimemanager.cpp | 23 +- tests/auto/usermanager/testusermanager.cpp | 1 + tests/auto/webserver/testwebserver.cpp | 2 +- tests/scripts/introspect.sh | 11 +- tests/testlib/nymeatestbase.cpp | 3 +- tests/testlib/nymeatestbase.h | 24 +- 53 files changed, 3444 insertions(+), 4317 deletions(-) delete mode 100644 libnymea-core/jsonrpc/jsonhandler.cpp delete mode 100644 libnymea-core/jsonrpc/jsonhandler.h delete mode 100644 libnymea-core/jsonrpc/jsontypes.cpp delete mode 100644 libnymea-core/jsonrpc/jsontypes.h create mode 100644 libnymea-core/jsonrpc/jsonvalidator.cpp create mode 100644 libnymea-core/jsonrpc/jsonvalidator.h create mode 100644 libnymea/jsonrpc/jsonhandler.cpp create mode 100644 libnymea/jsonrpc/jsonhandler.h create mode 100644 libnymea/jsonrpc/jsonreply.cpp create mode 100644 libnymea/jsonrpc/jsonreply.h diff --git a/libnymea-core/jsonrpc/actionhandler.cpp b/libnymea-core/jsonrpc/actionhandler.cpp index 5a56f3b3..19c204e7 100644 --- a/libnymea-core/jsonrpc/actionhandler.cpp +++ b/libnymea-core/jsonrpc/actionhandler.cpp @@ -33,6 +33,7 @@ */ #include "actionhandler.h" +#include "devicehandler.h" #include "nymeacore.h" #include "devices/devicemanager.h" @@ -48,41 +49,45 @@ namespace nymeaserver { ActionHandler::ActionHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap params; - QVariantMap returns; + // Objects + QVariantMap action; + action.insert("actionTypeId", enumValueName(Uuid)); + action.insert("deviceId", enumValueName(Uuid)); + action.insert("o:params", QVariantList() << objectRef("Param")); + registerObject("Action", action); + + // Methods + QString description; QVariantMap params; QVariantMap returns; + description = "Execute a single action."; + params.insert("actionTypeId", enumValueName(Uuid)); + params.insert("deviceId", enumValueName(Uuid)); + params.insert("o:params", QVariantList() << objectRef("Param")); + returns.insert("deviceError", enumRef()); + returns.insert("o:displayMessage", enumValueName(String)); + registerMethod("ExecuteAction", description, params, returns); params.clear(); returns.clear(); - setDescription("ExecuteAction", "Execute a single action."); - setParams("ExecuteAction", JsonTypes::actionDescription()); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("ExecuteAction", returns); + description = "Get the ActionType for the given ActionTypeId"; + params.insert("actionTypeId", enumValueName(Uuid)); + returns.insert("deviceError", enumRef()); + returns.insert("o:actionType", objectRef("ActionType")); + registerMethod("GetActionType", description, params, returns); params.clear(); returns.clear(); - setDescription("GetActionType", "Get the ActionType for the given ActionTypeId"); - params.insert("actionTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetActionType", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:actionType", JsonTypes::actionTypeDescription()); - setReturns("GetActionType", returns); + description = "Execute the item identified by itemId on the given device."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("itemId", enumValueName(String)); + returns.insert("deviceError", enumRef()); + registerMethod("ExecuteBrowserItem", description, params, returns); params.clear(); returns.clear(); - setDescription("ExecuteBrowserItem", "Execute the item identified by itemId on the given device."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("itemId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("ExecuteBrowserItem", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - setReturns("ExecuteBrowserItem", returns); - - params.clear(); returns.clear(); - setDescription("ExecuteBrowserItemAction", "Execute the action for the browser item identified by actionTypeId and the itemId on the given device."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("itemId", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("actionTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:params", QVariantList() << JsonTypes::paramRef()); - setParams("ExecuteBrowserItemAction", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - setReturns("ExecuteBrowserItemAction", returns); + description = "Execute the action for the browser item identified by actionTypeId and the itemId on the given device."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("itemId", enumValueName(String)); + params.insert("actionTypeId", enumValueName(Uuid)); + params.insert("o:params", QVariantList() << objectRef("Param")); + returns.insert("deviceError", enumRef()); + registerMethod("ExecuteBrowserItemAction", description, params, returns); } @@ -96,7 +101,7 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap ¶ms) { DeviceId deviceId(params.value("deviceId").toString()); ActionTypeId actionTypeId(params.value("actionTypeId").toString()); - ParamList actionParams = JsonTypes::unpackParams(params.value("params").toList()); + ParamList actionParams = DeviceHandler::unpackParams(params.value("params").toList()); QLocale locale = params.value("locale").toLocale(); Action action(actionTypeId, deviceId); @@ -105,8 +110,9 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap ¶ms) JsonReply *jsonReply = createAsyncReply("ExecuteAction"); DeviceActionInfo *info = NymeaCore::instance()->executeAction(action); - connect(info, &DeviceActionInfo::finished, jsonReply, [this, info, jsonReply, locale](){ - QVariantMap data = statusToReply(info->status()); + connect(info, &DeviceActionInfo::finished, jsonReply, [info, jsonReply, locale](){ + QVariantMap data; + data.insert("deviceError", enumValueName(info->status())); if (!info->displayMessage().isEmpty()) { data.insert("displayMessage", info->translatedDisplayMessage(locale)); } @@ -124,13 +130,16 @@ JsonReply *ActionHandler::GetActionType(const QVariantMap ¶ms) const foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const ActionType &actionType, deviceClass.actionTypes()) { if (actionType.id() == actionTypeId) { - QVariantMap data = statusToReply(Device::DeviceErrorNoError); - data.insert("actionType", JsonTypes::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); + QVariantMap data; + data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); + data.insert("actionType", DeviceHandler::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); return createReply(data); } } } - return createReply(statusToReply(Device::DeviceErrorActionTypeNotFound)); + QVariantMap data; + data.insert("deviceError", enumValueName(Device::DeviceErrorActionTypeNotFound)); + return createReply(data); } JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap ¶ms) @@ -142,8 +151,10 @@ JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap ¶ms) JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItem"); BrowserActionInfo *info = NymeaCore::instance()->executeBrowserItem(action); - connect(info, &BrowserActionInfo::finished, jsonReply, [this, info, jsonReply](){ - jsonReply->setData(statusToReply(info->status())); + connect(info, &BrowserActionInfo::finished, jsonReply, [info, jsonReply](){ + QVariantMap data; + data.insert("deviceError", enumValueName(info->status())); + jsonReply->setData(data); jsonReply->finished(); }); @@ -155,14 +166,16 @@ JsonReply *ActionHandler::ExecuteBrowserItemAction(const QVariantMap ¶ms) DeviceId deviceId = DeviceId(params.value("deviceId").toString()); QString itemId = params.value("itemId").toString(); ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString()); - ParamList paramList = JsonTypes::unpackParams(params.value("params").toList()); + ParamList paramList = DeviceHandler::unpackParams(params.value("params").toList()); BrowserItemAction browserItemAction(deviceId, itemId, actionTypeId, paramList); JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItemAction"); BrowserItemActionInfo *info = NymeaCore::instance()->executeBrowserItemAction(browserItemAction); - connect(info, &BrowserItemActionInfo::finished, jsonReply, [this, info, jsonReply](){ - jsonReply->setData(statusToReply(info->status())); + connect(info, &BrowserItemActionInfo::finished, jsonReply, [info, jsonReply](){ + QVariantMap data; + data.insert("deviceError", enumValueName(info->status())); + jsonReply->setData(data); jsonReply->finished(); }); diff --git a/libnymea-core/jsonrpc/actionhandler.h b/libnymea-core/jsonrpc/actionhandler.h index da081871..d1cae8be 100644 --- a/libnymea-core/jsonrpc/actionhandler.h +++ b/libnymea-core/jsonrpc/actionhandler.h @@ -22,7 +22,7 @@ #ifndef ACTIONHANDLER_H #define ACTIONHANDLER_H -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" #include "devices/devicemanager.h" namespace nymeaserver { diff --git a/libnymea-core/jsonrpc/configurationhandler.cpp b/libnymea-core/jsonrpc/configurationhandler.cpp index 0ae065fc..597d50a7 100644 --- a/libnymea-core/jsonrpc/configurationhandler.cpp +++ b/libnymea-core/jsonrpc/configurationhandler.cpp @@ -60,6 +60,7 @@ #include "configurationhandler.h" #include "nymeacore.h" +#include "nymeaconfiguration.h" namespace nymeaserver { @@ -67,229 +68,233 @@ namespace nymeaserver { ConfigurationHandler::ConfigurationHandler(QObject *parent): JsonHandler(parent) { + // Enums + registerEnum(); + + // Objects + QVariantMap serverConfiguration; + serverConfiguration.insert("id", enumValueName(String)); + serverConfiguration.insert("address", enumValueName(String)); + serverConfiguration.insert("port", enumValueName(Uint)); + serverConfiguration.insert("sslEnabled", enumValueName(Bool)); + serverConfiguration.insert("authenticationEnabled", enumValueName(Bool)); + registerObject("ServerConfiguration", serverConfiguration); + + QVariantMap webServerConfiguration = serverConfiguration; + webServerConfiguration.insert("publicFolder", enumValueName(String)); + registerObject("WebServerConfiguration", webServerConfiguration); + + QVariantMap mqttPolicy; + mqttPolicy.insert("clientId", enumValueName(String)); + mqttPolicy.insert("username", enumValueName(String)); + mqttPolicy.insert("password", enumValueName(String)); + mqttPolicy.insert("allowedPublishTopicFilters", enumValueName(StringList)); + mqttPolicy.insert("allowedSubscribeTopicFilters", enumValueName(StringList)); + registerObject("MqttPolicy", mqttPolicy); + // Methods - QVariantMap params; QVariantMap returns; - setDescription("GetTimeZones", "Get the list of available timezones."); - setParams("GetTimeZones", params); - returns.insert("timeZones", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("GetTimeZones", returns); + QString description; QVariantMap params; QVariantMap returns; + description = "Get the list of available timezones."; + returns.insert("timeZones", QVariantList() << enumValueName(String)); + registerMethod("GetTimeZones", description, params, returns); params.clear(); returns.clear(); - setDescription("GetAvailableLanguages", "DEPRECATED - Use the locale property in the Handshake message instead - Returns a list of locale codes available for the server. i.e. en_US, de_AT"); - setParams("GetAvailableLanguages", params); - returns.insert("languages", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("GetAvailableLanguages", returns); + description = "DEPRECATED - Use the locale property in the Handshake message instead - Returns a list of locale codes available for the server. i.e. en_US, de_AT"; + returns.insert("languages", QVariantList() << enumValueName(String)); + registerMethod("GetAvailableLanguages", description, params, returns); params.clear(); returns.clear(); - setDescription("GetConfigurations", "Get all configuration parameters of the server."); - setParams("GetConfigurations", params); + description = "Get all configuration parameters of the server."; QVariantMap basicConfiguration; - basicConfiguration.insert("serverName", JsonTypes::basicTypeToString(JsonTypes::String)); - basicConfiguration.insert("serverUuid", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - basicConfiguration.insert("serverTime", JsonTypes::basicTypeToString(JsonTypes::Uint)); - basicConfiguration.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String)); - basicConfiguration.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); - basicConfiguration.insert("debugServerEnabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); + basicConfiguration.insert("serverName", enumValueName(String)); + basicConfiguration.insert("serverUuid", enumValueName(Uuid)); + basicConfiguration.insert("serverTime", enumValueName(Uint)); + basicConfiguration.insert("timeZone", enumValueName(String)); + basicConfiguration.insert("language", enumValueName(String)); + basicConfiguration.insert("debugServerEnabled", enumValueName(Bool)); returns.insert("basicConfiguration", basicConfiguration); QVariantList tcpServerConfigurations; - tcpServerConfigurations.append(JsonTypes::serverConfigurationRef()); + tcpServerConfigurations.append(objectRef("ServerConfiguration")); returns.insert("tcpServerConfigurations", tcpServerConfigurations); QVariantList webServerConfigurations; - webServerConfigurations.append(JsonTypes::webServerConfigurationRef()); + webServerConfigurations.append(objectRef("WebServerConfiguration")); returns.insert("webServerConfigurations", webServerConfigurations); QVariantList webSocketServerConfigurations; - webSocketServerConfigurations.append(JsonTypes::serverConfigurationRef()); + webSocketServerConfigurations.append(objectRef("ServerConfiguration")); returns.insert("webSocketServerConfigurations", webSocketServerConfigurations); QVariantList mqttServerConfigurations; - mqttServerConfigurations.append(JsonTypes::serverConfigurationRef()); + mqttServerConfigurations.append(objectRef("ServerConfiguration")); QVariantMap cloudConfiguration; - cloudConfiguration.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); + cloudConfiguration.insert("enabled", enumValueName(Bool)); returns.insert("cloud", cloudConfiguration); - setReturns("GetConfigurations", returns); + registerMethod("GetConfigurations", description, params, returns); params.clear(); returns.clear(); - setDescription("SetServerName", "Set the name of the server. Default is nymea."); - params.insert("serverName", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("SetServerName", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetServerName", returns); + description = "Set the name of the server. Default is nymea."; + params.insert("serverName", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("SetServerName", description, params, returns); params.clear(); returns.clear(); - setDescription("SetTimeZone", "Set the time zone of the server. See also: \"GetTimeZones\""); - params.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("SetTimeZone", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetTimeZone", returns); + description = "Set the time zone of the server. See also: \"GetTimeZones\""; + params.insert("timeZone", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("SetTimeZone", description, params, returns); params.clear(); returns.clear(); - setDescription("SetLanguage", "DEPRECATED - Use the locale property in the Handshake message instead - Sets the server language to the given language. See also: \"GetAvailableLanguages\""); - params.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("SetLanguage", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetLanguage", returns); + description = "DEPRECATED - Use the locale property in the Handshake message instead - Sets the server language to the given language. See also: \"GetAvailableLanguages\""; + params.insert("language", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("SetLanguage", description, params, returns); params.clear(); returns.clear(); - setDescription("SetDebugServerEnabled", "Enable or disable the debug server."); - params.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("SetDebugServerEnabled", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetDebugServerEnabled", returns); + description = "Enable or disable the debug server."; + params.insert("enabled", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("SetDebugServerEnabled", description, params, returns); params.clear(); returns.clear(); - setDescription("SetTcpServerConfiguration", "Configure a TCP interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped."); - params.insert("configuration", JsonTypes::serverConfigurationRef()); - setParams("SetTcpServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetTcpServerConfiguration", returns); + description = "Configure a TCP interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped."; + params.insert("configuration", objectRef("ServerConfiguration")); + returns.insert("configurationError", enumRef()); + registerMethod("SetTcpServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("DeleteTcpServerConfiguration", "Delete a TCP interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("DeleteTcpServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("DeleteTcpServerConfiguration", returns); + description = "Delete a TCP interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped."; + params.insert("id", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("DeleteTcpServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("SetWebSocketServerConfiguration", "Configure a WebSocket Server interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped."); - params.insert("configuration", JsonTypes::serverConfigurationRef()); - setParams("SetWebSocketServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetWebSocketServerConfiguration", returns); + description = "Configure a WebSocket Server interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped."; + params.insert("configuration", objectRef("ServerConfiguration")); + returns.insert("configurationError", enumRef()); + registerMethod("SetWebSocketServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("DeleteWebSocketServerConfiguration", "Delete a WebSocket Server interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("DeleteWebSocketServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("DeleteWebSocketServerConfiguration", returns); + description = "Delete a WebSocket Server interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped."; + params.insert("id", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("DeleteWebSocketServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("SetWebServerConfiguration", "Configure a WebServer interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added."); - params.insert("configuration", JsonTypes::webServerConfigurationRef()); - setParams("SetWebServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetWebServerConfiguration", returns); + description = "Configure a WebServer interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added."; + params.insert("configuration", objectRef("WebServerConfiguration")); + returns.insert("configurationError", enumRef()); + registerMethod("SetWebServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("DeleteWebServerConfiguration", "Delete a WebServer interface of the server."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("DeleteWebServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("DeleteWebServerConfiguration", returns); + description = "Delete a WebServer interface of the server."; + params.insert("id", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("DeleteWebServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("SetCloudEnabled", "Sets whether the cloud connection is enabled or disabled in the settings."); - params.insert("enabled", JsonTypes::basicTypeToString(QVariant::Bool)); - setParams("SetCloudEnabled", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetCloudEnabled", returns); + description = "Sets whether the cloud connection is enabled or disabled in the settings."; + params.insert("enabled", enumValueName(Bool)); + returns.insert("configurationError", enumRef()); + registerMethod("SetCloudEnabled", description, params, returns); // MQTT params.clear(); returns.clear(); - setDescription("GetMqttServerConfigurations", "Get all MQTT Server configurations."); - setParams("GetMqttServerConfigurations", params); - returns.insert("mqttServerConfigurations", QVariantList() << JsonTypes::serverConfigurationRef()); - setReturns("GetMqttServerConfigurations", returns); + description = "Get all MQTT Server configurations."; + returns.insert("mqttServerConfigurations", QVariantList() << objectRef("ServerConfiguration")); + registerMethod("GetMqttServerConfigurations", description, params, returns); params.clear(); returns.clear(); - setDescription("SetMqttServerConfiguration", "Configure a MQTT Server interface on the MQTT broker. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Setting authenticationEnabled to true will require MQTT clients to use credentials set in the MQTT broker policies."); - params.insert("configuration", JsonTypes::serverConfigurationRef()); - setParams("SetMqttServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetMqttServerConfiguration", returns); + description = "Configure a MQTT Server interface on the MQTT broker. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Setting authenticationEnabled to true will require MQTT clients to use credentials set in the MQTT broker policies."; + params.insert("configuration", objectRef("ServerConfiguration")); + returns.insert("configurationError", enumRef()); + registerMethod("SetMqttServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("DeleteMqttServerConfiguration", "Delete a MQTT Server interface of the server."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("DeleteMqttServerConfiguration", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("DeleteMqttServerConfiguration", returns); + description = "Delete a MQTT Server interface of the server."; + params.insert("id", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("DeleteMqttServerConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("GetMqttPolicies", "Get all MQTT broker policies."); - setParams("GetMqttPolicies", params); - returns.insert("mqttPolicies", QVariantList() << JsonTypes::mqttPolicyRef()); - setReturns("GetMqttPolicies", returns); + description = "Get all MQTT broker policies."; + returns.insert("mqttPolicies", QVariantList() << objectRef("MqttPolicy")); + registerMethod("GetMqttPolicies", description, params, returns); params.clear(); returns.clear(); - setDescription("SetMqttPolicy", "Configure a MQTT broker policy. If the ID is an existing one, the existing policy will be modified, otherwise a new one will be added."); - params.insert("policy", JsonTypes::mqttPolicyRef()); - setParams("SetMqttPolicy", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("SetMqttPolicy", returns); + description = "Configure a MQTT broker policy. If the ID is an existing one, the existing policy will be modified, otherwise a new one will be added."; + params.insert("policy", objectRef("MqttPolicy")); + returns.insert("configurationError", enumRef()); + registerMethod("SetMqttPolicy", description, params, returns); params.clear(); returns.clear(); - setDescription("DeleteMqttPolicy", "Delete a MQTT policy from the broker."); - params.insert("clientId", JsonTypes::basicTypeToString(QVariant::String)); - setParams("DeleteMqttPolicy", params); - returns.insert("configurationError", JsonTypes::configurationErrorRef()); - setReturns("DeleteMqttPolicy", returns); + description = "Delete a MQTT policy from the broker."; + params.insert("clientId", enumValueName(String)); + returns.insert("configurationError", enumRef()); + registerMethod("DeleteMqttPolicy", description, params, returns); // Notifications params.clear(); returns.clear(); - setDescription("BasicConfigurationChanged", "Emitted whenever the basic configuration of this server changes."); + description = "Emitted whenever the basic configuration of this server changes."; params.insert("basicConfiguration", basicConfiguration); - setParams("BasicConfigurationChanged", params); + registerNotification("BasicConfigurationChanged", description, params); params.clear(); returns.clear(); - setDescription("LanguageChanged", "Emitted whenever the language of the server changed. The Plugins, Vendors and DeviceClasses have to be reloaded to get the translated data."); - params.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("LanguageChanged", params); + description = "Emitted whenever the language of the server changed. The Plugins, Vendors and DeviceClasses have to be reloaded to get the translated data."; + params.insert("language", enumValueName(String)); + registerNotification("LanguageChanged", description, params); params.clear(); returns.clear(); - setDescription("TcpServerConfigurationChanged", "Emitted whenever the TCP server configuration changes."); - params.insert("tcpServerConfiguration", JsonTypes::serverConfigurationRef()); - setParams("TcpServerConfigurationChanged", params); + description = "Emitted whenever the TCP server configuration changes."; + params.insert("tcpServerConfiguration", objectRef("ServerConfiguration")); + registerNotification("TcpServerConfigurationChanged", description, params); params.clear(); returns.clear(); - setDescription("TcpServerConfigurationRemoved", "Emitted whenever a TCP server configuration is removed."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("TcpServerConfigurationRemoved", params); + description = "Emitted whenever a TCP server configuration is removed."; + params.insert("id", enumValueName(String)); + registerNotification("TcpServerConfigurationRemoved", description, params); params.clear(); returns.clear(); - setDescription("WebSocketServerConfigurationChanged", "Emitted whenever the web socket server configuration changes."); - params.insert("webSocketServerConfiguration", JsonTypes::serverConfigurationRef()); - setParams("WebSocketServerConfigurationChanged", params); + description = "Emitted whenever the web socket server configuration changes."; + params.insert("webSocketServerConfiguration", objectRef("ServerConfiguration")); + registerNotification("WebSocketServerConfigurationChanged", description, params); params.clear(); returns.clear(); - setDescription("WebSocketServerConfigurationRemoved", "Emitted whenever a WebSocket server configuration is removed."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("WebSocketServerConfigurationRemoved", params); + description = "Emitted whenever a WebSocket server configuration is removed."; + params.insert("id", enumValueName(String)); + registerNotification("WebSocketServerConfigurationRemoved", description, params); params.clear(); returns.clear(); - setDescription("MqttServerConfigurationChanged", "Emitted whenever the MQTT broker configuration is changed."); - params.insert("mqttServerConfiguration", JsonTypes::serverConfigurationRef()); - setParams("MqttServerConfigurationChanged", params); + description = "Emitted whenever the MQTT broker configuration is changed."; + params.insert("mqttServerConfiguration", objectRef("ServerConfiguration")); + registerNotification("MqttServerConfigurationChanged", description, params); params.clear(); returns.clear(); - setDescription("MqttServerConfigurationRemoved", "Emitted whenever a MQTT server configuration is removed."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("MqttServerConfigurationRemoved", params); + description = "Emitted whenever a MQTT server configuration is removed."; + params.insert("id", enumValueName(String)); + registerNotification("MqttServerConfigurationRemoved", description, params); params.clear(); returns.clear(); - setDescription("WebServerConfigurationChanged", "Emitted whenever the web server configuration changes."); - params.insert("webServerConfiguration", JsonTypes::webServerConfigurationRef()); - setParams("WebServerConfigurationChanged", params); + description = "Emitted whenever the web server configuration changes."; + params.insert("webServerConfiguration", objectRef("WebServerConfiguration")); + registerNotification("WebServerConfigurationChanged", description, params); params.clear(); returns.clear(); - setDescription("WebServerConfigurationRemoved", "Emitted whenever a Web server configuration is removed."); - params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); - setParams("WebServerConfigurationRemoved", params); + description = "Emitted whenever a Web server configuration is removed."; + params.insert("id", enumValueName(String)); + registerNotification("WebServerConfigurationRemoved", description, params); params.clear(); returns.clear(); - setDescription("CloudConfigurationChanged", "Emitted whenever the cloud configuration is changed."); + description = "Emitted whenever the cloud configuration is changed."; params.insert("cloudConfiguration", cloudConfiguration); - setParams("CloudConfigurationChanged", params); + registerNotification("CloudConfigurationChanged", description, params); params.clear(); returns.clear(); - setDescription("MqttPolicyChanged", "Emitted whenever a MQTT broker policy is changed."); - params.insert("policy", JsonTypes::mqttPolicyRef()); - setParams("MqttPolicyChanged", params); + description = "Emitted whenever a MQTT broker policy is changed."; + params.insert("policy", objectRef("MqttPolicy")); + registerNotification("MqttPolicyChanged", description, params); params.clear(); returns.clear(); - setDescription("MqttPolicyRemoved", "Emitted whenever a MQTT broker policy is removed."); - params.insert("clientId", JsonTypes::basicTypeToString(QVariant::String)); - setParams("MqttPolicyRemoved", params); + description = "Emitted whenever a MQTT broker policy is removed."; + params.insert("clientId", enumValueName(String)); + registerNotification("MqttPolicyRemoved", description, params); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::serverNameChanged, this, &ConfigurationHandler::onBasicConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::timeZoneChanged, this, &ConfigurationHandler::onBasicConfigurationChanged); @@ -319,23 +324,23 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap ¶ms) co { Q_UNUSED(params) QVariantMap returns; - returns.insert("basicConfiguration", JsonTypes::packBasicConfiguration()); + returns.insert("basicConfiguration", packBasicConfiguration()); QVariantList tcpServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) { - tcpServerConfigs.append(JsonTypes::packServerConfiguration(config)); + tcpServerConfigs.append(packServerConfiguration(config)); } returns.insert("tcpServerConfigurations", tcpServerConfigs); QVariantList webServerConfigs; foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - webServerConfigs.append(JsonTypes::packWebServerConfiguration(config)); + webServerConfigs.append(packWebServerConfiguration(config)); } returns.insert("webServerConfigurations", webServerConfigs); QVariantList webSocketServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) { - webSocketServerConfigs.append(JsonTypes::packServerConfiguration(config)); + webSocketServerConfigs.append(packServerConfiguration(config)); } returns.insert("webSocketServerConfigurations", webSocketServerConfigs); @@ -402,7 +407,7 @@ JsonReply *ConfigurationHandler::SetLanguage(const QVariantMap ¶ms) const JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap ¶ms) const { - ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap()); + ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); } @@ -432,7 +437,7 @@ JsonReply *ConfigurationHandler::DeleteTcpServerConfiguration(const QVariantMap JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap ¶ms) const { - WebServerConfiguration config = JsonTypes::unpackWebServerConfiguration(params.value("configuration").toMap()); + WebServerConfiguration config = unpackWebServerConfiguration(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); @@ -463,7 +468,7 @@ JsonReply *ConfigurationHandler::DeleteWebServerConfiguration(const QVariantMap JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantMap ¶ms) const { - ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap()); + ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); } @@ -498,7 +503,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap & QVariantMap ret; QVariantList mqttServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->mqttServerConfigurations()) { - mqttServerConfigs << JsonTypes::packServerConfiguration(config); + mqttServerConfigs << packServerConfiguration(config); } ret.insert("mqttServerConfigurations", mqttServerConfigs); return createReply(ret); @@ -506,7 +511,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap & JsonReply *ConfigurationHandler::SetMqttServerConfiguration(const QVariantMap ¶ms) const { - ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap()); + ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); } @@ -540,7 +545,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap ¶ms) cons Q_UNUSED(params) QVariantList mqttPolicies; foreach (const MqttPolicy &policy, NymeaCore::instance()->configuration()->mqttPolicies()) { - mqttPolicies << JsonTypes::packMqttPolicy(policy); + mqttPolicies << packMqttPolicy(policy); } QVariantMap ret; ret.insert("mqttPolicies", mqttPolicies); @@ -549,7 +554,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap ¶ms) cons JsonReply *ConfigurationHandler::SetMqttPolicy(const QVariantMap ¶ms) const { - MqttPolicy policy = JsonTypes::unpackMqttPolicy(params.value("policy").toMap()); + MqttPolicy policy = unpackMqttPolicy(params.value("policy").toMap()); NymeaCore::instance()->configuration()->updateMqttPolicy(policy); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError)); } @@ -579,7 +584,7 @@ void ConfigurationHandler::onBasicConfigurationChanged() { qCDebug(dcJsonRpc()) << "Notification: Basic configuration changed"; QVariantMap params; - params.insert("basicConfiguration", JsonTypes::packBasicConfiguration()); + params.insert("basicConfiguration", packBasicConfiguration()); emit BasicConfigurationChanged(params); } @@ -587,7 +592,7 @@ void ConfigurationHandler::onTcpServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: TCP server configuration changed"; QVariantMap params; - params.insert("tcpServerConfiguration", JsonTypes::packServerConfiguration(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id))); + params.insert("tcpServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id))); emit TcpServerConfigurationChanged(params); } @@ -603,7 +608,7 @@ void ConfigurationHandler::onWebServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: web server configuration changed"; QVariantMap params; - params.insert("webServerConfiguration", JsonTypes::packWebServerConfiguration(NymeaCore::instance()->configuration()->webServerConfigurations().value(id))); + params.insert("webServerConfiguration", packWebServerConfiguration(NymeaCore::instance()->configuration()->webServerConfigurations().value(id))); emit WebServerConfigurationChanged(params); } @@ -619,7 +624,7 @@ void ConfigurationHandler::onWebSocketServerConfigurationChanged(const QString & { qCDebug(dcJsonRpc()) << "Notification: web socket server configuration changed"; QVariantMap params; - params.insert("webSocketServerConfiguration", JsonTypes::packServerConfiguration(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id))); + params.insert("webSocketServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id))); emit WebSocketServerConfigurationChanged(params); } @@ -635,7 +640,7 @@ void ConfigurationHandler::onMqttServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed"; QVariantMap params; - params.insert("mqttServerConfiguration", JsonTypes::packServerConfiguration(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id))); + params.insert("mqttServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id))); emit MqttServerConfigurationChanged(params); } @@ -651,7 +656,7 @@ void ConfigurationHandler::onMqttPolicyChanged(const QString &clientId) { qCDebug(dcJsonRpc()) << "Notification: MQTT policy changed"; QVariantMap params; - params.insert("policy", JsonTypes::packMqttPolicy(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId))); + params.insert("policy", packMqttPolicy(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId))); emit MqttPolicyChanged(params); } @@ -663,6 +668,89 @@ void ConfigurationHandler::onMqttPolicyRemoved(const QString &clientId) emit MqttPolicyRemoved(params); } +QVariantMap ConfigurationHandler::packBasicConfiguration() +{ + QVariantMap basicConfiguration; + basicConfiguration.insert("serverName", NymeaCore::instance()->configuration()->serverName()); + basicConfiguration.insert("serverUuid", NymeaCore::instance()->configuration()->serverUuid().toString()); + basicConfiguration.insert("serverTime", NymeaCore::instance()->timeManager()->currentDateTime().toTime_t()); + basicConfiguration.insert("timeZone", QString::fromUtf8(NymeaCore::instance()->timeManager()->timeZone())); + basicConfiguration.insert("language", NymeaCore::instance()->configuration()->locale().name()); + basicConfiguration.insert("debugServerEnabled", NymeaCore::instance()->configuration()->debugServerEnabled()); + return basicConfiguration; +} + +QVariantMap ConfigurationHandler::packServerConfiguration(const ServerConfiguration &config) +{ + QVariantMap serverConfiguration; + serverConfiguration.insert("id", config.id); + serverConfiguration.insert("address", config.address.toString()); + serverConfiguration.insert("port", config.port); + serverConfiguration.insert("sslEnabled", config.sslEnabled); + serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled); + return serverConfiguration; +} + +QVariantMap ConfigurationHandler::packWebServerConfiguration(const WebServerConfiguration &config) +{ + QVariantMap webServerConfiguration = packServerConfiguration(config); + webServerConfiguration.insert("publicFolder", config.publicFolder); + return webServerConfiguration; +} + +QVariantMap ConfigurationHandler::packMqttPolicy(const MqttPolicy &policy) +{ + QVariantMap policyMap; + policyMap.insert("clientId", policy.clientId); + policyMap.insert("username", policy.username); + policyMap.insert("password", policy.password); + policyMap.insert("allowedPublishTopicFilters", policy.allowedPublishTopicFilters); + policyMap.insert("allowedSubscribeTopicFilters", policy.allowedSubscribeTopicFilters); + return policyMap; +} + +MqttPolicy ConfigurationHandler::unpackMqttPolicy(const QVariantMap &mqttPolicyMap) +{ + MqttPolicy policy; + policy.clientId = mqttPolicyMap.value("clientId").toString(); + policy.username = mqttPolicyMap.value("username").toString(); + policy.password = mqttPolicyMap.value("password").toString(); + policy.allowedPublishTopicFilters = mqttPolicyMap.value("allowedPublishTopicFilters").toStringList(); + policy.allowedSubscribeTopicFilters = mqttPolicyMap.value("allowedSubscribeTopicFilters").toStringList(); + return policy; +} + +ServerConfiguration ConfigurationHandler::unpackServerConfiguration(const QVariantMap &serverConfigurationMap) +{ + ServerConfiguration serverConfiguration; + serverConfiguration.id = serverConfigurationMap.value("id").toString(); + serverConfiguration.address = QHostAddress(serverConfigurationMap.value("address").toString()); + serverConfiguration.port = serverConfigurationMap.value("port").toUInt(); + serverConfiguration.sslEnabled = serverConfigurationMap.value("sslEnabled", true).toBool(); + serverConfiguration.authenticationEnabled = serverConfigurationMap.value("authenticationEnabled", true).toBool(); + return serverConfiguration; +} + +WebServerConfiguration ConfigurationHandler::unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap) +{ + ServerConfiguration tmp = unpackServerConfiguration(webServerConfigurationMap); + WebServerConfiguration webServerConfiguration; + webServerConfiguration.id = tmp.id; + webServerConfiguration.address = tmp.address; + webServerConfiguration.port = tmp.port; + webServerConfiguration.sslEnabled = tmp.sslEnabled; + webServerConfiguration.authenticationEnabled = tmp.authenticationEnabled; + webServerConfiguration.publicFolder = webServerConfigurationMap.value("publicFolder").toString(); + return webServerConfiguration; +} + +QVariantMap ConfigurationHandler::statusToReply(NymeaConfiguration::ConfigurationError status) const +{ + QVariantMap returns; + returns.insert("configurationError", enumValueName(status)); + return returns; +} + void ConfigurationHandler::onCloudConfigurationChanged(bool enabled) { qCDebug(dcJsonRpc()) << "Notification: cloud configuration changed"; diff --git a/libnymea-core/jsonrpc/configurationhandler.h b/libnymea-core/jsonrpc/configurationhandler.h index e5ef0e07..df15a937 100644 --- a/libnymea-core/jsonrpc/configurationhandler.h +++ b/libnymea-core/jsonrpc/configurationhandler.h @@ -23,7 +23,8 @@ #include -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" +#include "nymeaconfiguration.h" namespace nymeaserver { @@ -88,6 +89,19 @@ private slots: void onMqttServerConfigurationRemoved(const QString &id); void onMqttPolicyChanged(const QString &clientId); void onMqttPolicyRemoved(const QString &clientId); + +private: + static QVariantMap packBasicConfiguration(); + static QVariantMap packServerConfiguration(const ServerConfiguration &config); + static QVariantMap packWebServerConfiguration(const WebServerConfiguration &config); + static QVariantMap packMqttPolicy(const MqttPolicy &policy); + + static ServerConfiguration unpackServerConfiguration(const QVariantMap &serverConfigurationMap); + static WebServerConfiguration unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap); + static MqttPolicy unpackMqttPolicy(const QVariantMap &mqttPolicyMap); + + QVariantMap statusToReply(NymeaConfiguration::ConfigurationError status) const; + }; } diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index ea06a221..20383cd7 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -60,6 +60,8 @@ #include "devices/deviceplugin.h" #include "loggingcategories.h" #include "types/deviceclass.h" +#include "types/browseritem.h" +#include "types/mediabrowseritem.h" #include "devices/translator.h" #include "devices/devicediscoveryinfo.h" #include "devices/devicepairinginfo.h" @@ -75,74 +77,183 @@ namespace nymeaserver { DeviceHandler::DeviceHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap returns; - QVariantMap params; + // Enums + registerEnum(); + registerEnum(); + registerEnum(); + registerEnum(); + registerEnum(); + registerEnum(); + registerEnum(); + registerEnum(); + + // Objects + QVariantMap paramType; + paramType.insert("id", enumValueName(Uuid)); + paramType.insert("name", enumValueName(String)); + paramType.insert("displayName", enumValueName(String)); + paramType.insert("type", enumRef()); + paramType.insert("index", enumValueName(Int)); + paramType.insert("o:defaultValue", enumValueName(Variant)); + paramType.insert("o:minValue", enumValueName(Variant)); + paramType.insert("o:maxValue", enumValueName(Variant)); + paramType.insert("o:allowedValues", QVariantList() << enumValueName(Variant)); + paramType.insert("o:inputType", enumRef()); + paramType.insert("o:unit", enumRef()); + paramType.insert("o:readOnly", enumValueName(Bool)); + registerObject("ParamType", paramType); + + QVariantMap param; + param.insert("paramTypeId", enumValueName(Uuid)); + param.insert("value", enumValueName(Variant)); + registerObject("Param", param); + + QVariantMap plugin; + plugin.insert("id", enumValueName(Uuid)); + plugin.insert("name", enumValueName(String)); + plugin.insert("displayName", enumValueName(String)); + plugin.insert("paramTypes", QVariantList() << objectRef("ParamType")); + registerObject("Plugin", plugin); + + QVariantMap vendor; + vendor.insert("id", enumValueName(Uuid)); + vendor.insert("name", enumValueName(String)); + vendor.insert("displayName", enumValueName(String)); + registerObject("Vendor", vendor); + + QVariantMap eventType; + eventType.insert("id", enumValueName(Uuid)); + eventType.insert("name", enumValueName(String)); + eventType.insert("displayName", enumValueName(String)); + eventType.insert("index", enumValueName(Int)); + eventType.insert("paramTypes", QVariantList() << objectRef("ParamType")); + registerObject("EventType", eventType); + + QVariantMap stateType; + stateType.insert("id", enumValueName(Uuid)); + stateType.insert("name", enumValueName(String)); + stateType.insert("displayName", enumValueName(String)); + stateType.insert("type", enumRef()); + stateType.insert("index", enumValueName(Int)); + stateType.insert("defaultValue", enumValueName(Variant)); + stateType.insert("o:unit", enumRef()); + stateType.insert("o:minValue", enumValueName(Variant)); + stateType.insert("o:maxValue", enumValueName(Variant)); + stateType.insert("o:possibleValues", QVariantList() << enumValueName(Variant)); + registerObject("StateType", stateType); + + QVariantMap actionType; + actionType.insert("id", enumValueName(Uuid)); + actionType.insert("name", enumValueName(String)); + actionType.insert("displayName", enumValueName(String)); + actionType.insert("index", enumValueName(Int)); + actionType.insert("paramTypes", QVariantList() << objectRef("ParamType")); + registerObject("ActionType", actionType); + + QVariantMap deviceClass; + deviceClass.insert("id", enumValueName(Uuid)); + deviceClass.insert("vendorId", enumValueName(Uuid)); + deviceClass.insert("pluginId", enumValueName(Uuid)); + deviceClass.insert("name", enumValueName(String)); + deviceClass.insert("displayName", enumValueName(String)); + deviceClass.insert("interfaces", QVariantList() << enumValueName(String)); + deviceClass.insert("browsable", enumValueName(Bool)); + deviceClass.insert("setupMethod", enumRef()); + deviceClass.insert("createMethods", QVariantList() << enumRef()); + deviceClass.insert("stateTypes", QVariantList() << objectRef("StateType")); + deviceClass.insert("eventTypes", QVariantList() << objectRef("EventType")); + deviceClass.insert("actionTypes", QVariantList() << objectRef("ActionType")); + deviceClass.insert("browserItemActionTypes", QVariantList() << objectRef("ActionType")); + deviceClass.insert("paramTypes", QVariantList() << objectRef("ParamType")); + deviceClass.insert("settingsTypes", QVariantList() << objectRef("ParamType")); + deviceClass.insert("discoveryParamTypes", QVariantList() << objectRef("ParamType")); + registerObject("DeviceClass", deviceClass); + + QVariantMap deviceDescriptor; + deviceDescriptor.insert("id", enumValueName(Uuid)); + deviceDescriptor.insert("deviceId", enumValueName(Uuid)); + deviceDescriptor.insert("title", enumValueName(String)); + deviceDescriptor.insert("description", enumValueName(String)); + deviceDescriptor.insert("deviceParams", QVariantList() << objectRef("Param")); + registerObject("DeviceDescriptor", deviceDescriptor); + + QVariantMap device; + device.insert("id", enumValueName(Uuid)); + device.insert("deviceClassId", enumValueName(Uuid)); + device.insert("name", enumValueName(String)); + device.insert("params", QVariantList() << objectRef("Param")); + device.insert("settings", QVariantList() << objectRef("Param")); + QVariantMap stateValues; + stateValues.insert("stateTypeId", enumValueName(Uuid)); + stateValues.insert("value", enumValueName(Variant)); + device.insert("states", QVariantList() << stateValues); + device.insert("setupComplete", enumValueName(Bool)); + device.insert("o:parentId", enumValueName(Uuid)); + registerObject("Device", device); + + QVariantMap browserItem; + browserItem.insert("id", enumValueName(String)); + browserItem.insert("displayName", enumValueName(String)); + browserItem.insert("description", enumValueName(String)); + browserItem.insert("icon", enumRef()); + browserItem.insert("thumbnail", enumValueName(String)); + browserItem.insert("executable", enumValueName(Bool)); + browserItem.insert("browsable", enumValueName(Bool)); + browserItem.insert("disabled", enumValueName(Bool)); + browserItem.insert("actionTypeIds", QVariantList() << enumValueName(Uuid)); + browserItem.insert("o:mediaIcon", enumRef()); + registerObject("BrowserItem", browserItem); + + + // Methods + QString description; QVariantMap returns; QVariantMap params; + description = "Returns a list of supported Vendors."; + returns.insert("vendors", QVariantList() << objectRef("Vendor")); + registerMethod("GetSupportedVendors", description, params, returns); params.clear(); returns.clear(); - setDescription("GetSupportedVendors", "Returns a list of supported Vendors."); - setParams("GetSupportedVendors", params); - QVariantList vendors; - vendors.append(JsonTypes::vendorRef()); - returns.insert("vendors", vendors); - setReturns("GetSupportedVendors", returns); + description = "Returns a list of supported Device classes, optionally filtered by vendorId."; + params.insert("o:vendorId", enumValueName(Uuid)); + returns.insert("deviceClasses", QVariantList() << objectRef("DeviceClass")); + registerMethod("GetSupportedDevices", description, params, returns); params.clear(); returns.clear(); - setDescription("GetSupportedDevices", "Returns a list of supported Device classes, optionally filtered by vendorId."); - params.insert("o:vendorId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetSupportedDevices", params); - QVariantList deviceClasses; - deviceClasses.append(JsonTypes::deviceClassRef()); - returns.insert("deviceClasses", deviceClasses); - setReturns("GetSupportedDevices", returns); + description = "Returns a list of loaded plugins."; + returns.insert("plugins", QVariantList() << objectRef("Plugin")); + registerMethod("GetPlugins", description, params, returns); params.clear(); returns.clear(); - setDescription("GetPlugins", "Returns a list of loaded plugins."); - setParams("GetPlugins", params); - QVariantList plugins; - plugins.append(JsonTypes::pluginRef()); - returns.insert("plugins", plugins); - setReturns("GetPlugins", returns); + description = "Get a plugin's params."; + params.insert("pluginId", enumValueName(Uuid)); + returns.insert("deviceError", enumRef()); + returns.insert("o:configuration", QVariantList() << objectRef("Param")); + registerMethod("GetPluginConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("GetPluginConfiguration", "Get a plugin's params."); - params.insert("pluginId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetPluginConfiguration", params); - QVariantList pluginParams; - pluginParams.append(JsonTypes::paramRef()); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:configuration", pluginParams); - setReturns("GetPluginConfiguration", returns); + description = "Set a plugin's params."; + params.insert("pluginId", enumValueName(Uuid)); + params.insert("configuration", QVariantList() << objectRef("Param")); + returns.insert("deviceError", enumRef()); + registerMethod("SetPluginConfiguration", description, params, returns); params.clear(); returns.clear(); - setDescription("SetPluginConfiguration", "Set a plugin's params."); - params.insert("pluginId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("configuration", pluginParams); - setParams("SetPluginConfiguration", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - setReturns("SetPluginConfiguration", returns); - - params.clear(); returns.clear(); - setDescription("AddConfiguredDevice", "Add a configured device with a setupMethod of SetupMethodJustAdd. " + description = "Add a configured device with a setupMethod of SetupMethodJustAdd. " "For devices with a setupMethod different than SetupMethodJustAdd, use PairDevice. " "Devices with CreateMethodJustAdd require all parameters to be supplied here. " "Devices with CreateMethodDiscovery require the use of a deviceDescriptorId. For discovered " "devices params are not required and will be taken from the DeviceDescriptor, however, they " - "may be overridden by supplying deviceParams." - ); - params.insert("deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("o:deviceDescriptorId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - QVariantList deviceParams; - deviceParams.append(JsonTypes::paramRef()); - params.insert("o:deviceParams", deviceParams); - setParams("AddConfiguredDevice", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("AddConfiguredDevice", returns); + "may be overridden by supplying deviceParams."; + params.insert("deviceClassId", enumValueName(Uuid)); + params.insert("name", enumValueName(String)); + params.insert("o:deviceDescriptorId", enumValueName(Uuid)); + params.insert("o:deviceParams", QVariantList() << objectRef("Param")); + returns.insert("deviceError", enumRef()); + returns.insert("o:deviceId", enumValueName(Uuid)); + returns.insert("o:displayMessage", enumValueName(String)); + registerMethod("AddConfiguredDevice", description, params, returns); params.clear(); returns.clear(); - setDescription("PairDevice", "Pair a device. " + description = "Pair a device. " "Use this to set up or reconfigure devices for DeviceClasses with a setupMethod different than SetupMethodJustAdd. " "Depending on the CreateMethod and whether a new devices is set up or an existing one is reconfigured, different parameters " "are required:\n" @@ -158,215 +269,183 @@ DeviceHandler::DeviceHandler(QObject *parent) : "mask for a user and password login should be presented to the user. In case of SetupMethodOAuth, an OAuth URL will be returned " "which shall be opened in a web view to allow the user logging in.\n" "Once the login procedure has completed, the application shall proceed with ConfirmPairing, providing the results of the pairing " - "procedure." - ); - params.insert("o:deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:name", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("o:deviceDescriptorId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:deviceParams", deviceParams); - params.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("PairDevice", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:setupMethod", JsonTypes::setupMethodRef()); - returns.insert("o:pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("o:oAuthUrl", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("o:pin", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("PairDevice", returns); + "procedure."; + params.insert("o:deviceClassId", enumValueName(Uuid)); + params.insert("o:name", enumValueName(String)); + params.insert("o:deviceDescriptorId", enumValueName(Uuid)); + params.insert("o:deviceParams", QVariantList() << objectRef("Param")); + params.insert("o:deviceId", enumValueName(Uuid)); + returns.insert("deviceError", enumRef()); + returns.insert("o:setupMethod", enumRef()); + returns.insert("o:pairingTransactionId", enumValueName(Uuid)); + returns.insert("o:displayMessage", enumValueName(String)); + returns.insert("o:oAuthUrl", enumValueName(String)); + returns.insert("o:pin", enumValueName(String)); + registerMethod("PairDevice", description, params, returns); params.clear(); returns.clear(); - setDescription("ConfirmPairing", "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field " + description = "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field " "and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" " "field. In case of SetupMethodOAuth, the previously opened web view will eventually be redirected to http://128.0.0.1:8888 " - "and the OAuth code as query parameters to this url. Provide the entire unmodified URL in the secret field."); - params.insert("pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:username", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("o:secret", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("ConfirmPairing", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setReturns("ConfirmPairing", returns); + "and the OAuth code as query parameters to this url. Provide the entire unmodified URL in the secret field."; + params.insert("pairingTransactionId", enumValueName(Uuid)); + params.insert("o:username", enumValueName(String)); + params.insert("o:secret", enumValueName(String)); + returns.insert("deviceError", enumRef()); + returns.insert("o:displayMessage", enumValueName(String)); + returns.insert("o:deviceId", enumValueName(Uuid)); + registerMethod("ConfirmPairing", description, params, returns); params.clear(); returns.clear(); - setDescription("GetConfiguredDevices", "Returns a list of configured devices, optionally filtered by deviceId."); - params.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetConfiguredDevices", params); - QVariantList devices; - devices.append(JsonTypes::deviceRef()); - returns.insert("devices", devices); - setReturns("GetConfiguredDevices", returns); + description = "Returns a list of configured devices, optionally filtered by deviceId."; + params.insert("o:deviceId", enumValueName(Uuid)); + returns.insert("devices", QVariantList() << objectRef("Device")); + registerMethod("GetConfiguredDevices", description, params, returns); params.clear(); returns.clear(); - setDescription("GetDiscoveredDevices", "Performs a device discovery and returns the results. This function may take a while to return. " + description = "Performs a device discovery and returns the results. This function may take a while to return. " "Note that this method will include all the found devices, that is, including devices that may " "already have been added. Those devices will have deviceId set to the device id of the already " "added device. Such results may be used to reconfigure existing devices and might be filtered " - "in cases where only unknown devices are of interest."); - params.insert("deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - QVariantList discoveryParams; - discoveryParams.append(JsonTypes::paramRef()); - params.insert("o:discoveryParams", discoveryParams); - setParams("GetDiscoveredDevices", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); - QVariantList deviceDescriptors; - deviceDescriptors.append(JsonTypes::deviceDescriptorRef()); - returns.insert("o:deviceDescriptors", deviceDescriptors); - setReturns("GetDiscoveredDevices", returns); + "in cases where only unknown devices are of interest."; + params.insert("deviceClassId", enumValueName(Uuid)); + params.insert("o:discoveryParams", QVariantList() << objectRef("Param")); + returns.insert("deviceError", enumRef()); + returns.insert("o:displayMessage", enumValueName(String)); + returns.insert("o:deviceDescriptors", QVariantList() << objectRef("DeviceDescriptor")); + registerMethod("GetDiscoveredDevices", description, params, returns); params.clear(); returns.clear(); - setDescription("ReconfigureDevice", "Reconfigure a device. This comes down to removing and recreating a device with new parameters " - "but keeping its device id the same (and with that keeping rules, tags etc). For devices with " - "create method CreateMethodDiscovery, a discovery (GetDiscoveredDevices) shall be performed first " - "and this method is to be called with a deviceDescriptorId of the re-discovered device instead of " - "the deviceId directly. Device parameters will be taken from the discovery, but can be overridden " - "individually here by providing them in the deviceParams parameter. Only writable parameters can " - "be changed."); - params.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:deviceDescriptorId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - QVariantList newDeviceParams; - newDeviceParams.append(JsonTypes::paramRef()); - params.insert("o:deviceParams", newDeviceParams); - setParams("ReconfigureDevice", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("ReconfigureDevice", returns); + description = "Reconfigure a device. This comes down to removing and recreating a device with new parameters " + "but keeping its device id the same (and with that keeping rules, tags etc). For devices with " + "create method CreateMethodDiscovery, a discovery (GetDiscoveredDevices) shall be performed first " + "and this method is to be called with a deviceDescriptorId of the re-discovered device instead of " + "the deviceId directly. Device parameters will be taken from the discovery, but can be overridden " + "individually here by providing them in the deviceParams parameter. Only writable parameters can " + "be changed."; + params.insert("o:deviceId", enumValueName(Uuid)); + params.insert("o:deviceDescriptorId", enumValueName(Uuid)); + params.insert("o:deviceParams", QVariantList() << objectRef("Param")); + returns.insert("deviceError", enumRef()); + returns.insert("o:displayMessage", enumValueName(String)); + registerMethod("ReconfigureDevice", description, params, returns); params.clear(); returns.clear(); - setDescription("EditDevice", "Edit the name of a device. This method does not change the " - "configuration of the device."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("EditDevice", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - setReturns("EditDevice", returns); + description = "Edit the name of a device. This method does not change the " + "configuration of the device."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("name", enumValueName(String)); + returns.insert("deviceError", enumRef()); + registerMethod("EditDevice", description, params, returns); params.clear(); returns.clear(); - setDescription("SetDeviceSettings", "Change the settings of a device."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("settings", QVariantList() << JsonTypes::paramRef()); - setParams("SetDeviceSettings", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - setReturns("SetDeviceSettings", returns); + description = "Change the settings of a device."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("settings", QVariantList() << objectRef("Param")); + returns.insert("deviceError", enumRef()); + registerMethod("SetDeviceSettings", description, params, returns); params.clear(); returns.clear(); - setDescription("RemoveConfiguredDevice", "Remove a device from the system."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - QVariantList removePolicyList; + description = "Remove a device from the system."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("o:removePolicy", enumRef()); QVariantMap policy; - policy.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - policy.insert("policy", JsonTypes::removePolicyRef()); + policy.insert("ruleId", enumValueName(Uuid)); + policy.insert("policy", enumRef()); + QVariantList removePolicyList; removePolicyList.append(policy); - params.insert("o:removePolicy", JsonTypes::removePolicyRef()); params.insert("o:removePolicyList", removePolicyList); - setParams("RemoveConfiguredDevice", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:ruleIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setReturns("RemoveConfiguredDevice", returns); + returns.insert("deviceError", enumRef()); + returns.insert("o:ruleIds", QVariantList() << enumValueName(Uuid)); + registerMethod("RemoveConfiguredDevice", description, params, returns); params.clear(); returns.clear(); - setDescription("GetEventTypes", "Get event types for a specified deviceClassId."); - params.insert("deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetEventTypes", params); - QVariantList events; - events.append(JsonTypes::eventTypeRef()); - returns.insert("eventTypes", events); - setReturns("GetEventTypes", returns); + description = "Get event types for a specified deviceClassId."; + params.insert("deviceClassId", enumValueName(Uuid)); + returns.insert("eventTypes", QVariantList() << objectRef("EventType")); + registerMethod("GetEventTypes", description, params, returns); params.clear(); returns.clear(); - setDescription("GetActionTypes", "Get action types for a specified deviceClassId."); - params.insert("deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetActionTypes", params); - QVariantList actions; - actions.append(JsonTypes::actionTypeRef()); - returns.insert("actionTypes", actions); - setReturns("GetActionTypes", returns); + description = "Get action types for a specified deviceClassId."; + params.insert("deviceClassId", enumValueName(Uuid)); + returns.insert("actionTypes", QVariantList() << objectRef("ActionType")); + registerMethod("GetActionTypes", description, params, returns); params.clear(); returns.clear(); - setDescription("GetStateTypes", "Get state types for a specified deviceClassId."); - params.insert("deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetStateTypes", params); - QVariantList states; - states.append(JsonTypes::stateTypeRef()); - returns.insert("stateTypes", states); - setReturns("GetStateTypes", returns); + description = "Get state types for a specified deviceClassId."; + params.insert("deviceClassId", enumValueName(Uuid)); + returns.insert("stateTypes", QVariantList() << objectRef("StateType")); + registerMethod("GetStateTypes", description, params, returns); params.clear(); returns.clear(); - setDescription("GetStateValue", "Get the value of the given device and the given stateType"); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("stateTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetStateValue", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:value", JsonTypes::basicTypeToString(JsonTypes::Variant)); - setReturns("GetStateValue", returns); + description = "Get the value of the given device and the given stateType"; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("stateTypeId", enumValueName(Uuid)); + returns.insert("deviceError", enumRef()); + returns.insert("o:value", enumValueName(Variant)); + registerMethod("GetStateValue", description, params, returns); params.clear(); returns.clear(); - setDescription("GetStateValues", "Get all the state values of the given device."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetStateValues", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - states.clear(); + description = "Get all the state values of the given device."; + params.insert("deviceId", enumValueName(Uuid)); + returns.insert("deviceError", enumRef()); QVariantMap state; - state.insert("stateTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - state.insert("value", JsonTypes::basicTypeToString(JsonTypes::Variant)); - states.append(state); - returns.insert("o:values", states); - setReturns("GetStateValues", returns); + state.insert("stateTypeId", enumValueName(Uuid)); + state.insert("value", enumValueName(Variant)); + returns.insert("o:values", QVariantList() << state); + registerMethod("GetStateValues", description, params, returns); params.clear(); returns.clear(); - setDescription("BrowseDevice", "Browse a device. If a DeviceClass indicates a device is browsable, this method will return the BrowserItems. If no parameter besides the deviceId is used, the root node of this device will be returned. Any returned item which is browsable can be passed as node. Results will be children of the given node."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:itemId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("BrowseDevice", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("items", QVariantList() << JsonTypes::browserItemRef()); - setReturns("BrowseDevice", returns); + description = "Browse a device. If a DeviceClass indicates a device is browsable, this method will return the BrowserItems. If no parameter besides the deviceId is used, the root node of this device will be returned. Any returned item which is browsable can be passed as node. Results will be children of the given node."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("o:itemId", enumValueName(String)); + returns.insert("deviceError", enumRef()); + returns.insert("items", QVariantList() << objectRef("BrowserItem")); + registerMethod("BrowseDevice", description, params, returns); params.clear(); returns.clear(); - setDescription("GetBrowserItem", "Get a single item from the browser. This won't give any more info on an item than a regular browseDevice call, but it allows to fetch details of an item if only the ID is known."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:itemId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("GetBrowserItem", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:item", JsonTypes::browserItemRef()); - setReturns("GetBrowserItem", returns); + description = "Get a single item from the browser. This won't give any more info on an item than a regular browseDevice call, but it allows to fetch details of an item if only the ID is known."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("o:itemId", enumValueName(String)); + returns.insert("deviceError", enumRef()); + returns.insert("o:item", objectRef("BrowserItem")); + registerMethod("GetBrowserItem", description, params, returns); // Notifications params.clear(); returns.clear(); - setDescription("StateChanged", "Emitted whenever a State of a device changes."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("stateTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("value", JsonTypes::basicTypeToString(JsonTypes::Variant)); - setParams("StateChanged", params); + description = "Emitted whenever a State of a device changes."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("stateTypeId", enumValueName(Uuid)); + params.insert("value", enumValueName(Variant)); + registerNotification("StateChanged", description, params); params.clear(); returns.clear(); - setDescription("DeviceRemoved", "Emitted whenever a Device was removed."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("DeviceRemoved", params); + description = "Emitted whenever a Device was removed."; + params.insert("deviceId", enumValueName(Uuid)); + registerNotification("DeviceRemoved", description, params); params.clear(); returns.clear(); - setDescription("DeviceAdded", "Emitted whenever a Device was added."); - params.insert("device", JsonTypes::deviceRef()); - setParams("DeviceAdded", params); + description = "Emitted whenever a Device was added."; + params.insert("device", objectRef("Device")); + registerNotification("DeviceAdded", description, params); params.clear(); returns.clear(); - setDescription("DeviceChanged", "Emitted whenever the params or name of a Device are changed (by EditDevice or ReconfigureDevice)."); - params.insert("device", JsonTypes::deviceRef()); - setParams("DeviceChanged", params); + description = "Emitted whenever the params or name of a Device are changed (by EditDevice or ReconfigureDevice)."; + params.insert("device", objectRef("Device")); + registerNotification("DeviceChanged", description, params); params.clear(); returns.clear(); - setDescription("DeviceSettingChanged", "Emitted whenever the setting of a Device is changed."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("paramTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("value", JsonTypes::basicTypeToString(JsonTypes::Variant)); - setParams("DeviceSettingChanged", params); + description = "Emitted whenever the setting of a Device is changed."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("paramTypeId", enumValueName(Uuid)); + params.insert("value", enumValueName(Variant)); + registerNotification("DeviceSettingChanged", description, params); params.clear(); returns.clear(); - setDescription("PluginConfigurationChanged", "Emitted whenever a plugin's configuration is changed."); - params.insert("pluginId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("configuration", QVariantList() << JsonTypes::paramRef()); - setParams("PluginConfigurationChanged", params); + description = "Emitted whenever a plugin's configuration is changed."; + params.insert("pluginId", enumValueName(Uuid)); + params.insert("configuration", QVariantList() << objectRef("Param")); + registerNotification("PluginConfigurationChanged", description, params); connect(NymeaCore::instance(), &NymeaCore::pluginConfigChanged, this, &DeviceHandler::pluginConfigChanged); connect(NymeaCore::instance(), &NymeaCore::deviceStateChanged, this, &DeviceHandler::deviceStateChanged); @@ -384,17 +463,39 @@ QString DeviceHandler::name() const JsonReply* DeviceHandler::GetSupportedVendors(const QVariantMap ¶ms) const { - Q_UNUSED(params) + QLocale locale = params.value("locale").toLocale(); + + QVariantList vendors; + foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) { + + DevicePlugin *plugin = nullptr; + foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) { + if (p->supportedVendors().contains(vendor)) { + plugin = p; + } + } + QVariantMap variantMap; + variantMap.insert("id", vendor.id().toString()); + variantMap.insert("name", vendor.name()); + variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale)); + vendors.append(variantMap); + } QVariantMap returns; - returns.insert("vendors", JsonTypes::packSupportedVendors(params.value("locale").toLocale())); + returns.insert("vendors", vendors); return createReply(returns); } JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); + VendorId vendorId = VendorId(params.value("vendorId").toString()); QVariantMap returns; - returns.insert("deviceClasses", JsonTypes::packSupportedDevices(VendorId(params.value("vendorId").toString()), params.value("locale").toLocale())); + QVariantList deviceClasses; + foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) + deviceClasses.append(packDeviceClass(deviceClass, locale)); + + returns.insert("deviceClasses", deviceClasses); return createReply(returns); } @@ -406,16 +507,20 @@ JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap ¶ms) const DeviceClassId deviceClassId = DeviceClassId(params.value("deviceClassId").toString()); - ParamList discoveryParams = JsonTypes::unpackParams(params.value("discoveryParams").toList()); + ParamList discoveryParams = unpackParams(params.value("discoveryParams").toList()); JsonReply *reply = createAsyncReply("GetDiscoveredDevices"); DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(deviceClassId, discoveryParams); connect(info, &DeviceDiscoveryInfo::finished, reply, [reply, info, locale](){ QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status())); + returns.insert("deviceError", enumValueName(info->status())); if (info->status() == Device::DeviceErrorNoError) { - returns.insert("deviceDescriptors", JsonTypes::packDeviceDescriptors(info->deviceDescriptors())); + QVariantList deviceDescriptorList; + foreach (const DeviceDescriptor &deviceDescriptor, info->deviceDescriptors()) { + deviceDescriptorList.append(packDeviceDescriptor(deviceDescriptor)); + } + returns.insert("deviceDescriptors", deviceDescriptorList); } if (!info->displayMessage().isEmpty()) { @@ -431,10 +536,15 @@ JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap ¶ms) const JsonReply* DeviceHandler::GetPlugins(const QVariantMap ¶ms) const { - Q_UNUSED(params) + QLocale locale = params.value("locale").toLocale(); + + QVariantList plugins; + foreach (DevicePlugin* plugin, NymeaCore::instance()->deviceManager()->plugins()) { + plugins.append(packPlugin(plugin, locale)); + } QVariantMap returns; - returns.insert("plugins", JsonTypes::packPlugins(params.value("locale").toLocale())); + returns.insert("plugins", plugins); return createReply(returns); } @@ -444,16 +554,16 @@ JsonReply *DeviceHandler::GetPluginConfiguration(const QVariantMap ¶ms) cons DevicePlugin *plugin = NymeaCore::instance()->deviceManager()->plugins().findById(PluginId(params.value("pluginId").toString())); if (!plugin) { - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorPluginNotFound)); + returns.insert("deviceError", enumValueName(Device::DeviceErrorPluginNotFound)); return createReply(returns); } QVariantList paramVariantList; foreach (const Param ¶m, plugin->configuration()) { - paramVariantList.append(JsonTypes::packParam(param)); + paramVariantList.append(packParam(param)); } returns.insert("configuration", paramVariantList); - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorNoError)); + returns.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); return createReply(returns); } @@ -461,9 +571,9 @@ JsonReply* DeviceHandler::SetPluginConfiguration(const QVariantMap ¶ms) { QVariantMap returns; PluginId pluginId = PluginId(params.value("pluginId").toString()); - ParamList pluginParams = JsonTypes::unpackParams(params.value("configuration").toList()); + ParamList pluginParams = unpackParams(params.value("configuration").toList()); Device::DeviceError result = NymeaCore::instance()->deviceManager()->setPluginConfig(pluginId, pluginParams); - returns.insert("deviceError", JsonTypes::deviceErrorToString(result)); + returns.insert("deviceError",enumValueName(result)); return createReply(returns); } @@ -471,7 +581,7 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms) { DeviceClassId deviceClassId(params.value("deviceClassId").toString()); QString deviceName = params.value("name").toString(); - ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); + ParamList deviceParams = unpackParams(params.value("deviceParams").toList()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); QLocale locale = params.value("locale").toLocale(); @@ -485,7 +595,7 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms) } connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){ QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status())); + returns.insert("deviceError", enumValueName(info->status())); if (!info->displayMessage().isEmpty()) { returns.insert("displayMessage", info->translatedDisplayMessage(locale)); @@ -504,7 +614,7 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms) JsonReply *DeviceHandler::PairDevice(const QVariantMap ¶ms) { QString deviceName = params.value("name").toString(); - ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); + ParamList deviceParams = unpackParams(params.value("deviceParams").toList()); QLocale locale = params.value("locale").toLocale(); DevicePairingInfo *info; @@ -523,12 +633,12 @@ JsonReply *DeviceHandler::PairDevice(const QVariantMap ¶ms) connect(info, &DevicePairingInfo::finished, jsonReply, [jsonReply, info, locale](){ QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status())); + returns.insert("deviceError", enumValueName(info->status())); returns.insert("pairingTransactionId", info->transactionId().toString()); if (info->status() == Device::DeviceErrorNoError) { DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(info->deviceClassId()); - returns.insert("setupMethod", JsonTypes::setupMethodToString(deviceClass.setupMethod())); + returns.insert("setupMethod", enumValueName(deviceClass.setupMethod())); } if (!info->displayMessage().isEmpty()) { @@ -559,7 +669,7 @@ JsonReply *DeviceHandler::ConfirmPairing(const QVariantMap ¶ms) connect(info, &DevicePairingInfo::finished, jsonReply, [info, jsonReply, locale](){ QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status())); + returns.insert("deviceError", enumValueName(info->status())); if (!info->displayMessage().isEmpty()) { returns.insert("displayMessage", info->translatedDisplayMessage(locale)); } @@ -580,14 +690,14 @@ JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const if (params.contains("deviceId")) { Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(DeviceId(params.value("deviceId").toString())); if (!device) { - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorDeviceNotFound)); + returns.insert("deviceError", enumValueName(Device::DeviceErrorDeviceNotFound)); return createReply(returns); } else { - configuredDeviceList.append(JsonTypes::packDevice(device)); + configuredDeviceList.append(packDevice(device)); } } else { foreach (Device *device, NymeaCore::instance()->deviceManager()->configuredDevices()) { - configuredDeviceList.append(JsonTypes::packDevice(device)); + configuredDeviceList.append(packDevice(device)); } } returns.insert("devices", configuredDeviceList); @@ -597,7 +707,7 @@ JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const JsonReply *DeviceHandler::ReconfigureDevice(const QVariantMap ¶ms) { DeviceId deviceId = DeviceId(params.value("deviceId").toString()); - ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); + ParamList deviceParams = unpackParams(params.value("deviceParams").toList()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); QLocale locale = params.value("locale").toLocale(); @@ -611,14 +721,14 @@ JsonReply *DeviceHandler::ReconfigureDevice(const QVariantMap ¶ms) } else { qCWarning(dcJsonRpc()) << "Either deviceId or deviceDescriptorId are required"; QVariantMap ret; - ret.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorMissingParameter)); + ret.insert("deviceError", enumValueName(Device::DeviceErrorMissingParameter)); return createReply(ret); } connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){ QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status())); + returns.insert("deviceError", enumValueName(info->status())); returns.insert("displayMessage", info->translatedDisplayMessage(locale)); jsonReply->setData(returns); jsonReply->finished(); @@ -637,9 +747,7 @@ JsonReply *DeviceHandler::EditDevice(const QVariantMap ¶ms) Device::DeviceError status = NymeaCore::instance()->deviceManager()->editDevice(deviceId, name); - QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); - return createReply(returns); + return createReply(statusToReply(status)); } JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms) @@ -651,7 +759,7 @@ JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms) if (params.contains("removePolicy")) { RuleEngine::RemovePolicy removePolicy = params.value("removePolicy").toString() == "RemovePolicyCascade" ? RuleEngine::RemovePolicyCascade : RuleEngine::RemovePolicyUpdate; Device::DeviceError status = NymeaCore::instance()->removeConfiguredDevice(deviceId, removePolicy); - returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); + returns.insert("deviceError", enumValueName(status)); return createReply(returns); } @@ -663,7 +771,7 @@ JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms) } QPair > status = NymeaCore::instance()->removeConfiguredDevice(deviceId, removePolicyList); - returns.insert("deviceError", JsonTypes::deviceErrorToString(status.first)); + returns.insert("deviceError", enumValueName(status.first)); if (!status.second.isEmpty()) { QVariantList ruleIdList; @@ -678,12 +786,10 @@ JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms) JsonReply *DeviceHandler::SetDeviceSettings(const QVariantMap ¶ms) { - QVariantMap returns; DeviceId deviceId = DeviceId(params.value("deviceId").toString()); - ParamList settings = JsonTypes::unpackParams(params.value("settings").toList()); + ParamList settings = unpackParams(params.value("settings").toList()); Device::DeviceError status = NymeaCore::instance()->deviceManager()->setDeviceSettings(deviceId, settings); - returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); - return createReply(returns); + return createReply(statusToReply(status)); } JsonReply* DeviceHandler::GetEventTypes(const QVariantMap ¶ms) const @@ -693,7 +799,7 @@ JsonReply* DeviceHandler::GetEventTypes(const QVariantMap ¶ms) const QVariantList eventList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); foreach (const EventType &eventType, deviceClass.eventTypes()) { - eventList.append(JsonTypes::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); + eventList.append(packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); } returns.insert("eventTypes", eventList); return createReply(returns); @@ -706,7 +812,7 @@ JsonReply* DeviceHandler::GetActionTypes(const QVariantMap ¶ms) const QVariantList actionList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); foreach (const ActionType &actionType, deviceClass.actionTypes()) { - actionList.append(JsonTypes::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); + actionList.append(packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); } returns.insert("actionTypes", actionList); return createReply(returns); @@ -719,7 +825,7 @@ JsonReply* DeviceHandler::GetStateTypes(const QVariantMap ¶ms) const QVariantList stateList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); foreach (const StateType &stateType, deviceClass.stateTypes()) { - stateList.append(JsonTypes::packStateType(stateType, deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())); + stateList.append(packStateType(stateType, deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())); } returns.insert("stateTypes", stateList); return createReply(returns); @@ -727,36 +833,29 @@ JsonReply* DeviceHandler::GetStateTypes(const QVariantMap ¶ms) const JsonReply* DeviceHandler::GetStateValue(const QVariantMap ¶ms) const { - QVariantMap returns; - Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(DeviceId(params.value("deviceId").toString())); if (!device) { - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorDeviceNotFound)); - return createReply(returns); + return createReply(statusToReply(Device::DeviceErrorDeviceNotFound)); } StateTypeId stateTypeId = StateTypeId(params.value("stateTypeId").toString()); if (!device->hasState(stateTypeId)) { - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorStateTypeNotFound)); - return createReply(returns); + return createReply(statusToReply(Device::DeviceErrorStateTypeNotFound)); } - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorNoError)); + QVariantMap returns = statusToReply(Device::DeviceErrorNoError); returns.insert("value", device->state(stateTypeId).value()); return createReply(returns); } JsonReply *DeviceHandler::GetStateValues(const QVariantMap ¶ms) const { - QVariantMap returns; - Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(DeviceId(params.value("deviceId").toString())); if (!device) { - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorDeviceNotFound)); - return createReply(returns); + return createReply(statusToReply(Device::DeviceErrorDeviceNotFound)); } - returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorNoError)); - returns.insert("values", JsonTypes::packDeviceStates(device)); + QVariantMap returns = statusToReply(Device::DeviceErrorNoError); + returns.insert("values", packDeviceStates(device)); return createReply(returns); } @@ -768,11 +867,14 @@ JsonReply *DeviceHandler::BrowseDevice(const QVariantMap ¶ms) const JsonReply *jsonReply = createAsyncReply("BrowseDevice"); BrowseResult *result = NymeaCore::instance()->deviceManager()->browseDevice(deviceId, itemId, params.value("locale").toLocale()); - connect(result, &BrowseResult::finished, jsonReply, [jsonReply, result](){ + connect(result, &BrowseResult::finished, jsonReply, [this, jsonReply, result](){ - QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(result->status())); - returns.insert("items", JsonTypes::packBrowserItems(result->items())); + QVariantMap returns = statusToReply(result->status()); + QVariantList list; + foreach (const BrowserItem &item, result->items()) { + list.append(packBrowserItem(item)); + } + returns.insert("items", list); jsonReply->setData(returns); jsonReply->finished(); }); @@ -789,12 +891,11 @@ JsonReply *DeviceHandler::GetBrowserItem(const QVariantMap ¶ms) const JsonReply *jsonReply = createAsyncReply("GetBrowserItem"); BrowserItemResult *result = NymeaCore::instance()->deviceManager()->browserItemDetails(deviceId, itemId, params.value("locale").toLocale()); - connect(result, &BrowserItemResult::finished, jsonReply, [jsonReply, result](){ - QVariantMap params; + connect(result, &BrowserItemResult::finished, jsonReply, [this, jsonReply, result](){ + QVariantMap params = statusToReply(result->status()); if (result->status() == Device::DeviceErrorNoError) { - params.insert("item", JsonTypes::packBrowserItem(result->item())); + params.insert("item", packBrowserItem(result->item())); } - params.insert("deviceError", JsonTypes::deviceErrorToString(result->status())); jsonReply->setData(params); jsonReply->finished(); }); @@ -802,13 +903,304 @@ JsonReply *DeviceHandler::GetBrowserItem(const QVariantMap ¶ms) const return jsonReply; } +Param DeviceHandler::unpackParam(const QVariantMap ¶m) +{ + if (param.keys().count() == 0) + return Param(); + + ParamTypeId paramTypeId = param.value("paramTypeId").toString(); + QVariant value = param.value("value"); + return Param(paramTypeId, value); +} + +ParamList DeviceHandler::unpackParams(const QVariantList ¶ms) +{ + ParamList paramList; + foreach (const QVariant ¶mVariant, params) { + paramList.append(unpackParam(paramVariant.toMap())); + } + + return paramList; +} + +QVariantMap DeviceHandler::packParam(const Param ¶m) +{ + QVariantMap variantMap; + variantMap.insert("paramTypeId", param.paramTypeId().toString()); + variantMap.insert("value", param.value()); + return variantMap; +} + +QVariantList DeviceHandler::packParams(const ParamList ¶mList) +{ + QVariantList ret; + foreach (const Param ¶m, paramList) { + ret << packParam(param); + } + return ret; +} + +QVariantMap DeviceHandler::packDevice(Device *device) +{ + QVariantMap variant; + variant.insert("id", device->id().toString()); + variant.insert("deviceClassId", device->deviceClassId().toString()); + variant.insert("name", device->name()); + variant.insert("params", packParams(device->params())); + variant.insert("settings", packParams(device->settings())); + + if (!device->parentId().isNull()) + variant.insert("parentId", device->parentId().toString()); + + variant.insert("states", packDeviceStates(device)); + variant.insert("setupComplete", device->setupComplete()); + return variant; +} + +QVariantList DeviceHandler::packDeviceStates(Device *device) +{ + DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId()); + QVariantList stateValues; + foreach (const StateType &stateType, deviceClass.stateTypes()) { + QVariantMap stateValue; + stateValue.insert("stateTypeId", stateType.id().toString()); + stateValue.insert("value", device->stateValue(stateType.id())); + stateValues.append(stateValue); + } + return stateValues; +} + +QVariantMap DeviceHandler::packBrowserItem(const BrowserItem &item) +{ + QVariantMap ret; + ret.insert("id", item.id()); + ret.insert("displayName", item.displayName()); + ret.insert("description", item.description()); + ret.insert("icon", enumValueName(item.icon())); + if (item.extendedPropertiesFlags().testFlag(BrowserItem::ExtendedPropertiesMedia)) { + ret.insert("mediaIcon", enumValueName(static_cast(item.extendedProperty("mediaIcon").toInt()))); + } + ret.insert("thumbnail", item.thumbnail()); + ret.insert("executable", item.executable()); + ret.insert("browsable", item.browsable()); + ret.insert("disabled", item.disabled()); + QVariantList actionTypeIds; + foreach (const ActionTypeId &id, item.actionTypeIds()) { + actionTypeIds.append(id.toString()); + } + ret.insert("actionTypeIds", actionTypeIds); + return ret; +} + +QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) +{ + QVariantMap variantMap; + variantMap.insert("id", paramType.id().toString()); + variantMap.insert("name", paramType.name()); + variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); + variantMap.insert("type", enumValueName(variantTypeToBasicType(paramType.type()))); + variantMap.insert("index", paramType.index()); + + // Optional values + if (paramType.defaultValue().isValid()) + variantMap.insert("defaultValue", paramType.defaultValue()); + + if (paramType.minValue().isValid()) + variantMap.insert("minValue", paramType.minValue()); + + if (paramType.maxValue().isValid()) + variantMap.insert("maxValue", paramType.maxValue()); + + if (!paramType.allowedValues().isEmpty()) + variantMap.insert("allowedValues", paramType.allowedValues()); + + if (paramType.inputType() != Types::InputTypeNone) + variantMap.insert("inputType", enumValueName(paramType.inputType())); + + if (paramType.unit() != Types::UnitNone) + variantMap.insert("unit", enumValueName(paramType.unit())); + + if (paramType.readOnly()) + variantMap.insert("readOnly", paramType.readOnly()); + + return variantMap; +} + +QVariantMap DeviceHandler::packPlugin(DevicePlugin *plugin, const QLocale &locale) +{ + QVariantMap pluginMap; + pluginMap.insert("id", plugin->pluginId().toString()); + pluginMap.insert("name", plugin->pluginName()); + pluginMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale)); + + QVariantList params; + foreach (const ParamType ¶m, plugin->configurationDescription()) + params.append(packParamType(param, plugin->pluginId(), locale)); + + pluginMap.insert("paramTypes", params); + return pluginMap; +} + +QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) +{ + QVariantMap variant; + variant.insert("id", eventType.id().toString()); + variant.insert("name", eventType.name()); + variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, eventType.displayName(), locale)); + variant.insert("index", eventType.index()); + + QVariantList paramTypes; + foreach (const ParamType ¶mType, eventType.paramTypes()) + paramTypes.append(packParamType(paramType, pluginId, locale)); + + variant.insert("paramTypes", paramTypes); + return variant; +} + +QVariantMap DeviceHandler::packVendor(const Vendor &vendor, const QLocale &locale) +{ + DevicePlugin *plugin = nullptr; + foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) { + if (p->supportedVendors().contains(vendor)) { + plugin = p; + } + } + QVariantMap variantMap; + variantMap.insert("id", vendor.id().toString()); + variantMap.insert("name", vendor.name()); + variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale)); + return variantMap; + +} + +QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) +{ + QVariantMap variantMap; + variantMap.insert("id", actionType.id().toString()); + variantMap.insert("name", actionType.name()); + variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, actionType.displayName(), locale)); + variantMap.insert("index", actionType.index()); + QVariantList paramTypes; + foreach (const ParamType ¶mType, actionType.paramTypes()) + paramTypes.append(packParamType(paramType, pluginId, locale)); + + variantMap.insert("paramTypes", paramTypes); + return variantMap; +} + +QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods) +{ + QVariantList ret; + if (createMethods.testFlag(DeviceClass::CreateMethodUser)) + ret << "CreateMethodUser"; + + if (createMethods.testFlag(DeviceClass::CreateMethodAuto)) + ret << "CreateMethodAuto"; + + if (createMethods.testFlag(DeviceClass::CreateMethodDiscovery)) + ret << "CreateMethodDiscovery"; + + return ret; +} + +QVariantMap DeviceHandler::packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) +{ + QVariantMap variant; + variant.insert("id", deviceClass.id().toString()); + variant.insert("name", deviceClass.name()); + variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), deviceClass.displayName(), locale)); + variant.insert("vendorId", deviceClass.vendorId().toString()); + variant.insert("pluginId", deviceClass.pluginId().toString()); + variant.insert("interfaces", deviceClass.interfaces()); + variant.insert("browsable", deviceClass.browsable()); + + QVariantList stateTypes; + foreach (const StateType &stateType, deviceClass.stateTypes()) + stateTypes.append(packStateType(stateType, deviceClass.pluginId(), locale)); + + QVariantList eventTypes; + foreach (const EventType &eventType, deviceClass.eventTypes()) + eventTypes.append(packEventType(eventType, deviceClass.pluginId(), locale)); + + QVariantList actionTypes; + foreach (const ActionType &actionType, deviceClass.actionTypes()) + actionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); + + QVariantList browserItemActionTypes; + foreach (const ActionType &actionType, deviceClass.browserItemActionTypes()) + browserItemActionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); + + QVariantList paramTypes; + foreach (const ParamType ¶mType, deviceClass.paramTypes()) + paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); + + QVariantList settingsTypes; + foreach (const ParamType &settingsType, deviceClass.settingsTypes()) + settingsTypes.append(packParamType(settingsType, deviceClass.pluginId(), locale)); + + QVariantList discoveryParamTypes; + foreach (const ParamType ¶mType, deviceClass.discoveryParamTypes()) + discoveryParamTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); + + variant.insert("paramTypes", paramTypes); + variant.insert("settingsTypes", settingsTypes); + variant.insert("discoveryParamTypes", discoveryParamTypes); + variant.insert("stateTypes", stateTypes); + variant.insert("eventTypes", eventTypes); + variant.insert("actionTypes", actionTypes); + variant.insert("browserItemActionTypes", browserItemActionTypes); + variant.insert("createMethods", packCreateMethods(deviceClass.createMethods())); + variant.insert("setupMethod", enumValueName(deviceClass.setupMethod())); + return variant; +} + +QVariantMap DeviceHandler::packDeviceDescriptor(const DeviceDescriptor &descriptor) +{ + QVariantMap variant; + variant.insert("id", descriptor.id().toString()); + variant.insert("deviceId", descriptor.deviceId().toString()); + variant.insert("title", descriptor.title()); + variant.insert("description", descriptor.description()); + QVariantList params; + foreach (const Param ¶m, descriptor.params()) { + params.append(packParam(param)); + } + variant.insert("deviceParams", params); + return variant; +} + +QVariantMap DeviceHandler::packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) +{ + QVariantMap variantMap; + variantMap.insert("id", stateType.id().toString()); + variantMap.insert("name", stateType.name()); + variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, stateType.displayName(), locale)); + variantMap.insert("index", stateType.index()); + variantMap.insert("type", enumValueName(variantTypeToBasicType(stateType.type()))); + variantMap.insert("defaultValue", stateType.defaultValue()); + + if (stateType.maxValue().isValid()) + variantMap.insert("maxValue", stateType.maxValue()); + + if (stateType.minValue().isValid()) + variantMap.insert("minValue", stateType.minValue()); + + if (!stateType.possibleValues().isEmpty()) + variantMap.insert("possibleValues", stateType.possibleValues()); + + if(stateType.unit() != Types::UnitNone) + variantMap.insert("unit", enumValueName(stateType.unit())); + + return variantMap; +} + void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config) { QVariantMap params; params.insert("pluginId", id); QVariantList configList; foreach (const Param ¶m, config) { - configList << JsonTypes::packParam(param); + configList << packParam(param); } params.insert("configuration", configList); emit PluginConfigurationChanged(params); @@ -820,7 +1212,6 @@ void DeviceHandler::deviceStateChanged(Device *device, const QUuid &stateTypeId, params.insert("deviceId", device->id()); params.insert("stateTypeId", stateTypeId); params.insert("value", value); - emit StateChanged(params); } @@ -828,23 +1219,20 @@ void DeviceHandler::deviceRemovedNotification(const QUuid &deviceId) { QVariantMap params; params.insert("deviceId", deviceId); - emit DeviceRemoved(params); } void DeviceHandler::deviceAddedNotification(Device *device) { QVariantMap params; - params.insert("device", JsonTypes::packDevice(device)); - + params.insert("device", packDevice(device)); emit DeviceAdded(params); } void DeviceHandler::deviceChangedNotification(Device *device) { QVariantMap params; - params.insert("device", JsonTypes::packDevice(device)); - + params.insert("device", packDevice(device)); emit DeviceChanged(params); } @@ -857,4 +1245,11 @@ void DeviceHandler::deviceSettingChangedNotification(const DeviceId deviceId, co emit DeviceSettingChanged(params); } +QVariantMap DeviceHandler::statusToReply(Device::DeviceError status) const +{ + QVariantMap returns; + returns.insert("deviceError", enumValueName(status)); + return returns; +} + } diff --git a/libnymea-core/jsonrpc/devicehandler.h b/libnymea-core/jsonrpc/devicehandler.h index a73d22ed..b96d37aa 100644 --- a/libnymea-core/jsonrpc/devicehandler.h +++ b/libnymea-core/jsonrpc/devicehandler.h @@ -22,7 +22,7 @@ #ifndef DEVICEHANDLER_H #define DEVICEHANDLER_H -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" #include "devices/devicemanager.h" namespace nymeaserver { @@ -60,6 +60,28 @@ public: Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap ¶ms) const; + static QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale); + static QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale); + static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale); + static QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale); + static QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale); + static QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale); + static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods); + static QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale); + static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor); + + static QVariantMap packParam(const Param ¶m); + static QVariantList packParams(const ParamList ¶mList); + + static QVariantMap packDevice(Device *device); + static QVariantList packDeviceStates(Device *device); + + static QVariantMap packBrowserItem(const BrowserItem &item); + + static Param unpackParam(const QVariantMap ¶m); + static ParamList unpackParams(const QVariantList ¶ms); + + signals: void PluginConfigurationChanged(const QVariantMap ¶ms); void StateChanged(const QVariantMap ¶ms); @@ -80,6 +102,9 @@ private slots: void deviceChangedNotification(Device *device); void deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId ¶mTypeId, const QVariant &value); + +private: + QVariantMap statusToReply(Device::DeviceError status) const; }; } diff --git a/libnymea-core/jsonrpc/eventhandler.cpp b/libnymea-core/jsonrpc/eventhandler.cpp index 12c784a5..f48f140b 100644 --- a/libnymea-core/jsonrpc/eventhandler.cpp +++ b/libnymea-core/jsonrpc/eventhandler.cpp @@ -38,6 +38,7 @@ */ #include "eventhandler.h" +#include "devicehandler.h" #include "nymeacore.h" #include "loggingcategories.h" @@ -47,23 +48,26 @@ namespace nymeaserver { EventHandler::EventHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap params; - QVariantMap returns; + // Objects + QVariantMap event; + event.insert("eventTypeId", enumValueName(Uuid)); + event.insert("deviceId", enumValueName(Uuid)); + event.insert("o:params", QVariantList() << objectRef("Param")); + registerObject("Event", event); + + // Methods + QString description; QVariantMap params; QVariantMap returns; + description = "Get the EventType for the given eventTypeId."; + params.insert("eventTypeId", enumValueName(Uuid)); + returns.insert("deviceError", enumRef()); + returns.insert("o:eventType", objectRef("EventType")); + registerMethod("GetEventType", description, params, returns); // Notifications params.clear(); returns.clear(); - setDescription("EventTriggered", "Emitted whenever an Event is triggered."); - params.insert("event", JsonTypes::eventRef()); - setParams("EventTriggered", params); - - params.clear(); returns.clear(); - setDescription("GetEventType", "Get the EventType for the given eventTypeId."); - params.insert("eventTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetEventType", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:eventType", JsonTypes::eventTypeRef()); - setReturns("GetEventType", returns); - + description = "Emitted whenever an Event is triggered."; + params.insert("event", objectRef("Event")); + registerNotification("EventTriggered", description, params); connect(NymeaCore::instance(), &NymeaCore::eventTriggered, this, &EventHandler::eventTriggered); } @@ -76,7 +80,17 @@ QString EventHandler::name() const void EventHandler::eventTriggered(const Event &event) { QVariantMap params; - params.insert("event", JsonTypes::packEvent(event)); + + QVariantMap variant; + variant.insert("eventTypeId", event.eventTypeId().toString()); + variant.insert("deviceId", event.deviceId().toString()); + QVariantList eventParams; + foreach (const Param ¶m, event.params()) { + eventParams.append(DeviceHandler::packParam(param)); + } + variant.insert("params", eventParams); + + params.insert("event", variant); emit EventTriggered(params); } @@ -87,13 +101,16 @@ JsonReply* EventHandler::GetEventType(const QVariantMap ¶ms) const foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const EventType &eventType, deviceClass.eventTypes()) { if (eventType.id() == eventTypeId) { - QVariantMap data = statusToReply(Device::DeviceErrorNoError); - data.insert("eventType", JsonTypes::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); + QVariantMap data; + data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); + data.insert("eventType", DeviceHandler::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); return createReply(data); } } } - return createReply(statusToReply(Device::DeviceErrorEventTypeNotFound)); + QVariantMap data; + data.insert("deviceError", enumValueName(Device::DeviceErrorEventTypeNotFound)); + return createReply(data); } } diff --git a/libnymea-core/jsonrpc/eventhandler.h b/libnymea-core/jsonrpc/eventhandler.h index deeffe69..6758ace7 100644 --- a/libnymea-core/jsonrpc/eventhandler.h +++ b/libnymea-core/jsonrpc/eventhandler.h @@ -22,7 +22,9 @@ #ifndef EVENTHANDLER_H #define EVENTHANDLER_H -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" + +#include "types/event.h" namespace nymeaserver { @@ -30,7 +32,7 @@ class EventHandler : public JsonHandler { Q_OBJECT public: - explicit EventHandler(QObject *parent = 0); + explicit EventHandler(QObject *parent = nullptr); QString name() const override; Q_INVOKABLE JsonReply *GetEventType(const QVariantMap ¶ms) const; diff --git a/libnymea-core/jsonrpc/jsonhandler.cpp b/libnymea-core/jsonrpc/jsonhandler.cpp deleted file mode 100644 index 81093f90..00000000 --- a/libnymea-core/jsonrpc/jsonhandler.cpp +++ /dev/null @@ -1,354 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * Copyright (C) 2014 Michael Zanetti * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::JsonHandler - \brief This class represents an interface for developing a handler for the JSON-RPC API. - - \ingroup json - \inmodule core - - \sa JsonRPCServer, JsonReply -*/ - -/*! \fn QString nymeaserver::JsonHandler::name() const; - Pure virtual method for a JSON RPC handler. Returns the namespace of the handler. -*/ - -/*! \fn void nymeaserver::JsonHandler::asyncReply(int id, const QVariantMap ¶ms); - This signal will be emitted when a reply with the given \a id and \a params is finished. -*/ - - -#include "jsonhandler.h" -#include "loggingcategories.h" - -#include -#include -#include - -namespace nymeaserver { - -/*! Constructs a new \l JsonHandler with the given \a parent. */ -JsonHandler::JsonHandler(QObject *parent) : - QObject(parent) -{ -} - -/*! Returns a map with all supported methods, notifications and types for the given meta \a type. */ -QVariantMap JsonHandler::introspect(QMetaMethod::MethodType type) -{ - QVariantMap data; - for (int i = 0; i < metaObject()->methodCount(); ++i) { - QMetaMethod method = metaObject()->method(i); - - if (method.methodType() != type) { - continue; - } - - switch (method.methodType()) { - case QMetaMethod::Method: { - if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name()) || !m_returns.contains(method.name())) { - continue; - } - qCDebug(dcJsonRpc) << "got method" << method.name(); - QVariantMap methodData; - methodData.insert("description", m_descriptions.value(method.name())); - methodData.insert("params", m_params.value(method.name())); - methodData.insert("returns", m_returns.value(method.name())); - data.insert(name() + "." + method.name(), methodData); - break; - } - case QMetaMethod::Signal: { - if (!m_descriptions.contains(method.name()) || !m_params.contains(method.name())) { - continue; - } - if (QString(method.name()).contains(QRegExp("^[A-Z]"))) { - qCDebug(dcJsonRpc) << "got signal" << method.name(); - QVariantMap methodData; - methodData.insert("description", m_descriptions.value(method.name())); - methodData.insert("params", m_params.value(method.name())); - data.insert(name() + "." + method.name(), methodData); - } - break; - default: - ;;// Nothing to do for slots - } - } - } - return data; -} - -/*! Returns true if this \l JsonHandler has a method with the given \a methodName.*/ -bool JsonHandler::hasMethod(const QString &methodName) -{ - return m_descriptions.contains(methodName) && m_params.contains(methodName) && m_returns.contains(methodName); -} - -/*! Validates the given \a params for the given \a methodName. Returns the error string and false if - the params are not valid. */ -QPair JsonHandler::validateParams(const QString &methodName, const QVariantMap ¶ms) -{ - QVariantMap paramTemplate = m_params.value(methodName); - return JsonTypes::validateMap(paramTemplate, params); -} - -/*! Validates the given \a returns for the given \a methodName. Returns the error string and false if - the params are not valid. */ -QPair JsonHandler::validateReturns(const QString &methodName, const QVariantMap &returns) -{ - QVariantMap returnsTemplate = m_returns.value(methodName); - return JsonTypes::validateMap(returnsTemplate, returns); -} - - -/*! Sets the \a description of the method with the given \a methodName. */ -void JsonHandler::setDescription(const QString &methodName, const QString &description) -{ - for(int i = 0; i < metaObject()->methodCount(); ++i) { - QMetaMethod method = metaObject()->method(i); - if (method.name() == methodName) { - m_descriptions.insert(methodName, description); - return; - } - } - qCWarning(dcJsonRpc) << "Cannot set description. No such method:" << methodName; -} - -/*! Sets the \a params of the method with the given \a methodName. */ -void JsonHandler::setParams(const QString &methodName, const QVariantMap ¶ms) -{ - for(int i = 0; i < metaObject()->methodCount(); ++i) { - QMetaMethod method = metaObject()->method(i); - if (method.name() == methodName) { - m_params.insert(methodName, params); - return; - } - } - qCWarning(dcJsonRpc) << "Cannot set params. No such method:" << methodName; -} - -/*! Sets the \a returns of the method with the given \a methodName. */ -void JsonHandler::setReturns(const QString &methodName, const QVariantMap &returns) -{ - for(int i = 0; i < metaObject()->methodCount(); ++i) { - QMetaMethod method = metaObject()->method(i); - if (method.name() == methodName) { - m_returns.insert(methodName, returns); - return; - } - } - qCWarning(dcJsonRpc) << "Cannot set returns. No such method:" << methodName; -} - -/*! Returns the pointer to a new \l{JsonReply} with the given \a data. */ -JsonReply *JsonHandler::createReply(const QVariantMap &data) const -{ - return JsonReply::createReply(const_cast(this), data); -} - -/*! Returns the pointer to an asynchronous new \l{JsonReply} with the given \a method. */ -JsonReply* JsonHandler::createAsyncReply(const QString &method) const -{ - return JsonReply::createAsyncReply(const_cast(this), method); -} - -/*! Returns the formated error map for the given \a status. - * - * \sa Device::DeviceError - */ -QVariantMap JsonHandler::statusToReply(Device::DeviceError status) const -{ - QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); - return returns; -} - -/*! Returns the formated error map for the given \a status. - * - * \sa RuleEngine::RuleError - */ -QVariantMap JsonHandler::statusToReply(RuleEngine::RuleError status) const -{ - QVariantMap returns; - returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); - return returns; -} - -/*! Returns the formated error map for the given \a status. - * - * \sa Logging::LoggingError - */ -QVariantMap JsonHandler::statusToReply(Logging::LoggingError status) const -{ - QVariantMap returns; - returns.insert("loggingError", JsonTypes::loggingErrorToString(status)); - return returns; -} - -/*! Returns the formated error map for the given \a status. */ -QVariantMap JsonHandler::statusToReply(NymeaConfiguration::ConfigurationError status) const -{ - QVariantMap returns; - returns.insert("configurationError", JsonTypes::configurationErrorToString(status)); - return returns; -} - -/*! Returns the formated error map for the given \a status. */ -QVariantMap JsonHandler::statusToReply(NetworkManager::NetworkManagerError status) const -{ - QVariantMap returns; - returns.insert("networkManagerError", JsonTypes::networkManagerErrorToString(status)); - return returns; -} - -/*! Returns the formated error map for the given \a status. */ -QVariantMap JsonHandler::statusToReply(TagsStorage::TagError status) const -{ - QVariantMap returns; - returns.insert("tagError", JsonTypes::tagErrorToString(status)); - return returns; -} - - -/*! - \class nymeaserver::JsonReply - \brief This class represents a reply for the JSON-RPC API request. - - \ingroup json - \inmodule core - - \sa JsonHandler, JsonRPCServer -*/ - -/*! \enum nymeaserver::JsonReply::Type - - This enum type specifies the type of a JsonReply. - - \value TypeSync - The response is synchronous. - \value TypeAsync - The response is asynchronous. -*/ - -/*! \fn void nymeaserver::JsonReply::finished(); - This signal will be emitted when a JsonReply is finished. A JsonReply is finished when - the response is ready or then the reply timed out. -*/ - - - -/*! Constructs a new \l JsonReply with the given \a type, \a handler, \a method and \a data. */ -JsonReply::JsonReply(Type type, JsonHandler *handler, const QString &method, const QVariantMap &data): - m_type(type), - m_data(data), - m_handler(handler), - m_method(method), - m_timedOut(false) -{ - connect(&m_timeout, &QTimer::timeout, this, &JsonReply::timeout); -} - -/*! Returns the pointer to a new \l{JsonReply} for the given \a handler and \a data. */ -JsonReply *JsonReply::createReply(JsonHandler *handler, const QVariantMap &data) -{ - return new JsonReply(TypeSync, handler, QString(), data); -} - -/*! Returns the pointer to a new asynchronous \l{JsonReply} for the given \a handler and \a method. */ -JsonReply *JsonReply::createAsyncReply(JsonHandler *handler, const QString &method) -{ - return new JsonReply(TypeAsync, handler, method); -} - -/*! Returns the type of this \l{JsonReply}.*/ -JsonReply::Type JsonReply::type() const -{ - return m_type; -} - -/*! Returns the data of this \l{JsonReply}.*/ -QVariantMap JsonReply::data() const -{ - return m_data; -} - -/*! Sets the \a data of this \l{JsonReply}.*/ -void JsonReply::setData(const QVariantMap &data) -{ - m_data = data; -} - -/*! Returns the handler of this \l{JsonReply}.*/ -JsonHandler *JsonReply::handler() const -{ - return m_handler; -} - -/*! Returns the method of this \l{JsonReply}.*/ -QString JsonReply::method() const -{ - return m_method; -} - -/*! Returns the client ID of this \l{JsonReply}.*/ -QUuid JsonReply::clientId() const -{ - return m_clientId; -} - -/*! Sets the \a clientId of this \l{JsonReply}.*/ -void JsonReply::setClientId(const QUuid &clientId) -{ - m_clientId = clientId; -} - -/*! Returns the command ID of this \l{JsonReply}.*/ -int JsonReply::commandId() const -{ - return m_commandId; -} - -/*! Returns the \a commandId of this \l{JsonReply}.*/ -void JsonReply::setCommandId(int commandId) -{ - m_commandId = commandId; -} - -/*! Start the timeout timer for this \l{JsonReply}. The default timeout is 15 seconds. */ -void JsonReply::startWait() -{ - m_timeout.start(30000); -} - -void JsonReply::timeout() -{ - m_timedOut = true; - emit finished(); -} - -/*! Returns true if this \l{JsonReply} timed out.*/ -bool JsonReply::timedOut() const -{ - return m_timedOut; -} - -} diff --git a/libnymea-core/jsonrpc/jsonhandler.h b/libnymea-core/jsonrpc/jsonhandler.h deleted file mode 100644 index bf6f099d..00000000 --- a/libnymea-core/jsonrpc/jsonhandler.h +++ /dev/null @@ -1,126 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * Copyright (C) 2014 Michael Zanetti * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef JSONHANDLER_H -#define JSONHANDLER_H - -#include "jsontypes.h" - -#include -#include -#include -#include - -namespace nymeaserver { - -class JsonHandler; - -class JsonReply: public QObject -{ - Q_OBJECT -public: - enum Type { - TypeSync, - TypeAsync - }; - - static JsonReply *createReply(JsonHandler *handler, const QVariantMap &data); - static JsonReply *createAsyncReply(JsonHandler *handler, const QString &method); - - Type type() const; - QVariantMap data() const; - void setData(const QVariantMap &data); - - JsonHandler *handler() const; - QString method() const; - - QUuid clientId() const; - void setClientId(const QUuid &clientId); - - int commandId() const; - void setCommandId(int commandId); - - bool timedOut() const; - -public slots: - void startWait(); - -signals: - void finished(); - -private slots: - void timeout(); - -private: - JsonReply(Type type, JsonHandler *handler, const QString &method, const QVariantMap &data = QVariantMap()); - Type m_type; - QVariantMap m_data; - - JsonHandler *m_handler; - QString m_method; - QUuid m_clientId; - int m_commandId; - bool m_timedOut; - - QTimer m_timeout; - -}; - -class JsonHandler : public QObject -{ - Q_OBJECT -public: - explicit JsonHandler(QObject *parent = nullptr); - - virtual QString name() const = 0; - - QVariantMap introspect(QMetaMethod::MethodType); - - bool hasMethod(const QString &methodName); - QPair validateParams(const QString &methodName, const QVariantMap ¶ms); - QPair validateReturns(const QString &methodName, const QVariantMap &returns); - -signals: - void asyncReply(int id, const QVariantMap ¶ms); - -protected: - void setDescription(const QString &methodName, const QString &description); - void setParams(const QString &methodName, const QVariantMap ¶ms); - void setReturns(const QString &methodName, const QVariantMap &returns); - - JsonReply *createReply(const QVariantMap &data) const; - JsonReply *createAsyncReply(const QString &method) const; - QVariantMap statusToReply(Device::DeviceError status) const; - QVariantMap statusToReply(RuleEngine::RuleError status) const; - QVariantMap statusToReply(Logging::LoggingError status) const; - QVariantMap statusToReply(NymeaConfiguration::ConfigurationError status) const; - QVariantMap statusToReply(NetworkManager::NetworkManagerError status) const; - QVariantMap statusToReply(TagsStorage::TagError status) const; - -private: - QHash m_descriptions; - QHash m_params; - QHash m_returns; -}; - -} - -#endif // JSONHANDLER_H diff --git a/libnymea-core/jsonrpc/jsonrpcserver.cpp b/libnymea-core/jsonrpc/jsonrpcserver.cpp index 6736f9ef..6ad3d6f8 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserver.cpp @@ -37,8 +37,8 @@ #include "jsonrpcserver.h" -#include "jsontypes.h" -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" +#include "jsonvalidator.h" #include "nymeacore.h" #include "devices/devicemanager.h" #include "devices/deviceplugin.h" @@ -72,12 +72,24 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject m_notificationId(0) { Q_UNUSED(sslConfiguration) - // First, define our own JSONRPC methods - QVariantMap returns; - QVariantMap params; + // First, define our own JSONRPC API - params.clear(); returns.clear(); - setDescription("Hello", "Initiates a connection. Use this method to perform an initial handshake of the " + // Enums + registerEnum(); + registerEnum(); + registerEnum(); + + // Objects + QVariantMap tokenInfo; + tokenInfo.insert("id", enumValueName(Uuid)); + tokenInfo.insert("userName", enumValueName(String)); + tokenInfo.insert("deviceName", enumValueName(String)); + tokenInfo.insert("creationTime", enumValueName(Uint)); + registerObject("TokenInfo", tokenInfo); + + // Methods + QString description; QVariantMap returns; QVariantMap params; + description = "Initiates a connection. Use this method to perform an initial handshake of the " "connection. Optionally, a parameter \"locale\" is can be passed to set up the used " "locale for this connection. Strings such as DeviceClass displayNames etc will be " "localized to this locale. If this parameter is omitted, the default system locale " @@ -85,75 +97,69 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject "about this core instance such as version information, uuid and its name. The locale value" "indicates the locale used for this connection. Note: This method can be called multiple " "times. The locale used in the last call for this connection will be used. Other values, " - "like initialSetupRequired might change if the setup has been performed in the meantime."); - params.insert("o:locale", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("Hello", params); - returns.insert("server", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("version", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("uuid", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - returns.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("locale", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("protocol version", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("initialSetupRequired", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("authenticationRequired", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("pushButtonAuthAvailable", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("Hello", returns); + "like initialSetupRequired might change if the setup has been performed in the meantime."; + params.insert("o:locale", enumValueName(String)); + returns.insert("server", enumValueName(String)); + returns.insert("name", enumValueName(String)); + returns.insert("version", enumValueName(String)); + returns.insert("uuid", enumValueName(Uuid)); + returns.insert("language", enumValueName(String)); + returns.insert("locale", enumValueName(String)); + returns.insert("protocol version", enumValueName(String)); + returns.insert("initialSetupRequired", enumValueName(Bool)); + returns.insert("authenticationRequired", enumValueName(Bool)); + returns.insert("pushButtonAuthAvailable", enumValueName(Bool)); + registerMethod("Hello", description, params, returns); params.clear(); returns.clear(); - setDescription("Introspect", "Introspect this API."); - setParams("Introspect", params); - returns.insert("methods", JsonTypes::basicTypeToString(JsonTypes::Object)); - returns.insert("notifications", JsonTypes::basicTypeToString(JsonTypes::Object)); - returns.insert("types", JsonTypes::basicTypeToString(JsonTypes::Object)); - setReturns("Introspect", returns); + description = "Introspect this API."; + returns.insert("methods", enumValueName(Object)); + returns.insert("notifications", enumValueName(Object)); + returns.insert("types", enumValueName(Object)); + registerMethod("Introspect", description, params, returns); params.clear(); returns.clear(); - setDescription("Version", "Version of this nymea/JSONRPC interface."); - setParams("Version", params); - returns.insert("version", JsonTypes::basicTypeToString(JsonTypes::String)); - returns.insert("protocol version", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("Version", returns); + description = "Version of this nymea/JSONRPC interface."; + returns.insert("version", enumValueName(String)); + returns.insert("protocol version", enumValueName(String)); + registerMethod("Version", description, params, returns); params.clear(); returns.clear(); - setDescription("SetNotificationStatus", "Enable/Disable notifications for this connections. Either \"enabled\" or """ + description = "Enable/Disable notifications for this connections. Either \"enabled\" or """ "\"namespaces\" needs to be given but not both of them. The boolean based " "\"enabled\" parameter will enable/disable all notifications at once. If " "instead the list-based \"namespaces\" parameter is provided, all given namespaces" "will be enabled, the others will be disabled. The return value of \"success\" will " "indicate success of the operation. The \"enabled\" property in the return value is " "deprecated and used for legacy compatibilty only. It will be set to true if at least " - "one namespace has been enabled."); - params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); - params.insert("o:namespaces", QVariantList() << QStringLiteral("$ref:Namespace")); - setParams("SetNotificationStatus", params); - returns.insert("namespaces", QVariantList() << QStringLiteral("$ref:Namespace")); - returns.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("SetNotificationStatus", returns); + "one namespace has been enabled."; + params.insert("o:namespaces", enumValueName(StringList)); + params.insert("o:enabled", enumValueName(Bool)); + returns.insert("namespaces", enumValueName(StringList)); + returns.insert("enabled", enumValueName(Bool)); + registerMethod("SetNotificationStatus", description, params, returns); params.clear(); returns.clear(); - setDescription("CreateUser", "Create a new user in the API. Currently this is only allowed to be called once when a new nymea instance is set up. Call Authenticate after this to obtain a device token for this user."); - params.insert("username", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("password", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("CreateUser", params); - returns.insert("error", JsonTypes::userErrorRef()); - setReturns("CreateUser", returns); + description = "Create a new user in the API. Currently this is only allowed to be called once when a new nymea instance is set up. Call Authenticate after this to obtain a device token for this user."; + params.insert("username", enumValueName(String)); + params.insert("password", enumValueName(String)); + returns.insert("error", enumRef()); + registerMethod("CreateUser", description, params, returns); params.clear(); returns.clear(); - setDescription("Authenticate", "Authenticate a client to the api via user & password challenge. Provide " + description = "Authenticate a client to the api via user & password challenge. Provide " "a device name which allows the user to identify the client and revoke the token in case " "the device is lost or stolen. This will return a new token to be used to authorize a " - "client at the API."); - params.insert("username", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("password", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("deviceName", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("Authenticate", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("o:token", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("Authenticate", returns); + "client at the API."; + params.insert("username", enumValueName(String)); + params.insert("password", enumValueName(String)); + params.insert("deviceName", enumValueName(String)); + returns.insert("success", enumValueName(Bool)); + returns.insert("o:token", enumValueName(String)); + registerMethod("Authenticate", description, params, returns); params.clear(); returns.clear(); - setDescription("RequestPushButtonAuth", "Authenticate a client to the api via Push Button method. " + description = "Authenticate a client to the api via Push Button method. " "Provide a device name which allows the user to identify the client and revoke the " "token in case the device is lost or stolen. If push button hardware is available, " "this will return with success and start listening for push button presses. When the " @@ -165,74 +171,67 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject "to the user to not press the button when the procedure fails as this can happen for 2 " "reasons: a) a second user is trying to auth at the same time and only the currently " "active user should press the button or b) it might indicate an attacker trying to take " - "over and snooping in for tokens."); - params.insert("deviceName", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("RequestPushButtonAuth", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("transactionId", JsonTypes::basicTypeToString(JsonTypes::Int)); - setReturns("RequestPushButtonAuth", returns); + "over and snooping in for tokens."; + params.insert("deviceName", enumValueName(String)); + returns.insert("success", enumValueName(Bool)); + returns.insert("transactionId", enumValueName(Int)); + registerMethod("RequestPushButtonAuth", description, params, returns); params.clear(); returns.clear(); - setDescription("Tokens", "Return a list of TokenInfo objects of all the tokens for the current user."); - setParams("Tokens", params); - returns.insert("tokenInfoList", QVariantList() << JsonTypes::tokenInfoRef()); - setReturns("Tokens", returns); + description = "Return a list of TokenInfo objects of all the tokens for the current user."; + returns.insert("tokenInfoList", QVariantList() << objectRef("TokenInfo")); + registerMethod("Tokens", description, params, returns); params.clear(); returns.clear(); - setDescription("RemoveToken", "Revoke access for a given token."); - params.insert("tokenId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("RemoveToken", params); - returns.insert("error", JsonTypes::userErrorRef()); - setReturns("RemoveToken", returns); + description = "Revoke access for a given token."; + params.insert("tokenId", enumValueName(Uuid)); + returns.insert("error", enumRef()); + registerMethod("RemoveToken", description, params, returns); params.clear(); returns.clear(); - setDescription("SetupCloudConnection", "Sets up the cloud connection by deploying a certificate and its configuration."); - params.insert("rootCA", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("certificatePEM", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("publicKey", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("privateKey", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("endpoint", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("SetupCloudConnection", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("SetupCloudConnection", returns); + description = "Sets up the cloud connection by deploying a certificate and its configuration."; + params.insert("rootCA", enumValueName(String)); + params.insert("certificatePEM", enumValueName(String)); + params.insert("publicKey", enumValueName(String)); + params.insert("privateKey", enumValueName(String)); + params.insert("endpoint", enumValueName(String)); + returns.insert("success", enumValueName(Bool)); + registerMethod("SetupCloudConnection", description, params, returns); params.clear(); returns.clear(); - setDescription("SetupRemoteAccess", "Setup the remote connection by providing AWS token information. This requires the cloud to be connected."); - params.insert("idToken", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("userId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("SetupRemoteAccess", params); - returns.insert("status", JsonTypes::basicTypeToString(JsonTypes::Int)); - returns.insert("message", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("SetupRemoteAccess", returns); + description = "Setup the remote connection by providing AWS token information. This requires the cloud to be connected."; + params.insert("idToken", enumValueName(String)); + params.insert("userId", enumValueName(String)); + returns.insert("status", enumValueName(Int)); + returns.insert("message", enumValueName(String)); + registerMethod("SetupRemoteAccess", description, params, returns); params.clear(); returns.clear(); - setDescription("IsCloudConnected", "Check whether the cloud is currently connected. \"connected\" will be true whenever connectionState equals CloudConnectionStateConnected and is deprecated. Please use the connectionState value instead."); - setParams("IsCloudConnected", params); - returns.insert("connected", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("connectionState", JsonTypes::cloudConnectionStateRef()); - setReturns("IsCloudConnected", returns); + description = "Check whether the cloud is currently connected. \"connected\" will be true whenever connectionState equals CloudConnectionStateConnected and is deprecated. Please use the connectionState value instead."; + returns.insert("connected", enumValueName(Bool)); + returns.insert("connectionState", enumRef()); + registerMethod("IsCloudConnected", description, params, returns); params.clear(); returns.clear(); - setDescription("KeepAlive", "This is basically a Ping/Pong mechanism a client app may use to check server connectivity. Currently, the server does not actually do anything with this information and will return the call providing the given sessionId back to the caller. It is up to the client whether to use this or not and not required by the server to keep the connection alive."); - params.insert("sessionId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("KeepAlive", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("sessionId", JsonTypes::basicTypeToString(JsonTypes::String)); - setReturns("KeepAlive", returns); + description = "This is basically a Ping/Pong mechanism a client app may use to check server connectivity. Currently, the server does not actually do anything with this information and will return the call providing the given sessionId back to the caller. It is up to the client whether to use this or not and not required by the server to keep the connection alive."; + params.insert("sessionId", enumValueName(String)); + returns.insert("success", enumValueName(Bool)); + returns.insert("sessionId", enumValueName(String)); + registerMethod("KeepAlive", description, params, returns); // Notifications params.clear(); returns.clear(); - setDescription("CloudConnectedChanged", "Emitted whenever the cloud connection status changes."); - params.insert("connected", JsonTypes::basicTypeToString(JsonTypes::Bool)); - params.insert("connectionState", JsonTypes::cloudConnectionStateRef()); - setParams("CloudConnectedChanged", params); + description = "Emitted whenever the cloud connection status changes."; + params.insert("connected", enumValueName(Bool)); + params.insert("connectionState", enumRef()); + registerNotification("CloudConnectedChanged", description, params); params.clear(); - setDescription("PushButtonAuthFinished", "Emitted when a push button authentication reaches final state. NOTE: This notification is special. It will only be emitted to connections that did actively request a push button authentication, but also it will be emitted regardless of the notification settings. "); - params.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - params.insert("transactionId", JsonTypes::basicTypeToString(JsonTypes::Int)); - params.insert("o:token", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("PushButtonAuthFinished", params); + description = "Emitted when a push button authentication reaches final state. NOTE: This notification is special. It will only be emitted to connections that did actively request a push button authentication, but also it will be emitted regardless of the notification settings. "; + params.insert("success", enumValueName(Bool)); + params.insert("transactionId", enumValueName(Int)); + params.insert("o:token", enumValueName(String)); + registerNotification("PushButtonAuthFinished", description, params); QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection); @@ -247,7 +246,6 @@ QString JsonRPCServer::name() const JsonReply *JsonRPCServer::Hello(const QVariantMap ¶ms) { - Q_UNUSED(params); TransportInterface *interface = reinterpret_cast(property("transportInterface").toLongLong()); qCDebug(dcJsonRpc()) << params; @@ -269,32 +267,7 @@ JsonReply *JsonRPCServer::Hello(const QVariantMap ¶ms) JsonReply* JsonRPCServer::Introspect(const QVariantMap ¶ms) const { Q_UNUSED(params) - - // We need to add dynamic stuff ourselves - QVariantMap allTypes = JsonTypes::allTypes(); - QStringList namespaces; - foreach (const QString &namespaceString, m_handlers.keys()) { - namespaces.append(namespaceString); - } - // We need to sort them to have a predictable ordering - std::sort(namespaces.begin(), namespaces.end()); - allTypes.insert("Namespace", namespaces); - - QVariantMap data; - data.insert("types", allTypes); - QVariantMap methods; - foreach (JsonHandler *handler, m_handlers) - methods.unite(handler->introspect(QMetaMethod::Method)); - - data.insert("methods", methods); - - QVariantMap signalsMap; - foreach (JsonHandler *handler, m_handlers) - signalsMap.unite(handler->introspect(QMetaMethod::Signal)); - - data.insert("notifications", signalsMap); - - return createReply(data); + return createReply(m_api); } JsonReply* JsonRPCServer::Version(const QVariantMap ¶ms) const @@ -342,7 +315,7 @@ JsonReply *JsonRPCServer::CreateUser(const QVariantMap ¶ms) UserManager::UserError status = NymeaCore::instance()->userManager()->createUser(username, password); QVariantMap returns; - returns.insert("error", JsonTypes::userErrorToString(status)); + returns.insert("error", enumValueName(status)); return createReply(returns); } @@ -389,7 +362,7 @@ JsonReply *JsonRPCServer::Tokens(const QVariantMap ¶ms) const QList tokens = NymeaCore::instance()->userManager()->tokens(username); QVariantList retList; foreach (const TokenInfo &tokenInfo, tokens) { - retList << JsonTypes::packTokenInfo(tokenInfo); + retList << packTokenInfo(tokenInfo); } QVariantMap retMap; retMap.insert("tokenInfoList", retList); @@ -401,7 +374,7 @@ JsonReply *JsonRPCServer::RemoveToken(const QVariantMap ¶ms) QUuid tokenId = params.value("tokenId").toUuid(); UserManager::UserError error = NymeaCore::instance()->userManager()->removeToken(tokenId); QVariantMap ret; - ret.insert("error", JsonTypes::userErrorToString(error)); + ret.insert("error", enumValueName(error)); return createReply(ret); } @@ -443,7 +416,7 @@ JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap ¶ms) bool connected = NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected; QVariantMap data; data.insert("connected", connected); - data.insert("connectionState", JsonTypes::cloudConnectionStateToString(NymeaCore::instance()->cloudManager()->connectionState())); + data.insert("connectionState", enumValueName(NymeaCore::instance()->cloudManager()->connectionState())); return createReply(data); } @@ -646,19 +619,25 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid JsonHandler *handler = m_handlers.value(targetNamespace); if (!handler) { + qCWarning(dcJsonRpc()) << "JSON RPC method called for invalid namespace:" << targetNamespace; sendErrorResponse(interface, clientId, commandId, "No such namespace"); return; } - if (!handler->hasMethod(method)) { + if (!handler->jsonMethods().contains(method)) { + qCWarning(dcJsonRpc()) << QString("JSON RPC method called for invalid method: %1.%2").arg(targetNamespace).arg(method); sendErrorResponse(interface, clientId, commandId, "No such method"); return; } QVariantMap params = message.value("params").toMap(); - QPair validationResult = handler->validateParams(method, params); - if (!validationResult.first) { - sendErrorResponse(interface, clientId, commandId, "Invalid params: " + validationResult.second); + QVariantMap definition = handler->jsonMethods().value(method).toMap().value("params").toMap(); + JsonValidator validator; + JsonValidator::Result validationResult = validator.validateParams(params, targetNamespace + '.' + method, m_api); + if (!validationResult.success()) { + qCWarning(dcJsonRpc()) << "JSON RPC parameter verification failed for method" << targetNamespace + '.' + method; + qCWarning(dcJsonRpc()) << validationResult.errorString() << "in" << validationResult.where(); + sendErrorResponse(interface, clientId, commandId, "Invalid params: " + validationResult.errorString() + " in " + validationResult.where()); return; } @@ -694,21 +673,23 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid connect(reply, &JsonReply::finished, this, &JsonRPCServer::asyncReplyFinished); reply->startWait(); } else { - Q_ASSERT_X((targetNamespace == "JSONRPC" && method == "Introspect") || handler->validateReturns(method, reply->data()).first - ,"validating return value", formatAssertion(targetNamespace, method, QMetaMethod::Method, handler, reply->data()).toLatin1().data()); + JsonValidator validator; + Q_ASSERT_X((targetNamespace == "JSONRPC" && method == "Introspect") || validator.validateReturns(reply->data(), targetNamespace + '.' + method, m_api).success(), + validator.result().where().toUtf8(), + validator.result().errorString().toUtf8() + "\nReturn value:\n" + QJsonDocument::fromVariant(reply->data()).toJson()); sendResponse(interface, clientId, commandId, reply->data()); reply->deleteLater(); } } -QString JsonRPCServer::formatAssertion(const QString &targetNamespace, const QString &method, QMetaMethod::MethodType methodType, JsonHandler *handler, const QVariantMap &data) const +QVariantMap JsonRPCServer::packTokenInfo(const TokenInfo &tokenInfo) { - QJsonDocument doc = QJsonDocument::fromVariant(handler->introspect(methodType).value(targetNamespace + "." + method)); - QJsonDocument doc2 = QJsonDocument::fromVariant(data); - return QString("\nMethod: %1\nTemplate: %2\nValue: %3") - .arg(targetNamespace + "." + method) - .arg(QString(doc.toJson(QJsonDocument::Indented))) - .arg(QString(doc2.toJson(QJsonDocument::Indented))); + QVariantMap ret; + ret.insert("id", tokenInfo.id().toString()); + ret.insert("userName", tokenInfo.username()); + ret.insert("deviceName", tokenInfo.deviceName()); + ret.insert("creationTime", tokenInfo.creationTime().toTime_t()); + return ret; } void JsonRPCServer::sendNotification(const QVariantMap ¶ms) @@ -721,7 +702,10 @@ void JsonRPCServer::sendNotification(const QVariantMap ¶ms) notification.insert("notification", handler->name() + "." + method.name()); notification.insert("params", params); - Q_ASSERT_X(handler->validateParams(method.name(), params).first, "validating return value", formatAssertion(handler->name(), method.name(), QMetaMethod::Signal, handler, notification).toLatin1().data()); + JsonValidator validator; + Q_ASSERT_X(validator.validateNotificationParams(params, handler->name() + '.' + method.name(), m_api).success(), + validator.result().where().toUtf8(), + validator.result().errorString().toUtf8()); QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact); qCDebug(dcJsonRpc()) << "Sending notification:" << handler->name() + "." + method.name(); qCDebug(dcJsonRpcTraffic()) << "Notification content:" << data; @@ -743,8 +727,10 @@ void JsonRPCServer::asyncReplyFinished() return; } if (!reply->timedOut()) { - Q_ASSERT_X(reply->handler()->validateReturns(reply->method(), reply->data()).first - ,"validating return value", formatAssertion(reply->handler()->name(), reply->method(), QMetaMethod::Method, reply->handler(), reply->data()).toLatin1().data()); + JsonValidator validator; + Q_ASSERT_X(validator.validateReturns(reply->data(), reply->handler()->name() + '.' + reply->method(), m_api).success() + ,validator.result().where().toUtf8() + ,validator.result().errorString().toUtf8()); sendResponse(interface, reply->clientId(), reply->commandId(), reply->data()); } else { qCWarning(dcJsonRpc()) << "RPC call timed out:" << reply->handler()->name() << ":" << reply->method(); @@ -771,7 +757,7 @@ void JsonRPCServer::onCloudConnectionStateChanged() { QVariantMap params; params.insert("connected", NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected); - params.insert("connectionState", JsonTypes::cloudConnectionStateToString(NymeaCore::instance()->cloudManager()->connectionState())); + params.insert("connectionState", enumValueName(NymeaCore::instance()->cloudManager()->connectionState())); emit CloudConnectedChanged(params); } @@ -806,6 +792,79 @@ void JsonRPCServer::onPushButtonAuthFinished(int transactionId, bool success, co void JsonRPCServer::registerHandler(JsonHandler *handler) { + // Sanity checks on API: + // * Make sure all $ref: entries are valid. A Handler can reference Types from previously loaded handlers or own ones. + // * A handler must not register a type name that is already registered by a previously loaded handler. + QVariantMap types = m_api.value("types").toMap(); + QVariantMap methods = m_api.value("methods").toMap(); + QVariantMap notifications = m_api.value("notifications").toMap(); + + // Verify enums name clash + foreach (const QString &enumName, handler->jsonEnums().keys()) { + QVariantList list = handler->jsonEnums().value(enumName).toList(); + if (types.contains(enumName)) { + qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name(); + return; + } + types.insert(enumName, list); + } + + // Verify objects + QVariantMap typesIncludingThis = types; + typesIncludingThis.unite(handler->jsonObjects()); + foreach (const QString &objectName, handler->jsonObjects().keys()) { + QVariantMap object = handler->jsonObjects().value(objectName).toMap(); + // Check for name clashes + if (types.contains(objectName)) { + qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name(); + return; + } + // Check for invalid $ref: entries + if (!JsonValidator::checkRefs(object, typesIncludingThis)) { + qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name(); + return; + } + } + types = typesIncludingThis; + + // Verify methods + QVariantMap newMethods; + foreach (const QString &methodName, handler->jsonMethods().keys()) { + QVariantMap method = handler->jsonMethods().value(methodName).toMap(); + if (handler->metaObject()->indexOfMethod(methodName.toUtf8() + "(QVariantMap)") < 0) { + qCWarning(dcJsonRpc()).nospace().noquote() << "Invalid method \"" << methodName << "\". Method \"JsonReply* " + methodName + "(QVariantMap)\" does not exist. Not registering handler " << handler->name(); + return; + } + if (!JsonValidator::checkRefs(method.value("params").toMap(), types)) { + qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of method " << methodName << ". Not registering handler " << handler->name(); + return; + } + if (!JsonValidator::checkRefs(method.value("returns").toMap(), types)) { + qCWarning(dcJsonRpc()).nospace() << "Invalid reference in return value of method " << methodName << ". Not registering handler " << handler->name(); + return; + } + newMethods.insert(handler->name() + '.' + methodName, method); + } + methods.unite(newMethods); + + // Verify notifications + QVariantMap newNotifications; + foreach (const QString ¬ificationName, handler->jsonNotifications().keys()) { + QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap(); + if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) { + qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name(); + return; + } + newNotifications.insert(handler->name() + '.' + notificationName, notification); + } + notifications.unite(newNotifications); + + // Checks completed. Store new API + qCDebug(dcJsonRpc()) << "Registering JSON RPC handler:" << handler->name(); + m_api["types"] = types; + m_api["methods"] = methods; + m_api["notifications"] = notifications; + m_handlers.insert(handler->name(), handler); for (int i = 0; i < handler->metaObject()->methodCount(); ++i) { QMetaMethod method = handler->metaObject()->method(i); diff --git a/libnymea-core/jsonrpc/jsonrpcserver.h b/libnymea-core/jsonrpc/jsonrpcserver.h index 09fc0d21..28ee036a 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.h +++ b/libnymea-core/jsonrpc/jsonrpcserver.h @@ -22,7 +22,7 @@ #ifndef JSONRPCSERVER_H #define JSONRPCSERVER_H -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" #include "transportinterface.h" #include "usermanager/usermanager.h" @@ -81,6 +81,9 @@ private: void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data); + + static QVariantMap packTokenInfo(const TokenInfo &tokenInfo); + private slots: void setup(); @@ -98,6 +101,7 @@ private slots: void onPushButtonAuthFinished(int transactionId, bool success, const QByteArray &token); private: + QVariantMap m_api; QMap m_interfaces; // Interface, authenticationRequired QHash m_handlers; QHash m_asyncReplies; @@ -114,6 +118,7 @@ private: int m_notificationId; void registerHandler(JsonHandler *handler); + QString formatAssertion(const QString &targetNamespace, const QString &method, QMetaMethod::MethodType methodType, JsonHandler *handler, const QVariantMap &data) const; }; diff --git a/libnymea-core/jsonrpc/jsontypes.cpp b/libnymea-core/jsonrpc/jsontypes.cpp deleted file mode 100644 index 717d6f48..00000000 --- a/libnymea-core/jsonrpc/jsontypes.cpp +++ /dev/null @@ -1,2392 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * Copyright (C) 2014 Michael Zanetti * - * Copyright (C) 2017 Michael Zanetti * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -/*! - \class nymeaserver::JsonTypes - \brief This class represents the types for the JSON-RPC API. - - \ingroup json - \inmodule core - - This class represents all JSON-RPC API types and allows to transform Json - objects into c++ objects and vers visa. - -*/ - -/*! \enum nymeaserver::JsonTypes::BasicType - - This enum type specifies the basic types of a JSON RPC API. - - \value Uuid - \value String - \value Int - \value Uint - \value Double - \value Bool - \value Variant - \value Color - \value Time - \value Object -*/ - -#include "jsontypes.h" - -#include "devices/device.h" -#include "devices/devicemanager.h" -#include "devices/deviceplugin.h" -#include "nymeacore.h" -#include "ruleengine/ruleengine.h" -#include "loggingcategories.h" -#include "logging/logvaluetool.h" - -#include "types/mediabrowseritem.h" - -#include -#include -#include -#include - -namespace nymeaserver { - -bool JsonTypes::s_initialized = false; -QString JsonTypes::s_lastError; - -QVariantList JsonTypes::s_basicType; -QVariantList JsonTypes::s_stateOperator; -QVariantList JsonTypes::s_valueOperator; -QVariantList JsonTypes::s_inputType; -QVariantList JsonTypes::s_unit; -QVariantList JsonTypes::s_createMethod; -QVariantList JsonTypes::s_setupMethod; -QVariantList JsonTypes::s_removePolicy; -QVariantList JsonTypes::s_deviceError; -QVariantList JsonTypes::s_ruleError; -QVariantList JsonTypes::s_loggingError; -QVariantList JsonTypes::s_loggingSource; -QVariantList JsonTypes::s_loggingLevel; -QVariantList JsonTypes::s_loggingEventType; -QVariantList JsonTypes::s_repeatingMode; -QVariantList JsonTypes::s_configurationError; -QVariantList JsonTypes::s_networkManagerError; -QVariantList JsonTypes::s_networkManagerState; -QVariantList JsonTypes::s_networkDeviceState; -QVariantList JsonTypes::s_userError; -QVariantList JsonTypes::s_tagError; -QVariantList JsonTypes::s_cloudConnectionState; -QVariantList JsonTypes::s_browserIcon; -QVariantList JsonTypes::s_mediaBrowserIcon; - -QVariantMap JsonTypes::s_paramType; -QVariantMap JsonTypes::s_param; -QVariantMap JsonTypes::s_ruleAction; -QVariantMap JsonTypes::s_ruleActionParam; -QVariantMap JsonTypes::s_paramDescriptor; -QVariantMap JsonTypes::s_stateType; -QVariantMap JsonTypes::s_state; -QVariantMap JsonTypes::s_stateDescriptor; -QVariantMap JsonTypes::s_stateEvaluator; -QVariantMap JsonTypes::s_eventType; -QVariantMap JsonTypes::s_event; -QVariantMap JsonTypes::s_eventDescriptor; -QVariantMap JsonTypes::s_actionType; -QVariantMap JsonTypes::s_action; -QVariantMap JsonTypes::s_plugin; -QVariantMap JsonTypes::s_vendor; -QVariantMap JsonTypes::s_deviceClass; -QVariantMap JsonTypes::s_device; -QVariantMap JsonTypes::s_deviceDescriptor; -QVariantMap JsonTypes::s_rule; -QVariantMap JsonTypes::s_ruleDescription; -QVariantMap JsonTypes::s_logEntry; -QVariantMap JsonTypes::s_timeDescriptor; -QVariantMap JsonTypes::s_calendarItem; -QVariantMap JsonTypes::s_timeEventItem; -QVariantMap JsonTypes::s_repeatingOption; -QVariantMap JsonTypes::s_wirelessAccessPoint; -QVariantMap JsonTypes::s_wiredNetworkDevice; -QVariantMap JsonTypes::s_wirelessNetworkDevice; -QVariantMap JsonTypes::s_tokenInfo; -QVariantMap JsonTypes::s_serverConfiguration; -QVariantMap JsonTypes::s_webServerConfiguration; -QVariantMap JsonTypes::s_tag; -QVariantMap JsonTypes::s_mqttPolicy; -QVariantMap JsonTypes::s_package; -QVariantMap JsonTypes::s_repository; -QVariantMap JsonTypes::s_browserItem; - -void JsonTypes::init() -{ - // Enums - s_basicType = enumToStrings(JsonTypes::staticMetaObject, "BasicType"); - s_stateOperator = enumToStrings(Types::staticMetaObject, "StateOperator"); - s_valueOperator = enumToStrings(Types::staticMetaObject, "ValueOperator"); - s_inputType = enumToStrings(Types::staticMetaObject, "InputType"); - s_unit = enumToStrings(Types::staticMetaObject, "Unit"); - s_createMethod = enumToStrings(DeviceClass::staticMetaObject, "CreateMethod"); - s_setupMethod = enumToStrings(DeviceClass::staticMetaObject, "SetupMethod"); - s_removePolicy = enumToStrings(RuleEngine::staticMetaObject, "RemovePolicy"); - s_deviceError = enumToStrings(Device::staticMetaObject, "DeviceError"); - s_ruleError = enumToStrings(RuleEngine::staticMetaObject, "RuleError"); - s_loggingError = enumToStrings(Logging::staticMetaObject, "LoggingError"); - s_loggingSource = enumToStrings(Logging::staticMetaObject, "LoggingSource"); - s_loggingLevel = enumToStrings(Logging::staticMetaObject, "LoggingLevel"); - s_loggingEventType = enumToStrings(Logging::staticMetaObject, "LoggingEventType"); - s_repeatingMode = enumToStrings(RepeatingOption::staticMetaObject, "RepeatingMode"); - s_configurationError = enumToStrings(NymeaConfiguration::staticMetaObject, "ConfigurationError"); - s_networkManagerError = enumToStrings(NetworkManager::staticMetaObject, "NetworkManagerError"); - s_networkManagerState = enumToStrings(NetworkManager::staticMetaObject, "NetworkManagerState"); - s_networkDeviceState = enumToStrings(NetworkDevice::staticMetaObject, "NetworkDeviceState"); - s_userError = enumToStrings(UserManager::staticMetaObject, "UserError"); - s_tagError = enumToStrings(TagsStorage::staticMetaObject, "TagError"); - s_cloudConnectionState = enumToStrings(CloudManager::staticMetaObject, "CloudConnectionState"); - s_browserIcon = enumToStrings(BrowserItem::staticMetaObject, "BrowserIcon"); - s_mediaBrowserIcon = enumToStrings(MediaBrowserItem::staticMetaObject, "MediaBrowserIcon"); - - // ParamType - s_paramType.insert("id", basicTypeToString(Uuid)); - s_paramType.insert("name", basicTypeToString(String)); - s_paramType.insert("displayName", basicTypeToString(String)); - s_paramType.insert("type", basicTypeRef()); - s_paramType.insert("index", basicTypeToString(Int)); - s_paramType.insert("o:defaultValue", basicTypeToString(Variant)); - s_paramType.insert("o:minValue", basicTypeToString(Variant)); - s_paramType.insert("o:maxValue", basicTypeToString(Variant)); - s_paramType.insert("o:allowedValues", QVariantList() << basicTypeToString(Variant)); - s_paramType.insert("o:inputType", inputTypeRef()); - s_paramType.insert("o:unit", unitRef()); - s_paramType.insert("o:readOnly", basicTypeToString(Bool)); - - // Param - s_param.insert("paramTypeId", basicTypeToString(Uuid)); - s_param.insert("value", basicTypeRef()); - - // RuleAction - s_ruleAction.insert("o:deviceId", basicTypeToString(Uuid)); - s_ruleAction.insert("o:actionTypeId", basicTypeToString(Uuid)); - s_ruleAction.insert("o:interface", basicTypeToString(String)); - s_ruleAction.insert("o:interfaceAction", basicTypeToString(String)); - s_ruleAction.insert("o:browserItemId", basicTypeToString(String)); - s_ruleAction.insert("o:ruleActionParams", QVariantList() << ruleActionParamRef()); - - // RuleActionParam - s_ruleActionParam.insert("o:paramTypeId", basicTypeToString(Uuid)); - s_ruleActionParam.insert("o:paramName", basicTypeToString(String)); - s_ruleActionParam.insert("o:value", basicTypeRef()); - s_ruleActionParam.insert("o:eventTypeId", basicTypeToString(Uuid)); - s_ruleActionParam.insert("o:eventParamTypeId", basicTypeToString(Uuid)); - s_ruleActionParam.insert("o:stateDeviceId", basicTypeToString(Uuid)); - s_ruleActionParam.insert("o:stateTypeId", basicTypeToString(Uuid)); - - // ParamDescriptor - s_paramDescriptor.insert("o:paramTypeId", basicTypeToString(Uuid)); - s_paramDescriptor.insert("o:paramName", basicTypeToString(Uuid)); - s_paramDescriptor.insert("value", basicTypeRef()); - s_paramDescriptor.insert("operator", valueOperatorRef()); - - // StateType - s_stateType.insert("id", basicTypeToString(Uuid)); - s_stateType.insert("name", basicTypeToString(String)); - s_stateType.insert("displayName", basicTypeToString(String)); - s_stateType.insert("type", basicTypeRef()); - s_stateType.insert("index", basicTypeToString(Int)); - s_stateType.insert("defaultValue", basicTypeToString(Variant)); - s_stateType.insert("o:unit", unitRef()); - s_stateType.insert("o:minValue", basicTypeToString(Variant)); - s_stateType.insert("o:maxValue", basicTypeToString(Variant)); - s_stateType.insert("o:possibleValues", QVariantList() << basicTypeToString(Variant)); - - // State - s_state.insert("stateTypeId", basicTypeToString(Uuid)); - s_state.insert("deviceId", basicTypeToString(Uuid)); - s_state.insert("value", basicTypeToString(Variant)); - - // StateDescriptor - s_stateDescriptor.insert("o:stateTypeId", basicTypeToString(Uuid)); - s_stateDescriptor.insert("o:deviceId", basicTypeToString(Uuid)); - s_stateDescriptor.insert("o:interface", basicTypeToString(String)); - s_stateDescriptor.insert("o:interfaceState", basicTypeToString(String)); - s_stateDescriptor.insert("value", basicTypeToString(Variant)); - s_stateDescriptor.insert("operator", valueOperatorRef()); - - // StateEvaluator - s_stateEvaluator.insert("o:stateDescriptor", stateDescriptorRef()); - s_stateEvaluator.insert("o:childEvaluators", QVariantList() << stateEvaluatorRef()); - s_stateEvaluator.insert("o:operator", stateOperatorRef()); - - // EventType - s_eventType.insert("id", basicTypeToString(Uuid)); - s_eventType.insert("name", basicTypeToString(String)); - s_eventType.insert("displayName", basicTypeToString(String)); - s_eventType.insert("index", basicTypeToString(Int)); - s_eventType.insert("paramTypes", QVariantList() << paramTypeRef()); - - // Event - s_event.insert("eventTypeId", basicTypeToString(Uuid)); - s_event.insert("deviceId", basicTypeToString(Uuid)); - s_event.insert("o:params", QVariantList() << paramRef()); - - // EventDescriptor - s_eventDescriptor.insert("o:eventTypeId", basicTypeToString(Uuid)); - s_eventDescriptor.insert("o:deviceId", basicTypeToString(Uuid)); - s_eventDescriptor.insert("o:interface", basicTypeToString(String)); - s_eventDescriptor.insert("o:interfaceEvent", basicTypeToString(String)); - s_eventDescriptor.insert("o:paramDescriptors", QVariantList() << paramDescriptorRef()); - - // ActionType - s_actionType.insert("id", basicTypeToString(Uuid)); - s_actionType.insert("name", basicTypeToString(String)); - s_actionType.insert("displayName", basicTypeToString(String)); - s_actionType.insert("index", basicTypeToString(Int)); - s_actionType.insert("paramTypes", QVariantList() << paramTypeRef()); - - // Action - s_action.insert("actionTypeId", basicTypeToString(Uuid)); - s_action.insert("deviceId", basicTypeToString(Uuid)); - s_action.insert("o:params", QVariantList() << paramRef()); - - // Pugin - s_plugin.insert("id", basicTypeToString(Uuid)); - s_plugin.insert("name", basicTypeToString(String)); - s_plugin.insert("displayName", basicTypeToString(String)); - s_plugin.insert("paramTypes", QVariantList() << paramTypeRef()); - - // Vendor - s_vendor.insert("id", basicTypeToString(Uuid)); - s_vendor.insert("name", basicTypeToString(String)); - s_vendor.insert("displayName", basicTypeToString(String)); - - // DeviceClass - s_deviceClass.insert("id", basicTypeToString(Uuid)); - s_deviceClass.insert("vendorId", basicTypeToString(Uuid)); - s_deviceClass.insert("pluginId", basicTypeToString(Uuid)); - s_deviceClass.insert("name", basicTypeToString(String)); - s_deviceClass.insert("displayName", basicTypeToString(String)); - s_deviceClass.insert("interfaces", QVariantList() << basicTypeToString(String)); - s_deviceClass.insert("browsable", basicTypeToString(Bool)); - s_deviceClass.insert("setupMethod", setupMethodRef()); - s_deviceClass.insert("createMethods", QVariantList() << createMethodRef()); - s_deviceClass.insert("stateTypes", QVariantList() << stateTypeRef()); - s_deviceClass.insert("eventTypes", QVariantList() << eventTypeRef()); - s_deviceClass.insert("actionTypes", QVariantList() << actionTypeRef()); - s_deviceClass.insert("browserItemActionTypes", QVariantList() << actionTypeRef()); - s_deviceClass.insert("paramTypes", QVariantList() << paramTypeRef()); - s_deviceClass.insert("settingsTypes", QVariantList() << paramTypeRef()); - s_deviceClass.insert("discoveryParamTypes", QVariantList() << paramTypeRef()); - - // Device - s_device.insert("id", basicTypeToString(Uuid)); - s_device.insert("deviceClassId", basicTypeToString(Uuid)); - s_device.insert("name", basicTypeToString(String)); - s_device.insert("params", QVariantList() << paramRef()); - s_device.insert("settings", QVariantList() << paramRef()); - QVariantMap stateValues; - stateValues.insert("stateTypeId", basicTypeToString(Uuid)); - stateValues.insert("value", basicTypeToString(Variant)); - s_device.insert("states", QVariantList() << stateValues); - s_device.insert("setupComplete", basicTypeToString(Bool)); - s_device.insert("o:parentId", basicTypeToString(Uuid)); - - // DeviceDescriptor - s_deviceDescriptor.insert("id", basicTypeToString(Uuid)); - s_deviceDescriptor.insert("deviceId", basicTypeToString(Uuid)); - s_deviceDescriptor.insert("title", basicTypeToString(String)); - s_deviceDescriptor.insert("description", basicTypeToString(String)); - s_deviceDescriptor.insert("deviceParams", QVariantList() << paramRef()); - - // Rule - s_rule.insert("id", basicTypeToString(Uuid)); - s_rule.insert("name", basicTypeToString(String)); - s_rule.insert("enabled", basicTypeToString(Bool)); - s_rule.insert("executable", basicTypeToString(Bool)); - s_rule.insert("active", basicTypeToString(Bool)); - s_rule.insert("eventDescriptors", QVariantList() << eventDescriptorRef()); - s_rule.insert("actions", QVariantList() << ruleActionRef()); - s_rule.insert("exitActions", QVariantList() << ruleActionRef()); - s_rule.insert("stateEvaluator", stateEvaluatorRef()); - s_rule.insert("timeDescriptor", timeDescriptorRef()); - - // RuleDescription - s_ruleDescription.insert("id", basicTypeToString(Uuid)); - s_ruleDescription.insert("name", basicTypeToString(String)); - s_ruleDescription.insert("enabled", basicTypeToString(Bool)); - s_ruleDescription.insert("active", basicTypeToString(Bool)); - s_ruleDescription.insert("executable", basicTypeToString(Bool)); - - // LogEntry - s_logEntry.insert("timestamp", basicTypeToString(Int)); - s_logEntry.insert("loggingLevel", loggingLevelRef()); - s_logEntry.insert("source", loggingSourceRef()); - s_logEntry.insert("o:typeId", basicTypeToString(Uuid)); - s_logEntry.insert("o:deviceId", basicTypeToString(Uuid)); - s_logEntry.insert("o:itemId", basicTypeToString(String)); - s_logEntry.insert("o:value", basicTypeToString(String)); - s_logEntry.insert("o:active", basicTypeToString(Bool)); - s_logEntry.insert("o:eventType", loggingEventTypeRef()); - s_logEntry.insert("o:errorCode", basicTypeToString(String)); - - // TimeDescriptor - s_timeDescriptor.insert("o:calendarItems", QVariantList() << calendarItemRef()); - s_timeDescriptor.insert("o:timeEventItems", QVariantList() << timeEventItemRef()); - - // CalendarItem - s_calendarItem.insert("o:datetime", basicTypeToString(QVariant::UInt)); - s_calendarItem.insert("o:startTime", basicTypeToString(QVariant::Time)); - s_calendarItem.insert("duration", basicTypeToString(QVariant::UInt)); - s_calendarItem.insert("o:repeating", repeatingOptionRef()); - - // TimeEventItem - s_timeEventItem.insert("o:datetime", basicTypeToString(QVariant::UInt)); - s_timeEventItem.insert("o:time", basicTypeToString(QVariant::Time)); - s_timeEventItem.insert("o:repeating", repeatingOptionRef()); - - // RepeatingOption - s_repeatingOption.insert("mode", repeatingModeRef()); - s_repeatingOption.insert("o:weekDays", QVariantList() << basicTypeToString(Int)); - s_repeatingOption.insert("o:monthDays", QVariantList() << basicTypeToString(Int)); - - // WirelessAccessPoint - s_wirelessAccessPoint.insert("ssid", basicTypeToString(QVariant::String)); - s_wirelessAccessPoint.insert("macAddress", basicTypeToString(QVariant::String)); - s_wirelessAccessPoint.insert("frequency", basicTypeToString(QVariant::Double)); - s_wirelessAccessPoint.insert("signalStrength", basicTypeToString(QVariant::Int)); - s_wirelessAccessPoint.insert("protected", basicTypeToString(QVariant::Bool)); - - // WiredNetworkDevice - s_wiredNetworkDevice.insert("interface", basicTypeToString(QVariant::String)); - s_wiredNetworkDevice.insert("macAddress", basicTypeToString(QVariant::String)); - s_wiredNetworkDevice.insert("state", networkDeviceStateRef()); - s_wiredNetworkDevice.insert("bitRate", basicTypeToString(QVariant::String)); - s_wiredNetworkDevice.insert("pluggedIn", basicTypeToString(QVariant::Bool)); - - // WirelessNetworkDevice - s_wirelessNetworkDevice.insert("interface", basicTypeToString(QVariant::String)); - s_wirelessNetworkDevice.insert("macAddress", basicTypeToString(QVariant::String)); - s_wirelessNetworkDevice.insert("state", networkDeviceStateRef()); - s_wirelessNetworkDevice.insert("bitRate", basicTypeToString(QVariant::String)); - s_wirelessNetworkDevice.insert("o:currentAccessPoint", wirelessAccessPointRef()); - - // TokenInfo - s_tokenInfo.insert("id", basicTypeToString(QVariant::Uuid)); - s_tokenInfo.insert("userName", basicTypeToString(QVariant::String)); - s_tokenInfo.insert("deviceName", basicTypeToString(QVariant::String)); - s_tokenInfo.insert("creationTime", basicTypeToString(QVariant::UInt)); - - // ServerConfiguration - s_serverConfiguration.insert("id", basicTypeToString(QVariant::String)); - s_serverConfiguration.insert("address", basicTypeToString(QVariant::String)); - s_serverConfiguration.insert("port", basicTypeToString(QVariant::UInt)); - s_serverConfiguration.insert("sslEnabled", basicTypeToString(QVariant::Bool)); - s_serverConfiguration.insert("authenticationEnabled", basicTypeToString(QVariant::Bool)); - - s_webServerConfiguration = s_serverConfiguration; - s_webServerConfiguration.insert("publicFolder", basicTypeToString(QVariant::String)); - - // MQTT - s_mqttPolicy.insert("clientId", basicTypeToString(QVariant::String)); - s_mqttPolicy.insert("username", basicTypeToString(QVariant::String)); - s_mqttPolicy.insert("password", basicTypeToString(QVariant::String)); - s_mqttPolicy.insert("allowedPublishTopicFilters", basicTypeToString(QVariant::StringList)); - s_mqttPolicy.insert("allowedSubscribeTopicFilters", basicTypeToString(QVariant::StringList)); - - // Tag - s_tag.insert("o:deviceId", basicTypeToString(QVariant::Uuid)); - s_tag.insert("o:ruleId", basicTypeToString(QVariant::Uuid)); - s_tag.insert("appId", basicTypeToString(QVariant::String)); - s_tag.insert("tagId", basicTypeToString(QVariant::String)); - s_tag.insert("o:value", basicTypeToString(QVariant::String)); - - // Package - s_package.insert("id", basicTypeToString(QVariant::String)); - s_package.insert("displayName", basicTypeToString(QVariant::String)); - s_package.insert("summary", basicTypeToString(QVariant::String)); - s_package.insert("installedVersion", basicTypeToString(QVariant::String)); - s_package.insert("candidateVersion", basicTypeToString(QVariant::String)); - s_package.insert("changelog", basicTypeToString(QVariant::String)); - s_package.insert("updateAvailable", basicTypeToString(QVariant::Bool)); - s_package.insert("rollbackAvailable", basicTypeToString(QVariant::Bool)); - s_package.insert("canRemove", basicTypeToString(QVariant::Bool)); - - // Repository - s_repository.insert("id", basicTypeToString(QVariant::String)); - s_repository.insert("displayName", basicTypeToString(QVariant::String)); - s_repository.insert("enabled", basicTypeToString(QVariant::Bool)); - - // BrowserItem - s_browserItem.insert("id", basicTypeToString(QVariant::String)); - s_browserItem.insert("displayName", basicTypeToString(QVariant::String)); - s_browserItem.insert("description", basicTypeToString(QVariant::String)); - s_browserItem.insert("icon", browserIconRef()); - s_browserItem.insert("thumbnail", basicTypeToString(QVariant::String)); - s_browserItem.insert("executable", basicTypeToString(QVariant::Bool)); - s_browserItem.insert("browsable", basicTypeToString(QVariant::Bool)); - s_browserItem.insert("disabled", basicTypeToString(QVariant::Bool)); - s_browserItem.insert("actionTypeIds", QVariantList() << basicTypeToString(QVariant::Uuid)); - s_browserItem.insert("o:mediaIcon", mediaBrowserIconRef()); - - s_initialized = true; -} - -QPair JsonTypes::report(bool status, const QString &message) -{ - return qMakePair(status, message); -} - -QVariantList JsonTypes::enumToStrings(const QMetaObject &metaObject, const QString &enumName) -{ - int enumIndex = metaObject.indexOfEnumerator(enumName.toLatin1().data()); - Q_ASSERT_X(enumIndex >= 0, "JsonTypes", QString("Enumerator %1 not found in %2").arg(enumName).arg(metaObject.className()).toLocal8Bit()); - QMetaEnum metaEnum = metaObject.enumerator(enumIndex); - - QVariantList enumStrings; - for (int i = 0; i < metaEnum.keyCount(); i++) - enumStrings << metaEnum.valueToKey(metaEnum.value(i)); - - return enumStrings; -} - -/*! Returns a map containing all API types. */ -QVariantMap JsonTypes::allTypes() -{ - QVariantMap allTypes; - allTypes.insert("BasicType", basicType()); - allTypes.insert("ParamType", paramTypeDescription()); - allTypes.insert("InputType", inputType()); - allTypes.insert("Unit", unit()); - allTypes.insert("CreateMethod", createMethod()); - allTypes.insert("SetupMethod", setupMethod()); - allTypes.insert("ValueOperator", valueOperator()); - allTypes.insert("StateOperator", stateOperator()); - allTypes.insert("RemovePolicy", removePolicy()); - allTypes.insert("DeviceError", deviceError()); - allTypes.insert("RuleError", ruleError()); - allTypes.insert("LoggingError", loggingError()); - allTypes.insert("LoggingLevel", loggingLevel()); - allTypes.insert("LoggingSource", loggingSource()); - allTypes.insert("LoggingEventType", loggingEventType()); - allTypes.insert("RepeatingMode", repeatingMode()); - allTypes.insert("ConfigurationError", configurationError()); - allTypes.insert("NetworkManagerError", networkManagerError()); - allTypes.insert("NetworkManagerState", networkManagerState()); - allTypes.insert("NetworkDeviceState", networkDeviceState()); - allTypes.insert("UserError", userError()); - allTypes.insert("TagError", tagError()); - allTypes.insert("CloudConnectionState", cloudConnectionState()); - allTypes.insert("BrowserIcon", browserIcon()); - allTypes.insert("MediaBrowserIcon", mediaBrowserIcon()); - - allTypes.insert("StateType", stateTypeDescription()); - allTypes.insert("StateDescriptor", stateDescriptorDescription()); - allTypes.insert("StateEvaluator", stateEvaluatorDescription()); - allTypes.insert("Event", eventDescription()); - allTypes.insert("EventType", eventTypeDescription()); - allTypes.insert("EventDescriptor", eventDescriptorDescription()); - allTypes.insert("ActionType", actionTypeDescription()); - allTypes.insert("Vendor", vendorDescription()); - allTypes.insert("DeviceClass", deviceClassDescription()); - allTypes.insert("Plugin", pluginDescription()); - allTypes.insert("Param", paramDescription()); - allTypes.insert("RuleAction", ruleActionDescription()); - allTypes.insert("RuleActionParam", ruleActionParamDescription()); - allTypes.insert("ParamDescriptor", paramDescriptorDescription()); - allTypes.insert("State", stateDescription()); - allTypes.insert("Device", deviceDescription()); - allTypes.insert("DeviceDescriptor", deviceDescriptorDescription()); - allTypes.insert("Action", actionDescription()); - allTypes.insert("Rule", ruleDescription()); - allTypes.insert("RuleDescription", ruleDescriptionDescription()); - allTypes.insert("LogEntry", logEntryDescription()); - allTypes.insert("TimeDescriptor", timeDescriptorDescription()); - allTypes.insert("CalendarItem", calendarItemDescription()); - allTypes.insert("TimeEventItem", timeEventItemDescription()); - allTypes.insert("RepeatingOption", repeatingOptionDescription()); - allTypes.insert("WirelessAccessPoint", wirelessAccessPointDescription()); - allTypes.insert("WiredNetworkDevice", wiredNetworkDeviceDescription()); - allTypes.insert("WirelessNetworkDevice", wirelessNetworkDeviceDescription()); - allTypes.insert("TokenInfo", tokenInfoDescription()); - allTypes.insert("ServerConfiguration", serverConfigurationDescription()); - allTypes.insert("WebServerConfiguration", serverConfigurationDescription()); - allTypes.insert("Tag", tagDescription()); - allTypes.insert("MqttPolicy", mqttPolicyDescription()); - allTypes.insert("Package", packageDescription()); - allTypes.insert("Repository", repositoryDescription()); - allTypes.insert("BrowserItem", browserItemDescription()); - - return allTypes; -} - -/*! Returns a variant map of the given \a eventType. */ -QVariantMap JsonTypes::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) -{ - QVariantMap variant; - variant.insert("id", eventType.id().toString()); - variant.insert("name", eventType.name()); - variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, eventType.displayName(), locale)); - variant.insert("index", eventType.index()); - - QVariantList paramTypes; - foreach (const ParamType ¶mType, eventType.paramTypes()) - paramTypes.append(packParamType(paramType, pluginId, locale)); - - variant.insert("paramTypes", paramTypes); - return variant; -} - -/*! Returns a variant map of the given \a event. */ -QVariantMap JsonTypes::packEvent(const Event &event) -{ - QVariantMap variant; - variant.insert("eventTypeId", event.eventTypeId().toString()); - variant.insert("deviceId", event.deviceId().toString()); - QVariantList params; - foreach (const Param ¶m, event.params()) - params.append(packParam(param)); - - variant.insert("params", params); - return variant; -} - -/*! Returns a variant map of the given \a eventDescriptor. */ -QVariantMap JsonTypes::packEventDescriptor(const EventDescriptor &eventDescriptor) -{ - QVariantMap variant; - if (eventDescriptor.type() == EventDescriptor::TypeDevice) { - variant.insert("eventTypeId", eventDescriptor.eventTypeId().toString()); - variant.insert("deviceId", eventDescriptor.deviceId().toString()); - } else { - variant.insert("interface", eventDescriptor.interface()); - variant.insert("interfaceEvent", eventDescriptor.interfaceEvent()); - } - QVariantList params; - foreach (const ParamDescriptor ¶mDescriptor, eventDescriptor.paramDescriptors()) - params.append(packParamDescriptor(paramDescriptor)); - - variant.insert("paramDescriptors", params); - return variant; -} - -/*! Returns a variant map of the given \a actionType. */ -QVariantMap JsonTypes::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) -{ - QVariantMap variantMap; - variantMap.insert("id", actionType.id().toString()); - variantMap.insert("name", actionType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, actionType.displayName(), locale)); - variantMap.insert("index", actionType.index()); - QVariantList paramTypes; - foreach (const ParamType ¶mType, actionType.paramTypes()) - paramTypes.append(packParamType(paramType, pluginId, locale)); - - variantMap.insert("paramTypes", paramTypes); - return variantMap; -} - -/*! Returns a variant map of the given \a action. */ -QVariantMap JsonTypes::packAction(const Action &action) -{ - QVariantMap variant; - variant.insert("actionTypeId", action.actionTypeId().toString()); - variant.insert("deviceId", action.deviceId().toString()); - QVariantList params; - foreach (const Param ¶m, action.params()) - params.append(packParam(param)); - - variant.insert("params", params); - return variant; -} - -/*! Returns a variant map of the given \a ruleAction. */ -QVariantMap JsonTypes::packRuleAction(const RuleAction &ruleAction) -{ - QVariantMap variant; - if (ruleAction.type() == RuleAction::TypeDevice) { - variant.insert("deviceId", ruleAction.deviceId().toString()); - variant.insert("actionTypeId", ruleAction.actionTypeId().toString()); - } else if (ruleAction.type() == RuleAction::TypeBrowser) { - variant.insert("deviceId", ruleAction.deviceId().toString()); - variant.insert("browserItemId", ruleAction.browserItemId()); - } else { - variant.insert("interface", ruleAction.interface()); - variant.insert("interfaceAction", ruleAction.interfaceAction()); - } - QVariantList params; - foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) - params.append(packRuleActionParam(ruleActionParam)); - - variant.insert("ruleActionParams", params); - return variant; -} - -/*! Returns a variant map of the given \a ruleActionParam. */ -QVariantMap JsonTypes::packRuleActionParam(const RuleActionParam &ruleActionParam) -{ - QVariantMap variantMap; - if (!ruleActionParam.paramTypeId().isNull()) { - variantMap.insert("paramTypeId", ruleActionParam.paramTypeId().toString()); - } else { - variantMap.insert("paramName", ruleActionParam.paramName()); - } - - if (ruleActionParam.isEventBased()) { - variantMap.insert("eventTypeId", ruleActionParam.eventTypeId().toString()); - variantMap.insert("eventParamTypeId", ruleActionParam.eventParamTypeId().toString()); - } else if (ruleActionParam.isStateBased()) { - variantMap.insert("stateDeviceId", ruleActionParam.stateDeviceId().toString()); - variantMap.insert("stateTypeId", ruleActionParam.stateTypeId().toString()); - } else { - variantMap.insert("value", ruleActionParam.value()); - } - return variantMap; -} - -/*! Returns a variant map of the given \a state. */ -QVariantMap JsonTypes::packState(const State &state) -{ - QVariantMap stateMap; - stateMap.insert("stateTypeId", state.stateTypeId().toString()); - stateMap.insert("value", state.value()); - return stateMap; -} - -/*! Returns a variant map of the given \a stateType. */ -QVariantMap JsonTypes::packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) -{ - QVariantMap variantMap; - variantMap.insert("id", stateType.id().toString()); - variantMap.insert("name", stateType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, stateType.displayName(), locale)); - variantMap.insert("index", stateType.index()); - variantMap.insert("type", basicTypeToString(stateType.type())); - variantMap.insert("defaultValue", stateType.defaultValue()); - - if (stateType.maxValue().isValid()) - variantMap.insert("maxValue", stateType.maxValue()); - - if (stateType.minValue().isValid()) - variantMap.insert("minValue", stateType.minValue()); - - if (!stateType.possibleValues().isEmpty()) - variantMap.insert("possibleValues", stateType.possibleValues()); - - if(stateType.unit() != Types::UnitNone) - variantMap.insert("unit", s_unit.at(stateType.unit())); - - return variantMap; -} - -/*! Returns a variant map of the given \a stateDescriptor. */ -QVariantMap JsonTypes::packStateDescriptor(const StateDescriptor &stateDescriptor) -{ - QVariantMap variantMap; - if (stateDescriptor.type() == StateDescriptor::TypeDevice) { - variantMap.insert("stateTypeId", stateDescriptor.stateTypeId().toString()); - variantMap.insert("deviceId", stateDescriptor.deviceId().toString()); - } else { - variantMap.insert("interface", stateDescriptor.interface()); - variantMap.insert("interfaceState", stateDescriptor.interfaceState()); - } - variantMap.insert("value", stateDescriptor.stateValue()); - variantMap.insert("operator", s_valueOperator.at(stateDescriptor.operatorType())); - return variantMap; -} - -/*! Returns a variant map of the given \a stateEvaluator. */ -QVariantMap JsonTypes::packStateEvaluator(const StateEvaluator &stateEvaluator) -{ - QVariantMap variantMap; - if (stateEvaluator.stateDescriptor().isValid()) - variantMap.insert("stateDescriptor", packStateDescriptor(stateEvaluator.stateDescriptor())); - - QVariantList childEvaluators; - foreach (const StateEvaluator &childEvaluator, stateEvaluator.childEvaluators()) - childEvaluators.append(packStateEvaluator(childEvaluator)); - - if (!childEvaluators.isEmpty() || stateEvaluator.stateDescriptor().isValid()) - variantMap.insert("operator", s_stateOperator.at(stateEvaluator.operatorType())); - - if (childEvaluators.count() > 0) - variantMap.insert("childEvaluators", childEvaluators); - - return variantMap; -} - -/*! Returns a variant map of the given \a param. */ -QVariantMap JsonTypes::packParam(const Param ¶m) -{ - QVariantMap variantMap; - variantMap.insert("paramTypeId", param.paramTypeId().toString()); - variantMap.insert("value", param.value()); - return variantMap; -} - -QVariantMap JsonTypes::packBrowserItem(const BrowserItem &item) -{ - QVariantMap ret; - ret.insert("id", item.id()); - ret.insert("displayName", item.displayName()); - ret.insert("description", item.description()); - ret.insert("icon", browserIconToString(item.icon())); - if (item.extendedPropertiesFlags().testFlag(BrowserItem::ExtendedPropertiesMedia)) { - ret.insert("mediaIcon", mediaBrowserIconToString(static_cast(item.extendedProperty("mediaIcon").toInt()))); - } - ret.insert("thumbnail", item.thumbnail()); - ret.insert("executable", item.executable()); - ret.insert("browsable", item.browsable()); - ret.insert("disabled", item.disabled()); - QVariantList actionTypeIds; - foreach (const ActionTypeId &id, item.actionTypeIds()) { - actionTypeIds.append(id.toString()); - } - ret.insert("actionTypeIds", actionTypeIds); - return ret; -} - -QVariantList JsonTypes::packParams(const ParamList ¶mList) -{ - QVariantList ret; - foreach (const Param ¶m, paramList) { - ret << packParam(param); - } - return ret; -} - -/*! Returns a variant map of the given \a paramDescriptor. */ -QVariantMap JsonTypes::packParamDescriptor(const ParamDescriptor ¶mDescriptor) -{ - QVariantMap variantMap; - if (!paramDescriptor.paramTypeId().isNull()) { - variantMap.insert("paramTypeId", paramDescriptor.paramTypeId().toString()); - } else { - variantMap.insert("paramName", paramDescriptor.paramName()); - } - variantMap.insert("value", paramDescriptor.value()); - variantMap.insert("operator", s_valueOperator.at(paramDescriptor.operatorType())); - return variantMap; -} - -/*! Returns a variant map of the given \a paramType. */ -QVariantMap JsonTypes::packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) -{ - QVariantMap variantMap; - variantMap.insert("id", paramType.id().toString()); - variantMap.insert("name", paramType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); - variantMap.insert("type", basicTypeToString(paramType.type())); - variantMap.insert("index", paramType.index()); - - // Optional values - if (paramType.defaultValue().isValid()) - variantMap.insert("defaultValue", paramType.defaultValue()); - - if (paramType.minValue().isValid()) - variantMap.insert("minValue", paramType.minValue()); - - if (paramType.maxValue().isValid()) - variantMap.insert("maxValue", paramType.maxValue()); - - if (!paramType.allowedValues().isEmpty()) - variantMap.insert("allowedValues", paramType.allowedValues()); - - if (paramType.inputType() != Types::InputTypeNone) - variantMap.insert("inputType", s_inputType.at(paramType.inputType())); - - if (paramType.unit() != Types::UnitNone) - variantMap.insert("unit", s_unit.at(paramType.unit())); - - if (paramType.readOnly()) - variantMap.insert("readOnly", paramType.readOnly()); - - return variantMap; -} - -/*! Returns a variant map of the given \a vendor. */ -QVariantMap JsonTypes::packVendor(const Vendor &vendor, const QLocale &locale) -{ - DevicePlugin *plugin = nullptr; - foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) { - if (p->supportedVendors().contains(vendor)) { - plugin = p; - } - } - QVariantMap variantMap; - variantMap.insert("id", vendor.id().toString()); - variantMap.insert("name", vendor.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale)); - return variantMap; -} - -/*! Returns a variant map of the given \a deviceClass. */ -QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) -{ - QVariantMap variant; - variant.insert("id", deviceClass.id().toString()); - variant.insert("name", deviceClass.name()); - variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), deviceClass.displayName(), locale)); - variant.insert("vendorId", deviceClass.vendorId().toString()); - variant.insert("pluginId", deviceClass.pluginId().toString()); - variant.insert("interfaces", deviceClass.interfaces()); - variant.insert("browsable", deviceClass.browsable()); - - QVariantList stateTypes; - foreach (const StateType &stateType, deviceClass.stateTypes()) - stateTypes.append(packStateType(stateType, deviceClass.pluginId(), locale)); - - QVariantList eventTypes; - foreach (const EventType &eventType, deviceClass.eventTypes()) - eventTypes.append(packEventType(eventType, deviceClass.pluginId(), locale)); - - QVariantList actionTypes; - foreach (const ActionType &actionType, deviceClass.actionTypes()) - actionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); - - QVariantList browserItemActionTypes; - foreach (const ActionType &actionType, deviceClass.browserItemActionTypes()) - browserItemActionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); - - QVariantList paramTypes; - foreach (const ParamType ¶mType, deviceClass.paramTypes()) - paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); - - QVariantList settingsTypes; - foreach (const ParamType &settingsType, deviceClass.settingsTypes()) - settingsTypes.append(packParamType(settingsType, deviceClass.pluginId(), locale)); - - QVariantList discoveryParamTypes; - foreach (const ParamType ¶mType, deviceClass.discoveryParamTypes()) - discoveryParamTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); - - variant.insert("paramTypes", paramTypes); - variant.insert("settingsTypes", settingsTypes); - variant.insert("discoveryParamTypes", discoveryParamTypes); - variant.insert("stateTypes", stateTypes); - variant.insert("eventTypes", eventTypes); - variant.insert("actionTypes", actionTypes); - variant.insert("browserItemActionTypes", browserItemActionTypes); - variant.insert("createMethods", packCreateMethods(deviceClass.createMethods())); - variant.insert("setupMethod", s_setupMethod.at(deviceClass.setupMethod())); - return variant; -} - -/*! Returns a variant map of the given \a plugin. */ -QVariantMap JsonTypes::packPlugin(DevicePlugin *plugin, const QLocale &locale) -{ - QVariantMap pluginMap; - pluginMap.insert("id", plugin->pluginId().toString()); - pluginMap.insert("name", plugin->pluginName()); - pluginMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale)); - - QVariantList params; - foreach (const ParamType ¶m, plugin->configurationDescription()) - params.append(packParamType(param, plugin->pluginId(), locale)); - - pluginMap.insert("paramTypes", params); - return pluginMap; -} - -/*! Returns a variant map of the given \a device. */ -QVariantMap JsonTypes::packDevice(Device *device) -{ - QVariantMap variant; - variant.insert("id", device->id().toString()); - variant.insert("deviceClassId", device->deviceClassId().toString()); - variant.insert("name", device->name()); - variant.insert("params", packParams(device->params())); - variant.insert("settings", packParams(device->settings())); - - if (!device->parentId().isNull()) - variant.insert("parentId", device->parentId().toString()); - - variant.insert("states", packDeviceStates(device)); - variant.insert("setupComplete", device->setupComplete()); - return variant; -} - -/*! Returns a variant map of the given \a descriptor. */ -QVariantMap JsonTypes::packDeviceDescriptor(const DeviceDescriptor &descriptor) -{ - QVariantMap variant; - variant.insert("id", descriptor.id().toString()); - variant.insert("deviceId", descriptor.deviceId().toString()); - variant.insert("title", descriptor.title()); - variant.insert("description", descriptor.description()); - QVariantList params; - foreach (const Param ¶m, descriptor.params()) { - params.append(packParam(param)); - } - variant.insert("deviceParams", params); - return variant; -} - -/*! Returns a variant map of the given \a rule. */ -QVariantMap JsonTypes::packRule(const Rule &rule) -{ - QVariantMap ruleMap; - ruleMap.insert("id", rule.id().toString()); - ruleMap.insert("name", rule.name()); - ruleMap.insert("enabled", rule.enabled()); - ruleMap.insert("active", rule.active()); - ruleMap.insert("executable", rule.executable()); - ruleMap.insert("timeDescriptor", JsonTypes::packTimeDescriptor(rule.timeDescriptor())); - - QVariantList eventDescriptorList; - foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) - eventDescriptorList.append(JsonTypes::packEventDescriptor(eventDescriptor)); - - ruleMap.insert("eventDescriptors", eventDescriptorList); - ruleMap.insert("stateEvaluator", JsonTypes::packStateEvaluator(rule.stateEvaluator())); - - QVariantList actionList; - foreach (const RuleAction &action, rule.actions()) - actionList.append(JsonTypes::packRuleAction(action)); - - ruleMap.insert("actions", actionList); - - QVariantList exitActionList; - foreach (const RuleAction &action, rule.exitActions()) - exitActionList.append(JsonTypes::packRuleAction(action)); - - ruleMap.insert("exitActions", exitActionList); - return ruleMap; -} - -/*! Returns a variant map of the given \a rules. */ -QVariantList JsonTypes::packRules(const QList rules) -{ - QVariantList rulesList; - foreach (const Rule &rule, rules) - rulesList.append(JsonTypes::packRule(rule)); - - return rulesList; -} - -/*! Returns a variant map of the given \a rule. */ -QVariantMap JsonTypes::packRuleDescription(const Rule &rule) -{ - QVariantMap ruleDescriptionMap; - ruleDescriptionMap.insert("id", rule.id().toString()); - ruleDescriptionMap.insert("name", rule.name()); - ruleDescriptionMap.insert("enabled", rule.enabled()); - ruleDescriptionMap.insert("active", rule.active()); - ruleDescriptionMap.insert("executable", rule.executable()); - return ruleDescriptionMap; -} - -/*! Returns a variant map of the given \a logEntry. */ -QVariantMap JsonTypes::packLogEntry(const LogEntry &logEntry) -{ - QVariantMap logEntryMap; - logEntryMap.insert("timestamp", logEntry.timestamp().toMSecsSinceEpoch()); - logEntryMap.insert("loggingLevel", s_loggingLevel.at(logEntry.level())); - logEntryMap.insert("source", s_loggingSource.at(logEntry.source())); - logEntryMap.insert("eventType", s_loggingEventType.at(logEntry.eventType())); - - if (logEntry.eventType() == Logging::LoggingEventTypeActiveChange) - logEntryMap.insert("active", logEntry.active()); - - if (logEntry.eventType() == Logging::LoggingEventTypeEnabledChange) - logEntryMap.insert("active", logEntry.active()); - - if (logEntry.level() == Logging::LoggingLevelAlert) { - switch (logEntry.source()) { - case Logging::LoggingSourceRules: - logEntryMap.insert("errorCode", s_ruleError.at(logEntry.errorCode())); - break; - case Logging::LoggingSourceActions: - case Logging::LoggingSourceEvents: - case Logging::LoggingSourceStates: - case Logging::LoggingSourceBrowserActions: - logEntryMap.insert("errorCode", s_deviceError.at(logEntry.errorCode())); - break; - case Logging::LoggingSourceSystem: - // FIXME: Update this once we support error codes for the general system - // logEntryMap.insert("errorCode", ""); - break; - } - } - - switch (logEntry.source()) { - case Logging::LoggingSourceActions: - case Logging::LoggingSourceEvents: - case Logging::LoggingSourceStates: - logEntryMap.insert("typeId", logEntry.typeId().toString()); - logEntryMap.insert("deviceId", logEntry.deviceId().toString()); - logEntryMap.insert("value", LogValueTool::convertVariantToString(logEntry.value())); - break; - case Logging::LoggingSourceSystem: - logEntryMap.insert("active", logEntry.active()); - break; - case Logging::LoggingSourceRules: - logEntryMap.insert("typeId", logEntry.typeId().toString()); - break; - case Logging::LoggingSourceBrowserActions: - logEntryMap.insert("itemId", logEntry.value()); - break; - } - - return logEntryMap; -} - -/*! Returns a variant map of the given \a tag. */ -QVariantMap JsonTypes::packTag(const Tag &tag) -{ - QVariantMap ret; - if (!tag.deviceId().isNull()){ - ret.insert("deviceId", tag.deviceId().toString()); - } else { - ret.insert("ruleId", tag.ruleId().toString()); - } - ret.insert("appId", tag.appId()); - ret.insert("tagId", tag.tagId()); - ret.insert("value", tag.value()); - return ret; -} - -/*! Returns a variant list of the given \a createMethods. */ -QVariantList JsonTypes::packCreateMethods(DeviceClass::CreateMethods createMethods) -{ - QVariantList ret; - if (createMethods.testFlag(DeviceClass::CreateMethodUser)) - ret << "CreateMethodUser"; - - if (createMethods.testFlag(DeviceClass::CreateMethodAuto)) - ret << "CreateMethodAuto"; - - if (createMethods.testFlag(DeviceClass::CreateMethodDiscovery)) - ret << "CreateMethodDiscovery"; - - return ret; -} - -/*! Returns a variant map of the given \a option. */ -QVariantMap JsonTypes::packRepeatingOption(const RepeatingOption &option) -{ - QVariantMap optionVariant; - optionVariant.insert("mode", s_repeatingMode.at(option.mode())); - if (!option.weekDays().isEmpty()) { - QVariantList weekDaysVariantList; - foreach (const int& weekDay, option.weekDays()) - weekDaysVariantList.append(QVariant(weekDay)); - - optionVariant.insert("weekDays", weekDaysVariantList); - } - - if (!option.monthDays().isEmpty()) { - QVariantList monthDaysVariantList; - foreach (const int& monthDay, option.monthDays()) - monthDaysVariantList.append(QVariant(monthDay)); - - optionVariant.insert("monthDays", monthDaysVariantList); - } - return optionVariant; -} - -/*! Returns a variant map of the given \a calendarItem. */ -QVariantMap JsonTypes::packCalendarItem(const CalendarItem &calendarItem) -{ - QVariantMap calendarItemVariant; - calendarItemVariant.insert("duration", calendarItem.duration()); - - if (!calendarItem.dateTime().isNull() && calendarItem.dateTime().toTime_t() != 0) - calendarItemVariant.insert("datetime", calendarItem.dateTime().toTime_t()); - - if (!calendarItem.startTime().isNull()) - calendarItemVariant.insert("startTime", calendarItem.startTime().toString("hh:mm")); - - if (!calendarItem.repeatingOption().isEmtpy()) - calendarItemVariant.insert("repeating", packRepeatingOption(calendarItem.repeatingOption())); - - return calendarItemVariant; -} - -/*! Returns a variant map of the given \a timeEventItem. */ -QVariantMap JsonTypes::packTimeEventItem(const TimeEventItem &timeEventItem) -{ - QVariantMap timeEventItemVariant; - - if (!timeEventItem.dateTime().isNull() && timeEventItem.dateTime().toTime_t() != 0) - timeEventItemVariant.insert("datetime", timeEventItem.dateTime().toTime_t()); - - if (!timeEventItem.time().isNull()) - timeEventItemVariant.insert("time", timeEventItem.time().toString("hh:mm")); - - if (!timeEventItem.repeatingOption().isEmtpy()) - timeEventItemVariant.insert("repeating", packRepeatingOption(timeEventItem.repeatingOption())); - - return timeEventItemVariant; -} - -/*! Returns a variant map of the given \a timeDescriptor. */ -QVariantMap JsonTypes::packTimeDescriptor(const TimeDescriptor &timeDescriptor) -{ - QVariantMap timeDescriptorVariant; - - if (!timeDescriptor.calendarItems().isEmpty()) { - QVariantList calendarItems; - foreach (const CalendarItem &calendarItem, timeDescriptor.calendarItems()) - calendarItems.append(packCalendarItem(calendarItem)); - - timeDescriptorVariant.insert("calendarItems", calendarItems); - } - - if (!timeDescriptor.timeEventItems().isEmpty()) { - QVariantList timeEventItems; - foreach (const TimeEventItem &timeEventItem, timeDescriptor.timeEventItems()) - timeEventItems.append(packTimeEventItem(timeEventItem)); - - timeDescriptorVariant.insert("timeEventItems", timeEventItems); - } - - return timeDescriptorVariant; -} - -/*! Returns a variant map of the given \a wirelessAccessPoint. */ -QVariantMap JsonTypes::packWirelessAccessPoint(WirelessAccessPoint *wirelessAccessPoint) -{ - QVariantMap wirelessAccessPointVariant; - wirelessAccessPointVariant.insert("ssid", wirelessAccessPoint->ssid()); - wirelessAccessPointVariant.insert("macAddress", wirelessAccessPoint->macAddress()); - wirelessAccessPointVariant.insert("frequency", wirelessAccessPoint->frequency()); - wirelessAccessPointVariant.insert("signalStrength", wirelessAccessPoint->signalStrength()); - wirelessAccessPointVariant.insert("protected", wirelessAccessPoint->isProtected()); - return wirelessAccessPointVariant; -} - -/*! Returns a variant map of the given \a networkDevice. */ -QVariantMap JsonTypes::packWiredNetworkDevice(WiredNetworkDevice *networkDevice) -{ - QVariantMap networkDeviceVariant; - networkDeviceVariant.insert("interface", networkDevice->interface()); - networkDeviceVariant.insert("macAddress", networkDevice->macAddress()); - networkDeviceVariant.insert("state", networkDevice->deviceStateString()); - networkDeviceVariant.insert("bitRate", QString("%1 [Mb/s]").arg(QString::number(networkDevice->bitRate()))); - networkDeviceVariant.insert("pluggedIn", networkDevice->pluggedIn()); - return networkDeviceVariant; -} - -/*! Returns a variant map of the given \a networkDevice. */ -QVariantMap JsonTypes::packWirelessNetworkDevice(WirelessNetworkDevice *networkDevice) -{ - QVariantMap networkDeviceVariant; - networkDeviceVariant.insert("interface", networkDevice->interface()); - networkDeviceVariant.insert("macAddress", networkDevice->macAddress()); - networkDeviceVariant.insert("state", networkDevice->deviceStateString()); - networkDeviceVariant.insert("bitRate", QString("%1 [Mb/s]").arg(QString::number(networkDevice->bitRate()))); - if (networkDevice->activeAccessPoint()) - networkDeviceVariant.insert("currentAccessPoint", JsonTypes::packWirelessAccessPoint(networkDevice->activeAccessPoint())); - - return networkDeviceVariant; -} - -/*! Returns a variant list of the supported vendors. */ -QVariantList JsonTypes::packSupportedVendors(const QLocale &locale) -{ - QVariantList supportedVendors; - foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) - supportedVendors.append(packVendor(vendor, locale)); - - return supportedVendors; -} - -/*! Returns a variant list of the supported devices with the given \a vendorId. */ -QVariantList JsonTypes::packSupportedDevices(const VendorId &vendorId, const QLocale &locale) -{ - QVariantList supportedDeviceList; - foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) - supportedDeviceList.append(packDeviceClass(deviceClass, locale)); - - return supportedDeviceList; -} - -/*! Returns a variant list of configured devices. */ -QVariantList JsonTypes::packConfiguredDevices() -{ - QVariantList configuredDeviceList; - foreach (Device *device, NymeaCore::instance()->deviceManager()->configuredDevices()) - configuredDeviceList.append(packDevice(device)); - - return configuredDeviceList; -} - -/*! Returns a variant list of States from the given \a device. */ -QVariantList JsonTypes::packDeviceStates(Device *device) -{ - DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId()); - QVariantList stateValues; - foreach (const StateType &stateType, deviceClass.stateTypes()) { - QVariantMap stateValue; - stateValue.insert("stateTypeId", stateType.id().toString()); - stateValue.insert("value", device->stateValue(stateType.id())); - stateValues.append(stateValue); - } - return stateValues; -} - -/*! Returns a variant list of the given \a deviceDescriptors. */ -QVariantList JsonTypes::packDeviceDescriptors(const QList deviceDescriptors) -{ - QVariantList deviceDescriptorList; - foreach (const DeviceDescriptor &deviceDescriptor, deviceDescriptors) - deviceDescriptorList.append(JsonTypes::packDeviceDescriptor(deviceDescriptor)); - - return deviceDescriptorList; -} - -QVariantList JsonTypes::packBrowserItems(const BrowserItems &items) -{ - QVariantList ret; - foreach (const BrowserItem &item, items) { - ret.append(packBrowserItem(item)); - } - return ret; -} - -/*! Returns a variant map with the current basic configuration of the server. */ -QVariantMap JsonTypes::packBasicConfiguration() -{ - QVariantMap basicConfiguration; - basicConfiguration.insert("serverName", NymeaCore::instance()->configuration()->serverName()); - basicConfiguration.insert("serverUuid", NymeaCore::instance()->configuration()->serverUuid().toString()); - basicConfiguration.insert("serverTime", NymeaCore::instance()->timeManager()->currentDateTime().toTime_t()); - basicConfiguration.insert("timeZone", QString::fromUtf8(NymeaCore::instance()->timeManager()->timeZone())); - basicConfiguration.insert("language", NymeaCore::instance()->configuration()->locale().name()); - basicConfiguration.insert("debugServerEnabled", NymeaCore::instance()->configuration()->debugServerEnabled()); - return basicConfiguration; -} - -QVariantMap JsonTypes::packServerConfiguration(const ServerConfiguration &config) -{ - QVariantMap serverConfiguration; - serverConfiguration.insert("id", config.id); - serverConfiguration.insert("address", config.address.toString()); - serverConfiguration.insert("port", config.port); - serverConfiguration.insert("sslEnabled", config.sslEnabled); - serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled); - return serverConfiguration; -} - -QVariantMap JsonTypes::packWebServerConfiguration(const WebServerConfiguration &config) -{ - QVariantMap webServerConfiguration = packServerConfiguration(config); - webServerConfiguration.insert("publicFolder", config.publicFolder); - return webServerConfiguration; -} - -QVariantMap JsonTypes::packMqttPolicy(const MqttPolicy &policy) -{ - QVariantMap policyMap; - policyMap.insert("clientId", policy.clientId); - policyMap.insert("username", policy.username); - policyMap.insert("password", policy.password); - policyMap.insert("allowedPublishTopicFilters", policy.allowedPublishTopicFilters); - policyMap.insert("allowedSubscribeTopicFilters", policy.allowedSubscribeTopicFilters); - return policyMap; -} - -/*! Returns a variant list containing all rule descriptions. */ -QVariantList JsonTypes::packRuleDescriptions() -{ - QVariantList rulesList; - foreach (const Rule &rule, NymeaCore::instance()->ruleEngine()->rules()) - rulesList.append(JsonTypes::packRuleDescription(rule)); - - return rulesList; -} - -/*! Returns a variant list of the given \a rules. */ -QVariantList JsonTypes::packRuleDescriptions(const QList &rules) -{ - QVariantList rulesList; - foreach (const Rule &rule, rules) - rulesList.append(JsonTypes::packRuleDescription(rule)); - - return rulesList; -} - -/*! Returns a variant list of action types for the given \a deviceClass. */ -QVariantList JsonTypes::packActionTypes(const DeviceClass &deviceClass, const QLocale &locale) -{ - QVariantList actionTypes; - foreach (const ActionType &actionType, deviceClass.actionTypes()) - actionTypes.append(JsonTypes::packActionType(actionType, deviceClass.pluginId(), locale)); - - return actionTypes; -} - -/*! Returns a variant list of state types for the given \a deviceClass. */ -QVariantList JsonTypes::packStateTypes(const DeviceClass &deviceClass, const QLocale &locale) -{ - QVariantList stateTypes; - foreach (const StateType &stateType, deviceClass.stateTypes()) - stateTypes.append(JsonTypes::packStateType(stateType, deviceClass.pluginId(), locale)); - - return stateTypes; -} - -/*! Returns a variant list of event types for the given \a deviceClass. */ -QVariantList JsonTypes::packEventTypes(const DeviceClass &deviceClass, const QLocale &locale) -{ - QVariantList eventTypes; - foreach (const EventType &eventType, deviceClass.eventTypes()) - eventTypes.append(JsonTypes::packEventType(eventType, deviceClass.pluginId(), locale)); - - return eventTypes; -} - -/*! Returns a variant list containing all plugins. */ -QVariantList JsonTypes::packPlugins(const QLocale &locale) -{ - QVariantList pluginsList; - foreach (DevicePlugin *plugin, NymeaCore::instance()->deviceManager()->plugins()) { - QVariantMap pluginMap = packPlugin(plugin, locale); - pluginsList.append(pluginMap); - } - return pluginsList; -} - -QVariantMap JsonTypes::packTokenInfo(const TokenInfo &tokenInfo) -{ - QVariantMap ret; - ret.insert("id", tokenInfo.id().toString()); - ret.insert("userName", tokenInfo.username()); - ret.insert("deviceName", tokenInfo.deviceName()); - ret.insert("creationTime", tokenInfo.creationTime().toTime_t()); - return ret; -} - -QVariantMap JsonTypes::packPackage(const Package &package) -{ - QVariantMap ret; - ret.insert("id", package.packageId()); - ret.insert("displayName", package.displayName()); - ret.insert("summary", package.summary()); - ret.insert("installedVersion", package.installedVersion()); - ret.insert("candidateVersion", package.candidateVersion()); - ret.insert("changelog", package.changelog()); - ret.insert("updateAvailable", package.updateAvailable()); - ret.insert("rollbackAvailable", package.rollbackAvailable()); - ret.insert("canRemove", package.canRemove()); - return ret; -} - -QVariantMap JsonTypes::packRepository(const Repository &repository) -{ - QVariantMap ret; - ret.insert("id", repository.id()); - ret.insert("displayName", repository.displayName()); - ret.insert("enabled", repository.enabled()); - return ret; -} - -/*! Returns the type string for the given \a type. */ -QString JsonTypes::basicTypeToString(const QVariant::Type &type) -{ - switch (type) { - case QVariant::Uuid: - return "Uuid"; - case QVariant::String: - return "String"; - case QVariant::StringList: - return "StringList"; - case QVariant::Int: - return "Int"; - case QVariant::UInt: - return "Uint"; - case QVariant::Double: - return "Double"; - case QVariant::Bool: - return "Bool"; - case QVariant::Color: - return "Color"; - case QVariant::Time: - return "Time"; - default: - return QVariant::typeToName(static_cast(type)); - } -} - -/*! Returns a \l{Param} created from the given \a paramMap. */ -Param JsonTypes::unpackParam(const QVariantMap ¶mMap) -{ - if (paramMap.keys().count() == 0) - return Param(); - - ParamTypeId paramTypeId = paramMap.value("paramTypeId").toString(); - QVariant value = paramMap.value("value"); - return Param(paramTypeId, value); -} - -/*! Returns a \l{ParamList} created from the given \a paramList. */ -ParamList JsonTypes::unpackParams(const QVariantList ¶mList) -{ - ParamList params; - foreach (const QVariant ¶mVariant, paramList) - params.append(unpackParam(paramVariant.toMap())); - - return params; -} - -/*! Returns a \l{Rule} created from the given \a ruleMap. */ -Rule JsonTypes::unpackRule(const QVariantMap &ruleMap) -{ - // The rule id will only be valid if unpacking for edit - RuleId ruleId = RuleId(ruleMap.value("ruleId").toString()); - - QString name = ruleMap.value("name", QString()).toString(); - - // By default enabled - bool enabled = ruleMap.value("enabled", true).toBool(); - - // By default executable - bool executable = ruleMap.value("executable", true).toBool(); - - StateEvaluator stateEvaluator = JsonTypes::unpackStateEvaluator(ruleMap.value("stateEvaluator").toMap()); - TimeDescriptor timeDescriptor = JsonTypes::unpackTimeDescriptor(ruleMap.value("timeDescriptor").toMap()); - - QList eventDescriptors; - if (ruleMap.contains("eventDescriptors")) { - QVariantList eventDescriptorVariantList = ruleMap.value("eventDescriptors").toList(); - foreach (const QVariant &eventDescriptorVariant, eventDescriptorVariantList) { - eventDescriptors.append(JsonTypes::unpackEventDescriptor(eventDescriptorVariant.toMap())); - } - } - - QList actions; - if (ruleMap.contains("actions")) { - QVariantList actionsVariantList = ruleMap.value("actions").toList(); - foreach (const QVariant &actionVariant, actionsVariantList) { - actions.append(JsonTypes::unpackRuleAction(actionVariant.toMap())); - } - } - - QList exitActions; - if (ruleMap.contains("exitActions")) { - QVariantList exitActionsVariantList = ruleMap.value("exitActions").toList(); - foreach (const QVariant &exitActionVariant, exitActionsVariantList) { - exitActions.append(JsonTypes::unpackRuleAction(exitActionVariant.toMap())); - } - } - - Rule rule; - rule.setId(ruleId); - rule.setName(name); - rule.setTimeDescriptor(timeDescriptor); - rule.setStateEvaluator(stateEvaluator); - rule.setEventDescriptors(eventDescriptors); - rule.setActions(actions); - rule.setExitActions(exitActions); - rule.setEnabled(enabled); - rule.setExecutable(executable); - return rule; -} - -/*! Returns a \l{RuleAction} created from the given \a ruleActionMap. */ -RuleAction JsonTypes::unpackRuleAction(const QVariantMap &ruleActionMap) -{ - ActionTypeId actionTypeId(ruleActionMap.value("actionTypeId").toString()); - DeviceId actionDeviceId(ruleActionMap.value("deviceId").toString()); - QString interface = ruleActionMap.value("interface").toString(); - QString interfaceAction = ruleActionMap.value("interfaceAction").toString(); - QString browserItemId = ruleActionMap.value("browserItemId").toString(); - RuleActionParamList actionParamList = JsonTypes::unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList()); - - if (!actionDeviceId.isNull() && !actionTypeId.isNull()) { - return RuleAction(actionTypeId, actionDeviceId, actionParamList); - } else if (!actionDeviceId.isNull() && !browserItemId.isNull()) { - return RuleAction(actionDeviceId, browserItemId); - } - return RuleAction(interface, interfaceAction, actionParamList); -} - -/*! Returns a \l{RuleActionParam} created from the given \a ruleActionParamMap. */ -RuleActionParam JsonTypes::unpackRuleActionParam(const QVariantMap &ruleActionParamMap) -{ - if (ruleActionParamMap.keys().count() == 0) - return RuleActionParam(); - - ParamTypeId paramTypeId = ParamTypeId(ruleActionParamMap.value("paramTypeId").toString()); - QString paramName = ruleActionParamMap.value("paramName").toString(); - - RuleActionParam param; - if (paramTypeId.isNull()) { - param = RuleActionParam(paramName); - } else { - param = RuleActionParam(paramTypeId); - } - param.setValue(ruleActionParamMap.value("value")); - param.setEventTypeId(EventTypeId(ruleActionParamMap.value("eventTypeId").toString())); - param.setEventParamTypeId(ParamTypeId(ruleActionParamMap.value("eventParamTypeId").toString())); - param.setStateDeviceId(DeviceId(ruleActionParamMap.value("stateDeviceId").toString())); - param.setStateTypeId(StateTypeId(ruleActionParamMap.value("stateTypeId").toString())); - return param; -} - -/*! Returns a \l{RuleActionParamList} created from the given \a ruleActionParamList. */ -RuleActionParamList JsonTypes::unpackRuleActionParams(const QVariantList &ruleActionParamList) -{ - RuleActionParamList ruleActionParams; - foreach (const QVariant ¶mVariant, ruleActionParamList) - ruleActionParams.append(unpackRuleActionParam(paramVariant.toMap())); - - return ruleActionParams; -} - -/*! Returns a \l{ParamDescriptor} created from the given \a paramMap. */ -ParamDescriptor JsonTypes::unpackParamDescriptor(const QVariantMap ¶mMap) -{ - QString operatorString = paramMap.value("operator").toString(); - QMetaObject metaObject = Types::staticMetaObject; - int enumIndex = metaObject.indexOfEnumerator("ValueOperator"); - QMetaEnum metaEnum = metaObject.enumerator(enumIndex); - Types::ValueOperator valueOperator = static_cast(metaEnum.keyToValue(operatorString.toLatin1().data())); - - if (paramMap.contains("paramTypeId")) { - ParamDescriptor param = ParamDescriptor(ParamTypeId(paramMap.value("paramTypeId").toString()), paramMap.value("value")); - param.setOperatorType(valueOperator); - return param; - } - ParamDescriptor param = ParamDescriptor(paramMap.value("paramName").toString(), paramMap.value("value")); - param.setOperatorType(valueOperator); - return param; -} - -/*! Returns a list of \l{ParamDescriptor} created from the given \a paramList. */ -QList JsonTypes::unpackParamDescriptors(const QVariantList ¶mList) -{ - QList params; - foreach (const QVariant ¶mVariant, paramList) - params.append(unpackParamDescriptor(paramVariant.toMap())); - - return params; -} - -/*! Returns a \l{EventDescriptor} created from the given \a eventDescriptorMap. */ -EventDescriptor JsonTypes::unpackEventDescriptor(const QVariantMap &eventDescriptorMap) -{ - EventTypeId eventTypeId(eventDescriptorMap.value("eventTypeId").toString()); - DeviceId eventDeviceId(eventDescriptorMap.value("deviceId").toString()); - QString interface = eventDescriptorMap.value("interface").toString(); - QString interfaceEvent = eventDescriptorMap.value("interfaceEvent").toString(); - QList eventParams = JsonTypes::unpackParamDescriptors(eventDescriptorMap.value("paramDescriptors").toList()); - if (!eventDeviceId.isNull() && !eventTypeId.isNull()) { - return EventDescriptor(eventTypeId, eventDeviceId, eventParams); - } - return EventDescriptor(interface, interfaceEvent, eventParams); -} - -/*! Returns a \l{StateEvaluator} created from the given \a stateEvaluatorMap. */ -StateEvaluator JsonTypes::unpackStateEvaluator(const QVariantMap &stateEvaluatorMap) -{ - StateEvaluator ret(unpackStateDescriptor(stateEvaluatorMap.value("stateDescriptor").toMap())); - if (stateEvaluatorMap.contains("operator")) { - ret.setOperatorType(static_cast(s_stateOperator.indexOf(stateEvaluatorMap.value("operator").toString()))); - } else { - ret.setOperatorType(Types::StateOperatorAnd); - } - - QList childEvaluators; - foreach (const QVariant &childEvaluator, stateEvaluatorMap.value("childEvaluators").toList()) - childEvaluators.append(unpackStateEvaluator(childEvaluator.toMap())); - - ret.setChildEvaluators(childEvaluators); - return ret; -} - -/*! Returns a \l{StateDescriptor} created from the given \a stateDescriptorMap. */ -StateDescriptor JsonTypes::unpackStateDescriptor(const QVariantMap &stateDescriptorMap) -{ - StateTypeId stateTypeId(stateDescriptorMap.value("stateTypeId").toString()); - DeviceId deviceId(stateDescriptorMap.value("deviceId").toString()); - QString interface(stateDescriptorMap.value("interface").toString()); - QString interfaceState(stateDescriptorMap.value("interfaceState").toString()); - QVariant value = stateDescriptorMap.value("value"); - Types::ValueOperator operatorType = static_cast(s_valueOperator.indexOf(stateDescriptorMap.value("operator").toString())); - if (!deviceId.isNull() && !stateTypeId.isNull()) { - StateDescriptor stateDescriptor(stateTypeId, deviceId, value, operatorType); - return stateDescriptor; - } - StateDescriptor stateDescriptor(interface, interfaceState, value, operatorType); - return stateDescriptor; -} - -/*! Returns a \l{LogFilter} created from the given \a logFilterMap. */ -LogFilter JsonTypes::unpackLogFilter(const QVariantMap &logFilterMap) -{ - LogFilter filter; - if (logFilterMap.contains("timeFilters")) { - QVariantList timeFilters = logFilterMap.value("timeFilters").toList(); - foreach (const QVariant &timeFilter, timeFilters) { - QVariantMap timeFilterMap = timeFilter.toMap(); - QDateTime startDate; QDateTime endDate; - if (timeFilterMap.contains("startDate")) - startDate = QDateTime::fromTime_t(timeFilterMap.value("startDate").toUInt()); - - if (timeFilterMap.contains("endDate")) - endDate = QDateTime::fromTime_t(timeFilterMap.value("endDate").toUInt()); - - filter.addTimeFilter(startDate, endDate); - } - } - - if (logFilterMap.contains("loggingSources")) { - QVariantList loggingSources = logFilterMap.value("loggingSources").toList(); - foreach (const QVariant &source, loggingSources) { - filter.addLoggingSource(static_cast(s_loggingSource.indexOf(source.toString()))); - } - } - if (logFilterMap.contains("loggingLevels")) { - QVariantList loggingLevels = logFilterMap.value("loggingLevels").toList(); - foreach (const QVariant &level, loggingLevels) { - filter.addLoggingLevel(static_cast(s_loggingLevel.indexOf(level.toString()))); - } - } - if (logFilterMap.contains("eventTypes")) { - QVariantList eventTypes = logFilterMap.value("eventTypes").toList(); - foreach (const QVariant &eventType, eventTypes) { - filter.addLoggingEventType(static_cast(s_loggingEventType.indexOf(eventType.toString()))); - } - } - if (logFilterMap.contains("typeIds")) { - QVariantList typeIds = logFilterMap.value("typeIds").toList(); - foreach (const QVariant &typeId, typeIds) { - filter.addTypeId(typeId.toUuid()); - } - } - if (logFilterMap.contains("deviceIds")) { - QVariantList deviceIds = logFilterMap.value("deviceIds").toList(); - foreach (const QVariant &deviceId, deviceIds) { - filter.addDeviceId(DeviceId(deviceId.toString())); - } - } - if (logFilterMap.contains("values")) { - QVariantList values = logFilterMap.value("values").toList(); - foreach (const QVariant &value, values) { - filter.addValue(value.toString()); - } - } - if (logFilterMap.contains("limit")) { - filter.setLimit(logFilterMap.value("limit", -1).toInt()); - } - if (logFilterMap.contains("offset")) { - filter.setOffset(logFilterMap.value("offset").toInt()); - } - - return filter; -} - -/*! Returns a \l{RepeatingOption} created from the given \a repeatingOptionMap. */ -RepeatingOption JsonTypes::unpackRepeatingOption(const QVariantMap &repeatingOptionMap) -{ - RepeatingOption::RepeatingMode mode = static_cast(s_repeatingMode.indexOf(repeatingOptionMap.value("mode").toString())); - - QList weekDays; - if (repeatingOptionMap.contains("weekDays")) { - foreach (const QVariant weekDayVariant, repeatingOptionMap.value("weekDays").toList()) { - weekDays.append(weekDayVariant.toInt()); - } - } - - QList monthDays; - if (repeatingOptionMap.contains("monthDays")) { - foreach (const QVariant monthDayVariant, repeatingOptionMap.value("monthDays").toList()) { - monthDays.append(monthDayVariant.toInt()); - } - } - - return RepeatingOption(mode, weekDays, monthDays); -} - -/*! Returns a \l{CalendarItem} created from the given \a calendarItemMap. */ -CalendarItem JsonTypes::unpackCalendarItem(const QVariantMap &calendarItemMap) -{ - CalendarItem calendarItem; - calendarItem.setDuration(calendarItemMap.value("duration").toUInt()); - - if (calendarItemMap.contains("datetime")) - calendarItem.setDateTime(QDateTime::fromTime_t(calendarItemMap.value("datetime").toUInt())); - - if (calendarItemMap.contains("startTime")) - calendarItem.setStartTime(QTime::fromString(calendarItemMap.value("startTime").toString(), "hh:mm")); - - if (calendarItemMap.contains("repeating")) - calendarItem.setRepeatingOption(unpackRepeatingOption(calendarItemMap.value("repeating").toMap())); - - return calendarItem; -} - -/*! Returns a \l{TimeEventItem} created from the given \a timeEventItemMap. */ -TimeEventItem JsonTypes::unpackTimeEventItem(const QVariantMap &timeEventItemMap) -{ - TimeEventItem timeEventItem; - - if (timeEventItemMap.contains("datetime")) - timeEventItem.setDateTime(timeEventItemMap.value("datetime").toUInt()); - - if (timeEventItemMap.contains("time")) - timeEventItem.setTime(timeEventItemMap.value("time").toTime()); - - if (timeEventItemMap.contains("repeating")) - timeEventItem.setRepeatingOption(unpackRepeatingOption(timeEventItemMap.value("repeating").toMap())); - - return timeEventItem; -} - -/*! Returns a \l{TimeDescriptor} created from the given \a timeDescriptorMap. */ -TimeDescriptor JsonTypes::unpackTimeDescriptor(const QVariantMap &timeDescriptorMap) -{ - TimeDescriptor timeDescriptor; - - if (timeDescriptorMap.contains("calendarItems")) { - QList calendarItems; - foreach (const QVariant &calendarItemValiant, timeDescriptorMap.value("calendarItems").toList()) { - calendarItems.append(unpackCalendarItem(calendarItemValiant.toMap())); - } - timeDescriptor.setCalendarItems(calendarItems); - } - - if (timeDescriptorMap.contains("timeEventItems")) { - QList timeEventItems; - foreach (const QVariant &timeEventItemValiant, timeDescriptorMap.value("timeEventItems").toList()) { - timeEventItems.append(unpackTimeEventItem(timeEventItemValiant.toMap())); - } - timeDescriptor.setTimeEventItems(timeEventItems); - } - - return timeDescriptor; -} - -/*! Returns a \l{Tag} created from the given \a tagMap. */ -Tag JsonTypes::unpackTag(const QVariantMap &tagMap) -{ - DeviceId deviceId = DeviceId(tagMap.value("deviceId").toString()); - RuleId ruleId = RuleId(tagMap.value("ruleId").toString()); - QString appId = tagMap.value("appId").toString(); - QString tagId = tagMap.value("tagId").toString(); - QString value = tagMap.value("value").toString(); - if (!deviceId.isNull()) { - return Tag(deviceId, appId, tagId, value); - } - return Tag(ruleId, appId, tagId, value); -} - -ServerConfiguration JsonTypes::unpackServerConfiguration(const QVariantMap &serverConfigurationMap) -{ - ServerConfiguration serverConfiguration; - serverConfiguration.id = serverConfigurationMap.value("id").toString(); - serverConfiguration.address = QHostAddress(serverConfigurationMap.value("address").toString()); - serverConfiguration.port = serverConfigurationMap.value("port").toUInt(); - serverConfiguration.sslEnabled = serverConfigurationMap.value("sslEnabled", true).toBool(); - serverConfiguration.authenticationEnabled = serverConfigurationMap.value("authenticationEnabled", true).toBool(); - return serverConfiguration; -} - -WebServerConfiguration JsonTypes::unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap) -{ - ServerConfiguration tmp = unpackServerConfiguration(webServerConfigurationMap); - WebServerConfiguration webServerConfiguration; - webServerConfiguration.id = tmp.id; - webServerConfiguration.address = tmp.address; - webServerConfiguration.port = tmp.port; - webServerConfiguration.sslEnabled = tmp.sslEnabled; - webServerConfiguration.authenticationEnabled = tmp.authenticationEnabled; - webServerConfiguration.publicFolder = webServerConfigurationMap.value("publicFolder").toString(); - return webServerConfiguration; -} - -MqttPolicy JsonTypes::unpackMqttPolicy(const QVariantMap &mqttPolicyMap) -{ - MqttPolicy policy; - policy.clientId = mqttPolicyMap.value("clientId").toString(); - policy.username = mqttPolicyMap.value("username").toString(); - policy.password = mqttPolicyMap.value("password").toString(); - policy.allowedPublishTopicFilters = mqttPolicyMap.value("allowedPublishTopicFilters").toStringList(); - policy.allowedSubscribeTopicFilters = mqttPolicyMap.value("allowedSubscribeTopicFilters").toStringList(); - return policy; -} - -/*! Compairs the given \a map with the given \a templateMap. Returns the error string and false if - the params are not valid. */ -QPair JsonTypes::validateMap(const QVariantMap &templateMap, const QVariantMap &map) -{ - s_lastError.clear(); - - // Make sure all values defined in the template are around - foreach (const QString &key, templateMap.keys()) { - QString strippedKey = key; - strippedKey.remove(QRegExp("^o:")); - if (!key.startsWith("o:") && !map.contains(strippedKey)) { - qCWarning(dcJsonRpc) << "*** missing key" << key; - qCWarning(dcJsonRpc) << "Expected: " << templateMap; - qCWarning(dcJsonRpc) << "Got: " << map; - QJsonDocument jsonDoc = QJsonDocument::fromVariant(map); - return report(false, QString("Missing key %1 in %2").arg(key).arg(QString(jsonDoc.toJson(QJsonDocument::Compact)))); - } - if (map.contains(strippedKey)) { - QPair result = validateVariant(templateMap.value(key), map.value(strippedKey)); - if (!result.first) { - QJsonDocument templateDoc = QJsonDocument::fromVariant(templateMap.value(key)); - QJsonDocument mapDoc = QJsonDocument::fromVariant(map.value(strippedKey)); - qCWarning(dcJsonRpc).nospace() << "Object\n" << qUtf8Printable(mapDoc.toJson(QJsonDocument::Indented)) << "not matching template\n" << qUtf8Printable(templateDoc.toJson(QJsonDocument::Indented)); - return result; - } - } - } - - // Make sure there aren't any other parameters than the allowed ones - foreach (const QString &key, map.keys()) { - QString optKey = "o:" + key; - - if (!templateMap.contains(key) && !templateMap.contains(optKey)) { - qCWarning(dcJsonRpc) << "Forbidden param" << key << "in params"; - QJsonDocument jsonDoc = QJsonDocument::fromVariant(map); - return report(false, QString("Forbidden key \"%1\" in %2").arg(key).arg(QString(jsonDoc.toJson(QJsonDocument::Compact)))); - } - } - - return report(true, ""); -} - -/*! Compairs the given \a value with the given \a templateValue. Returns the error string and false if - the params are not valid. */ -QPair JsonTypes::validateProperty(const QVariant &templateValue, const QVariant &value) -{ - QString strippedTemplateValue = templateValue.toString(); - - if (strippedTemplateValue == JsonTypes::basicTypeToString(JsonTypes::Variant)) { - return report(true, ""); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::Uuid)) { - QString errorString = QString("Param %1 is not a uuid.").arg(value.toString()); - return report(value.canConvert(QVariant::Uuid), errorString); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::String)) { - QString errorString = QString("Param %1 is not a string.").arg(value.toString()); - return report(value.canConvert(QVariant::String), errorString); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::StringList)) { - QString errorString = QString("Param %1 is not a string list.").arg(value.toString()); - return report(value.canConvert(QVariant::StringList), errorString); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::Bool)) { - QString errorString = QString("Param %1 is not a bool.").arg(value.toString()); - return report(value.canConvert(QVariant::Bool), errorString); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::Int)) { - QString errorString = QString("Param %1 is not a int.").arg(value.toString()); - return report(value.canConvert(QVariant::Int), errorString); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::UInt)) { - QString errorString = QString("Param %1 is not a uint.").arg(value.toString()); - return report(value.canConvert(QVariant::UInt), errorString); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::Double)) { - QString errorString = QString("Param %1 is not a double.").arg(value.toString()); - return report(value.canConvert(QVariant::Double), errorString); - } - if (strippedTemplateValue == JsonTypes::basicTypeToString(QVariant::Time)) { - QString errorString = QString("Param %1 is not a time (hh:mm).").arg(value.toString()); - return report(value.canConvert(QVariant::Time), errorString); - } - - qCWarning(dcJsonRpc) << QString("Unhandled property type: %1 (expected: %2)").arg(value.toString()).arg(strippedTemplateValue); - QString errorString = QString("Unhandled property type: %1 (expected: %2)").arg(value.toString()).arg(strippedTemplateValue); - return report(false, errorString); -} - -/*! Compairs the given \a list with the given \a templateList. Returns the error string and false if - the params are not valid. */ -QPair JsonTypes::validateList(const QVariantList &templateList, const QVariantList &list) -{ - Q_ASSERT(templateList.count() == 1); - QVariant entryTemplate = templateList.first(); - - for (int i = 0; i < list.count(); ++i) { - QVariant listEntry = list.at(i); - QPair result = validateVariant(entryTemplate, listEntry); - if (!result.first) { - qCWarning(dcJsonRpc) << "List entry not matching template"; - return result; - } - } - return report(true, ""); -} - -/*! Compairs the given \a variant with the given \a templateVariant. Returns the error string and false if - the params are not valid. */ -QPair JsonTypes::validateVariant(const QVariant &templateVariant, const QVariant &variant) -{ - switch(templateVariant.type()) { - case QVariant::String: - if (templateVariant.toString().startsWith("$ref:")) { - QString refName = templateVariant.toString(); - if (refName == actionRef()) { - QPair result = validateMap(actionDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Error validating action"; - return result; - } - } else if (refName == eventRef()) { - QPair result = validateMap(eventDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Event not valid"; - return result; - } - } else if (refName == paramRef()) { - if (!variant.canConvert(QVariant::Map)) { - report(false, "Param not valid. Should be a map."); - } - } else if (refName == paramDescriptorRef()) { - QPair result = validateMap(paramDescriptorDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "ParamDescriptor not valid"; - return result; - } - } else if (refName == deviceRef()) { - QPair result = validateMap(deviceDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Device not valid"; - return result; - } - } else if (refName == deviceDescriptorRef()) { - QPair result = validateMap(deviceDescriptorDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Devicedescriptor not valid"; - return result; - } - } else if (refName == vendorRef()) { - QPair result = validateMap(vendorDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Value not allowed in" << vendorRef(); - } - } else if (refName == deviceClassRef()) { - QPair result = validateMap(deviceClassDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Device class not valid"; - return result; - } - } else if (refName == paramTypeRef()) { - QPair result = validateMap(paramTypeDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Param types not matching"; - return result; - } - } else if (refName == ruleActionRef()) { - QPair result = validateMap(ruleActionDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "RuleAction type not matching"; - return result; - } - } else if (refName == ruleActionParamRef()) { - QPair result = validateMap(ruleActionParamDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "RuleActionParam type not matching"; - return result; - } - } else if (refName == actionTypeRef()) { - QPair result = validateMap(actionTypeDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Action type not matching"; - return result; - } - } else if (refName == eventTypeRef()) { - QPair result = validateMap(eventTypeDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Event type not matching"; - return result; - } - } else if (refName == stateTypeRef()) { - QPair result = validateMap(stateTypeDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "State type not matching"; - return result; - } - } else if (refName == stateEvaluatorRef()) { - QPair result = validateMap(stateEvaluatorDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "StateEvaluator type not matching"; - return result; - } - } else if (refName == stateDescriptorRef()) { - QPair result = validateMap(stateDescriptorDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "StateDescriptor type not matching"; - return result; - } - } else if (refName == pluginRef()) { - QPair result = validateMap(pluginDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Plugin not matching"; - return result; - } - } else if (refName == ruleRef()) { - QPair result = validateMap(ruleDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Rule type not matching"; - return result; - } - } else if (refName == ruleDescriptionRef()) { - QPair result = validateMap(s_ruleDescription, variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "RuleDescription type not matching"; - return result; - } - } else if (refName == stateRef()) { - QPair result = validateMap(s_state, variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "State not matching"; - return result; - } - } else if (refName == eventDescriptorRef()) { - QPair result = validateMap(eventDescriptorDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Eventdescriptor not matching"; - return result; - } - } else if (refName == logEntryRef()) { - QPair result = validateMap(logEntryDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "LogEntry not matching"; - return result; - } - } else if (refName == timeDescriptorRef()) { - QPair result = validateMap(timeDescriptorDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "TimeDescriptor not matching"; - return result; - } - } else if (refName == calendarItemRef()) { - QPair result = validateMap(calendarItemDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "CalendarItem not matching"; - return result; - } - } else if (refName == timeDescriptorRef()) { - QPair result = validateMap(timeEventItemDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "TimeEventItem not matching"; - return result; - } - } else if (refName == repeatingOptionRef()) { - QPair result = validateMap(repeatingOptionDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "RepeatingOption not matching"; - return result; - } - } else if (refName == timeEventItemRef()) { - QPair result = validateMap(timeEventItemDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "TimeEventItem not matching"; - return result; - } - } else if (refName == wirelessAccessPointRef()) { - QPair result = validateMap(wirelessAccessPointDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "WirelessAccessPoint not matching"; - return result; - } - } else if (refName == wiredNetworkDeviceRef()) { - QPair result = validateMap(wiredNetworkDeviceDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "WiredNetworkDevice not matching"; - return result; - } - } else if (refName == wirelessNetworkDeviceRef()) { - QPair result = validateMap(wirelessNetworkDeviceDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "WirelessNetworkDevice not matching"; - return result; - } - } else if (refName == tokenInfoRef()) { - QPair result = validateMap(tokenInfoDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "TokenInfo not matching"; - return result; - } - } else if (refName == serverConfigurationRef()) { - QPair result = validateMap(serverConfigurationDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "ServerConfiguration not matching"; - return result; - } - } else if (refName == webServerConfigurationRef()) { - QPair result = validateMap(webServerConfigurationDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "WebServerConfiguration not matching"; - return result; - } - } else if (refName == mqttPolicyRef()) { - QPair result = validateMap(s_mqttPolicy, variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "MqttPolicy not matching"; - return result; - } - } else if (refName == tagRef()) { - QPair result = validateMap(tagDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Tag not matching"; - return result; - } - } else if (refName == packageRef()) { - QPair result = validateMap(packageDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Package not matching"; - return result; - } - } else if (refName == repositoryRef()) { - QPair result = validateMap(repositoryDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "Repository not matching"; - return result; - } - } else if (refName == browserItemRef()) { - QPair result = validateMap(browserItemDescription(), variant.toMap()); - if (!result.first) { - qCWarning(dcJsonRpc) << "BrowserItem not matching"; - return result; - } - } else if (refName == basicTypeRef()) { - QPair result = validateBasicType(variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(basicTypeRef()); - return result; - } - } else if (refName == stateOperatorRef()) { - QPair result = validateEnum(s_stateOperator, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(stateOperatorRef()); - return result; - } - } else if (refName == createMethodRef()) { - QPair result = validateEnum(s_createMethod, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(createMethodRef()); - return result; - } - } else if (refName == setupMethodRef()) { - QPair result = validateEnum(s_setupMethod, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(setupMethodRef()); - return result; - } - } else if (refName == valueOperatorRef()) { - QPair result = validateEnum(s_valueOperator, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(valueOperatorRef()); - return result; - } - } else if (refName == deviceErrorRef()) { - QPair result = validateEnum(s_deviceError, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(deviceErrorRef()); - return result; - } - } else if (refName == ruleErrorRef()) { - QPair result = validateEnum(s_ruleError, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(ruleErrorRef()); - return result; - } - } else if (refName == loggingErrorRef()) { - QPair result = validateEnum(s_loggingError, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(loggingErrorRef()); - return result; - } - } else if (refName == loggingSourceRef()) { - QPair result = validateEnum(s_loggingSource, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(loggingSourceRef()); - return result; - } - } else if (refName == loggingLevelRef()) { - QPair result = validateEnum(s_loggingLevel, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(loggingLevelRef()); - return result; - } - } else if (refName == loggingEventTypeRef()) { - QPair result = validateEnum(s_loggingEventType, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(loggingEventTypeRef()); - return result; - } - } else if (refName == inputTypeRef()) { - QPair result = validateEnum(s_inputType, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(inputTypeRef()); - return result; - } - } else if (refName == unitRef()) { - QPair result = validateEnum(s_unit, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(unitRef()); - return result; - } - } else if (refName == repeatingModeRef()) { - QPair result = validateEnum(s_repeatingMode, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(repeatingModeRef()); - return result; - } - } else if (refName == removePolicyRef()) { - QPair result = validateEnum(s_removePolicy, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(removePolicyRef()); - return result; - } - } else if (refName == configurationErrorRef()) { - QPair result = validateEnum(s_configurationError, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(configurationErrorRef()); - return result; - } - } else if (refName == networkManagerStateRef()) { - QPair result = validateEnum(s_networkManagerState, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(networkManagerStateRef()); - return result; - } - } else if (refName == networkManagerErrorRef()) { - QPair result = validateEnum(s_networkManagerError, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(networkManagerErrorRef()); - return result; - } - } else if (refName == networkDeviceStateRef()) { - QPair result = validateEnum(s_networkDeviceState, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(networkDeviceStateRef()); - return result; - } - } else if (refName == userErrorRef()) { - QPair result = validateEnum(s_userError, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(userErrorRef()); - return result; - } - } else if (refName == tagErrorRef()) { - QPair result = validateEnum(s_tagError, variant); - if (!result.first) { - qCWarning(dcJsonRpc()) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(tagErrorRef()); - return result; - } - } else if (refName == cloudConnectionStateRef()) { - QPair result = validateEnum(s_cloudConnectionState, variant); - if (!result.first) { - qCWarning(dcJsonRpc()) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(cloudConnectionStateRef()); - return result; - } - } else if (refName == browserIconRef()) { - QPair result = validateEnum(s_browserIcon, variant); - if (!result.first) { - qCWarning(dcJsonRpc()) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(browserIconRef()); - return result; - } - } else if (refName == mediaBrowserIconRef()) { - QPair result = validateEnum(s_mediaBrowserIcon, variant); - if (!result.first) { - qCWarning(dcJsonRpc()) << QString("Value %1 not allowed in %2").arg(variant.toString()).arg(mediaBrowserIconRef()); - return result; - } - } else if (refName == "$ref:Namespace") { - // This is quite hacky, but unless we explicitly propagate the namespace info in here we can't know. - // Let's assume jsonrpcserver handles this properly... - // Actually this entire jsontypes file should probably be split up into the handlers themselves but that's a different story. - return qMakePair(true, QString()); - } else { - Q_ASSERT_X(false, "JsonTypes", QString("Unhandled ref: %1").arg(refName).toLatin1().data()); - return report(false, QString("Unhandled ref %1. Server implementation incomplete.").arg(refName)); - } - } else { - QPair result = JsonTypes::validateProperty(templateVariant, variant); - if (!result.first) { - qCWarning(dcJsonRpc) << "property not matching:" << templateVariant << "!=" << variant; - return result; - } - } - break; - case QVariant::Map: { - QPair result = validateMap(templateVariant.toMap(), variant.toMap()); - if (!result.first) { - return result; - } - break; - } - case QVariant::List: { - QPair result = validateList(templateVariant.toList(), variant.toList()); - if (!result.first) { - return result; - } - break; - } - default: - qCWarning(dcJsonRpc) << "Unhandled value" << templateVariant; - return report(false, QString("Unhandled value %1.").arg(templateVariant.toString())); - } - return report(true, ""); -} - -/*! Verify the given \a variant with the possible \l{BasicType}. Returns the error string and false if - the params are not valid. */ -QPair JsonTypes::validateBasicType(const QVariant &variant) -{ - if (variant.canConvert(QVariant::Uuid) && QVariant(variant).convert(QVariant::Uuid)) { - return report(true, ""); - } - if (variant.canConvert(QVariant::String) && QVariant(variant).convert(QVariant::String)) { - return report(true, ""); - } - if (variant.canConvert(QVariant::StringList) && QVariant(variant).convert(QVariant::StringList)) { - return report(true, ""); - } - if (variant.canConvert(QVariant::Int) && QVariant(variant).convert(QVariant::Int)) { - return report(true, ""); - } - if (variant.canConvert(QVariant::UInt) && QVariant(variant).convert(QVariant::UInt)){ - return report(true, ""); - } - if (variant.canConvert(QVariant::Double) && QVariant(variant).convert(QVariant::Double)) { - return report(true, ""); - } - if (variant.canConvert(QVariant::Bool && QVariant(variant).convert(QVariant::Bool))) { - return report(true, ""); - } - if (variant.canConvert(QVariant::Color) && QVariant(variant).convert(QVariant::Color)) { - return report(true, ""); - } - if (variant.canConvert(QVariant::Time) && QVariant(variant).convert(QVariant::Time)) { - return report(true, ""); - } - - return report(false, QString("Error validating basic type %1.").arg(variant.toString())); -} - -/*! Compairs the given \a value with the given \a enumDescription. Returns the error string and false if - the enum does not contain the given \a value. */ -QPair JsonTypes::validateEnum(const QVariantList &enumDescription, const QVariant &value) -{ - QStringList enumStrings; - foreach (const QVariant &variant, enumDescription) - enumStrings.append(variant.toString()); - - return report(enumDescription.contains(value.toString()), QString("Value %1 not allowed in %2").arg(value.toString()).arg(enumStrings.join(", "))); -} - -} diff --git a/libnymea-core/jsonrpc/jsontypes.h b/libnymea-core/jsonrpc/jsontypes.h deleted file mode 100644 index bc5f9878..00000000 --- a/libnymea-core/jsonrpc/jsontypes.h +++ /dev/null @@ -1,292 +0,0 @@ -/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * - * * - * Copyright (C) 2015 Simon Stürz * - * Copyright (C) 2014 Michael Zanetti * - * Copyright (C) 2017 Michael Zanetti * - * * - * This file is part of nymea. * - * * - * nymea is free software: you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation, version 2 of the License. * - * * - * nymea is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with nymea. If not, see . * - * * - * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ - -#ifndef JSONTYPES_H -#define JSONTYPES_H - -#include "devices/devicedescriptor.h" -#include "devices/devicemanager.h" -#include "ruleengine/rule.h" -#include "ruleengine/ruleengine.h" -#include "ruleengine/ruleactionparam.h" -#include "nymeaconfiguration.h" -#include "usermanager/usermanager.h" - -#include "types/deviceclass.h" -#include "types/event.h" -#include "types/action.h" -#include "types/actiontype.h" -#include "types/paramtype.h" -#include "types/paramdescriptor.h" -#include "types/mediabrowseritem.h" - -#include "logging/logging.h" -#include "logging/logentry.h" -#include "logging/logfilter.h" - -#include "tagging/tagsstorage.h" -#include "tagging/tag.h" - -#include "time/calendaritem.h" -#include "time/repeatingoption.h" -#include "time/timedescriptor.h" -#include "time/timeeventitem.h" - -#include "networkmanager/networkmanager.h" -#include "networkmanager/networkdevice.h" -#include "networkmanager/wirednetworkdevice.h" -#include "networkmanager/wirelessnetworkdevice.h" -#include "networkmanager/wirelessaccesspoint.h" - -#include "cloud/cloudmanager.h" -#include "platform/package.h" -#include "platform/repository.h" - -#include - -#include -#include -#include - -class DevicePlugin; -class Device; - -namespace nymeaserver { - -#define DECLARE_OBJECT(typeName, jsonName) \ - public: \ - static QString typeName##Ref() { return QStringLiteral("$ref:") + QStringLiteral(jsonName); } \ - static QVariantMap typeName##Description() { \ - if (!s_initialized) { init(); } \ - return s_##typeName; \ - } \ - private: \ - static QVariantMap s_##typeName; \ - public: - -#define DECLARE_TYPE(typeName, enumString, className, enumName) \ - public: \ - static QString typeName##Ref() { return QStringLiteral("$ref:") + QStringLiteral(enumString); } \ - static QVariantList typeName() { \ - if (!s_initialized) { init(); } \ - return s_##typeName; \ - } \ - static QString typeName##ToString(className::enumName value) { \ - QMetaEnum metaEnum = QMetaEnum::fromType(); \ - return metaEnum.valueToKey(value); \ - } \ - private: \ - static QVariantList s_##typeName; \ - public: - -class JsonTypes -{ - Q_GADGET - -public: - enum BasicType { - Uuid, - String, - StringList, - Int, - Uint, - Double, - Bool, - Variant, - Color, - Time, - Object - }; - Q_ENUM(BasicType) - - static QVariantMap allTypes(); - - DECLARE_TYPE(basicType, "BasicType", JsonTypes, BasicType) - DECLARE_TYPE(stateOperator, "StateOperator", Types, StateOperator) - DECLARE_TYPE(valueOperator, "ValueOperator", Types, ValueOperator) - DECLARE_TYPE(inputType, "InputType", Types, InputType) - DECLARE_TYPE(unit, "Unit", Types, Unit) - DECLARE_TYPE(createMethod, "CreateMethod", DeviceClass, CreateMethod) - DECLARE_TYPE(setupMethod, "SetupMethod", DeviceClass, SetupMethod) - DECLARE_TYPE(deviceError, "DeviceError", Device, DeviceError) - DECLARE_TYPE(removePolicy, "RemovePolicy", RuleEngine, RemovePolicy) - DECLARE_TYPE(ruleError, "RuleError", RuleEngine, RuleError) - DECLARE_TYPE(loggingError, "LoggingError", Logging, LoggingError) - DECLARE_TYPE(loggingSource, "LoggingSource", Logging, LoggingSource) - DECLARE_TYPE(loggingLevel, "LoggingLevel", Logging, LoggingLevel) - DECLARE_TYPE(loggingEventType, "LoggingEventType", Logging, LoggingEventType) - DECLARE_TYPE(repeatingMode, "RepeatingMode", RepeatingOption, RepeatingMode) - DECLARE_TYPE(configurationError, "ConfigurationError", NymeaConfiguration, ConfigurationError) - DECLARE_TYPE(networkManagerError, "NetworkManagerError", NetworkManager, NetworkManagerError) - DECLARE_TYPE(networkManagerState, "NetworkManagerState", NetworkManager, NetworkManagerState) - DECLARE_TYPE(networkDeviceState, "NetworkDeviceState", NetworkDevice, NetworkDeviceState) - DECLARE_TYPE(userError, "UserError", UserManager, UserError) - DECLARE_TYPE(tagError, "TagError", TagsStorage, TagError) - DECLARE_TYPE(cloudConnectionState, "CloudConnectionState", CloudManager, CloudConnectionState) - DECLARE_TYPE(browserIcon, "BrowserIcon", BrowserItem, BrowserIcon) - DECLARE_TYPE(mediaBrowserIcon, "MediaBrowserIcon", MediaBrowserItem, MediaBrowserIcon) - - DECLARE_OBJECT(paramType, "ParamType") - DECLARE_OBJECT(param, "Param") - DECLARE_OBJECT(paramDescriptor, "ParamDescriptor") - DECLARE_OBJECT(ruleAction, "RuleAction") - DECLARE_OBJECT(ruleActionParam, "RuleActionParam") - DECLARE_OBJECT(stateType, "StateType") - DECLARE_OBJECT(stateDescriptor, "StateDescriptor") - DECLARE_OBJECT(state, "State") - DECLARE_OBJECT(stateEvaluator, "StateEvaluator") - DECLARE_OBJECT(eventType, "EventType") - DECLARE_OBJECT(event, "Event") - DECLARE_OBJECT(eventDescriptor, "EventDescriptor") - DECLARE_OBJECT(actionType, "ActionType") - DECLARE_OBJECT(action, "Action") - DECLARE_OBJECT(plugin, "Plugin") - DECLARE_OBJECT(vendor, "Vendor") - DECLARE_OBJECT(deviceClass, "DeviceClass") - DECLARE_OBJECT(device, "Device") - DECLARE_OBJECT(deviceDescriptor, "DeviceDescriptor") - DECLARE_OBJECT(rule, "Rule") - DECLARE_OBJECT(ruleDescription, "RuleDescription") - DECLARE_OBJECT(logEntry, "LogEntry") - DECLARE_OBJECT(timeDescriptor, "TimeDescriptor") - DECLARE_OBJECT(calendarItem, "CalendarItem") - DECLARE_OBJECT(timeEventItem, "TimeEventItem") - DECLARE_OBJECT(repeatingOption, "RepeatingOption") - DECLARE_OBJECT(wirelessAccessPoint, "WirelessAccessPoint") - DECLARE_OBJECT(wiredNetworkDevice, "WiredNetworkDevice") - DECLARE_OBJECT(wirelessNetworkDevice, "WirelessNetworkDevice") - DECLARE_OBJECT(tokenInfo, "TokenInfo") - DECLARE_OBJECT(serverConfiguration, "ServerConfiguration") - DECLARE_OBJECT(webServerConfiguration, "WebServerConfiguration") - DECLARE_OBJECT(tag, "Tag") - DECLARE_OBJECT(mqttPolicy, "MqttPolicy") - DECLARE_OBJECT(package, "Package") - DECLARE_OBJECT(repository, "Repository") - DECLARE_OBJECT(browserItem, "BrowserItem") - - // pack types - static QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packEvent(const Event &event); - static QVariantMap packEventDescriptor(const EventDescriptor &event); - static QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packAction(const Action &action); - static QVariantMap packRuleAction(const RuleAction &ruleAction); - static QVariantMap packRuleActionParam(const RuleActionParam &ruleActionParam); - static QVariantMap packState(const State &state); - static QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor); - static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator); - static QVariantMap packParam(const Param ¶m); - static QVariantMap packBrowserItem(const BrowserItem &item); - static QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packParamDescriptor(const ParamDescriptor ¶mDescriptor); - static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale); - static QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale); - static QVariantMap packPlugin(DevicePlugin *pluginid, const QLocale &locale); - static QVariantMap packDevice(Device *device); - static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor); - static QVariantMap packRule(const Rule &rule); - static QVariantMap packRuleDescription(const Rule &rule); - static QVariantMap packLogEntry(const LogEntry &logEntry); - static QVariantMap packTag(const Tag &tag); - static QVariantMap packRepeatingOption(const RepeatingOption &option); - static QVariantMap packCalendarItem(const CalendarItem &calendarItem); - static QVariantMap packTimeEventItem(const TimeEventItem &timeEventItem); - static QVariantMap packTimeDescriptor(const TimeDescriptor &timeDescriptor); - static QVariantMap packWirelessAccessPoint(WirelessAccessPoint *wirelessAccessPoint); - static QVariantMap packWiredNetworkDevice(WiredNetworkDevice *networkDevice); - static QVariantMap packWirelessNetworkDevice(WirelessNetworkDevice *networkDevice); - - static QVariantList packParams(const ParamList ¶mList); - static QVariantList packBrowserItems(const BrowserItems &items); - static QVariantList packRules(const QList rules); - static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods); - static QVariantList packSupportedVendors(const QLocale &locale); - static QVariantList packSupportedDevices(const VendorId &vendorId, const QLocale &locale); - static QVariantList packConfiguredDevices(); - static QVariantList packDeviceStates(Device *device); - static QVariantList packDeviceDescriptors(const QList deviceDescriptors); - - static QVariantMap packBasicConfiguration(); - static QVariantMap packServerConfiguration(const ServerConfiguration &config); - static QVariantMap packWebServerConfiguration(const WebServerConfiguration &config); - static QVariantMap packMqttPolicy(const MqttPolicy &policy); - - static QVariantList packRuleDescriptions(); - static QVariantList packRuleDescriptions(const QList &rules); - - static QVariantList packActionTypes(const DeviceClass &deviceClass, const QLocale &locale); - static QVariantList packStateTypes(const DeviceClass &deviceClass, const QLocale &locale); - static QVariantList packEventTypes(const DeviceClass &deviceClass, const QLocale &locale); - static QVariantList packPlugins(const QLocale &locale); - - static QVariantMap packTokenInfo(const TokenInfo &tokenInfo); - - static QVariantMap packPackage(const Package &package); - static QVariantMap packRepository(const Repository &repository); - - static QString basicTypeToString(const QVariant::Type &type); - - // unpack Types - static Param unpackParam(const QVariantMap ¶mMap); - static ParamList unpackParams(const QVariantList ¶mList); - static Rule unpackRule(const QVariantMap &ruleMap); - static RuleAction unpackRuleAction(const QVariantMap &ruleActionMap); - static RuleActionParam unpackRuleActionParam(const QVariantMap &ruleActionParamMap); - static RuleActionParamList unpackRuleActionParams(const QVariantList &ruleActionParamList); - static ParamDescriptor unpackParamDescriptor(const QVariantMap ¶mDescriptorMap); - static QList unpackParamDescriptors(const QVariantList ¶mDescriptorList); - static EventDescriptor unpackEventDescriptor(const QVariantMap &eventDescriptorMap); - static StateEvaluator unpackStateEvaluator(const QVariantMap &stateEvaluatorMap); - static StateDescriptor unpackStateDescriptor(const QVariantMap &stateDescriptorMap); - static LogFilter unpackLogFilter(const QVariantMap &logFilterMap); - static RepeatingOption unpackRepeatingOption(const QVariantMap &repeatingOptionMap); - static CalendarItem unpackCalendarItem(const QVariantMap &calendarItemMap); - static TimeEventItem unpackTimeEventItem(const QVariantMap &timeEventItemMap); - static TimeDescriptor unpackTimeDescriptor(const QVariantMap &timeDescriptorMap); - static Tag unpackTag(const QVariantMap &tagMap); - - static ServerConfiguration unpackServerConfiguration(const QVariantMap &serverConfigurationMap); - static WebServerConfiguration unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap); - static MqttPolicy unpackMqttPolicy(const QVariantMap &mqttPolicyMap); - - // validate - static QPair validateMap(const QVariantMap &templateMap, const QVariantMap &map); - static QPair validateProperty(const QVariant &templateValue, const QVariant &value); - static QPair validateList(const QVariantList &templateList, const QVariantList &list); - static QPair validateVariant(const QVariant &templateVariant, const QVariant &variant); - static QPair validateEnum(const QVariantList &enumList, const QVariant &value); - static QPair validateBasicType(const QVariant &variant); - -private: - static bool s_initialized; - static void init(); - - static QPair report(bool status, const QString &message); - static QVariantList enumToStrings(const QMetaObject &metaObject, const QString &enumName); - - static QString s_lastError; -}; - -} - -#endif // JSONTYPES_H diff --git a/libnymea-core/jsonrpc/jsonvalidator.cpp b/libnymea-core/jsonrpc/jsonvalidator.cpp new file mode 100644 index 00000000..56cb1c61 --- /dev/null +++ b/libnymea-core/jsonrpc/jsonvalidator.cpp @@ -0,0 +1,223 @@ +#include "jsonvalidator.h" +#include "jsonrpc/jsonhandler.h" + +#include "loggingcategories.h" + +#include +#include +#include + +namespace nymeaserver { + +bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types) +{ + foreach (const QString &key, map.keys()) { + if (map.value(key).toString().startsWith("$ref:")) { + QString refName = map.value(key).toString().remove("$ref:"); + if (!types.contains(refName)) { + qCWarning(dcJsonRpc()) << "Invalid reference to" << refName; + return false; + } + } + if (map.value(key).type() == QVariant::Map) { + bool ret = checkRefs(map.value(key).toMap(), types); + if (!ret) { + return false; + } + } + if (map.value(key).type() == QVariant::List) { + foreach (const QVariant &entry, map.value(key).toList()) { + if (entry.toString().startsWith("$ref:")) { + QString refName = entry.toString().remove("$ref:"); + if (!types.contains(refName)) { + qCWarning(dcJsonRpc()) << "Invalid reference to" << refName; + return false; + } + } + if (entry.type() == QVariant::Map) { + bool ret = checkRefs(map.value(key).toMap(), types); + if (!ret) { + return false; + } + } + } + } + } + return true; + +} + +JsonValidator::Result JsonValidator::validateParams(const QVariantMap ¶ms, const QString &method, const QVariantMap &api) +{ + QVariantMap paramDefinition = api.value("methods").toMap().value(method).toMap().value("params").toMap(); + m_result = validateMap(params, paramDefinition, api.value("types").toMap()); + m_result.setWhere(method + ", param " + m_result.where()); + return m_result; +} + +JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api) +{ + QVariantMap returnsDefinition = api.value("methods").toMap().value(method).toMap().value("returns").toMap(); + m_result = validateMap(returns, returnsDefinition, api.value("types").toMap()); + m_result.setWhere(method + ", returns " + m_result.where()); + return m_result; +} + +JsonValidator::Result JsonValidator::validateNotificationParams(const QVariantMap ¶ms, const QString ¬ification, const QVariantMap &api) +{ + QVariantMap paramDefinition = api.value("notifications").toMap().value(notification).toMap().value("params").toMap(); + m_result = validateMap(params, paramDefinition, api.value("types").toMap()); + m_result.setWhere(notification + ", param " + m_result.where()); + return m_result; +} + +JsonValidator::Result JsonValidator::result() const +{ + return m_result; +} + +JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types) +{ + // Make sure all required values are available + foreach (const QString &key, definition.keys()) { + if (key.startsWith("o:")) { + continue; + } + if (!map.contains(key)) { + return Result(false, "Missing required key: " + key, key); + } + } + + // Make sure given values are valid + foreach (const QString &key, map.keys()) { + // Is the key allowed in here? + QVariant expectedValue = definition.value(key); + if (!expectedValue.isValid()) { + expectedValue = definition.value("o:" + key); + } + if (!expectedValue.isValid()) { + return Result(false, "Invalid key: " + key); + } + + // Validate content + QVariant value = map.value(key); + + Result result = validateEntry(value, expectedValue, types); + if (!result.success()) { + result.setWhere(key + '.' + result.where()); + result.setErrorString(result.errorString()); + return result; + } + + } + + return Result(true); +} + +JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types) +{ + if (definition.type() == QVariant::String) { + QString expectedTypeName = definition.toString(); + + if (expectedTypeName.startsWith("$ref:")) { + QString refName = expectedTypeName; + refName.remove("$ref:"); + + QVariant refDefinition = types.value(refName); + // Refs might be enums + if (refDefinition.type() == QVariant::List) { + if (value.type() != QVariant::String) { + return Result(false, "Expected enum " + refName + " but got " + value.toString()); + } + QVariantList enumList = refDefinition.toList(); + if (!enumList.contains(value.toString())) { + return Result(false, "Expected enum " + refName + " but got " + value.toString()); + } + return Result(true); + } + + return validateEntry(value, refDefinition, types); + } + + JsonHandler::BasicType expectedBasicType = JsonHandler::enumNameToValue(expectedTypeName); + QVariant::Type expectedVariantType = JsonHandler::basicTypeToVariantType(expectedBasicType); + + // Verify basic compatiblity + if (expectedBasicType != JsonHandler::Variant && !value.canConvert(expectedVariantType)) { + return Result(false, "Invalid value. Expected: " + definition.toString() + ", Got: " + value.toString()); + } + + // Any string converts fine to Uuid, but the resulting uuid might be null + if (expectedBasicType == JsonHandler::Uuid && value.toUuid().isNull()) { + return Result(false, "Invalid Uuid: " + value.toString()); + } + // Make sure ints are valid + if (expectedBasicType == JsonHandler::Int) { + bool ok; + value.toLongLong(&ok); + if (!ok) { + return Result(false, "Invalid Int: " + value.toString()); + } + } + // UInts + if (expectedBasicType == JsonHandler::Uint) { + bool ok; + value.toULongLong(&ok); + if (!ok) { + return Result(false, "Invalid UInt: " + value.toString()); + } + } + // Double + if (expectedBasicType == JsonHandler::Double) { + bool ok; + value.toDouble(&ok); + if (!ok) { + return Result(false, "Invalid Double: " + value.toString()); + } + } + // Color + if (expectedBasicType == JsonHandler::Color) { + QColor color = value.value(); + if (!color.isValid()) { + return Result(false, "Invalid Color: " + value.toString()); + } + } + // Time + if (expectedBasicType == JsonHandler::Time) { + bool ok; + QDateTime time = QDateTime::fromTime_t(value.toUInt(&ok)); + if (!ok || !time.isValid()) { + return Result(false, "Invalid Time: " + value.toString()); + } + } + + + return Result(true); + } + + if (definition.type() == QVariant::Map) { + if (value.type() != QVariant::Map) { + return Result(false, "Invalud value. Expected a map bug received: " + value.toString()); + } + return validateMap(value.toMap(), definition.toMap(), types); + } + + if (definition.type() == QVariant::List) { + QVariantList list = definition.toList(); + QVariant entryDefinition = list.first(); + if (value.type() != QVariant::List && value.type() != QVariant::StringList) { + return Result(false, "Expected list of " + entryDefinition.toString() + " but got value of type " + value.typeName() + "\n" + QJsonDocument::fromVariant(value).toJson()); + } + foreach (const QVariant &entry, value.toList()) { + Result result = validateEntry(entry, entryDefinition, types); + if (!result.success()) { + return result; + } + } + return Result(true); + } + Q_ASSERT_X(false, "JsonValildator", "Incomplete validation. Unexpected type in template"); + return Result(false); +} + +} diff --git a/libnymea-core/jsonrpc/jsonvalidator.h b/libnymea-core/jsonrpc/jsonvalidator.h new file mode 100644 index 00000000..731da915 --- /dev/null +++ b/libnymea-core/jsonrpc/jsonvalidator.h @@ -0,0 +1,49 @@ +#ifndef JSONVALIDATOR_H +#define JSONVALIDATOR_H + +#include +#include + +namespace nymeaserver { + +class JsonValidator +{ +public: + class Result { + public: + Result() {} + Result(bool success, const QString &errorString = QString(), const QString &where = QString()): m_success(success), m_errorString(errorString), m_where(where) {} + bool success() const { return m_success; } + void setSuccess(bool success) { m_success = success; } + QString errorString() const { return m_errorString; } + void setErrorString(const QString &errorString) { m_errorString = errorString; } + QString where() const { return m_where; } + void setWhere(const QString &where) { m_where = where; } + bool deprecated() { return m_deprecated; } + void setDeprecated(bool deprecated) { m_deprecated = deprecated; } + private: + bool m_success = false; + QString m_errorString; + QString m_where; + bool m_deprecated = false; + }; + + JsonValidator() {} + + static bool checkRefs(const QVariantMap &map, const QVariantMap &types); + + Result validateParams(const QVariantMap ¶ms, const QString &method, const QVariantMap &api); + Result validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api); + Result validateNotificationParams(const QVariantMap ¶ms, const QString ¬ification, const QVariantMap &api); + + Result result() const; +private: + Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types); + Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types); + + Result m_result; +}; + +} + +#endif // JSONVALIDATOR_H diff --git a/libnymea-core/jsonrpc/logginghandler.cpp b/libnymea-core/jsonrpc/logginghandler.cpp index abbeaadf..f3e3e0c0 100644 --- a/libnymea-core/jsonrpc/logginghandler.cpp +++ b/libnymea-core/jsonrpc/logginghandler.cpp @@ -45,6 +45,7 @@ #include "logginghandler.h" #include "logging/logengine.h" #include "logging/logfilter.h" +#include "logging/logvaluetool.h" #include "loggingcategories.h" #include "nymeacore.h" @@ -54,12 +55,29 @@ namespace nymeaserver { LoggingHandler::LoggingHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap params; - QVariantMap returns; + // Enums + registerEnum(); + registerEnum(); + registerEnum(); + registerEnum(); - QVariantMap timeFilter; - params.clear(); returns.clear(); - setDescription("GetLogEntries", "Get the LogEntries matching the given filter. " + // Objects + QVariantMap logEntry; + logEntry.insert("timestamp", enumValueName(Int)); + logEntry.insert("loggingLevel", enumRef()); + logEntry.insert("source", enumRef()); + logEntry.insert("o:typeId", enumValueName(Uuid)); + logEntry.insert("o:deviceId", enumValueName(Uuid)); + logEntry.insert("o:itemId", enumValueName(String)); + logEntry.insert("o:value", enumValueName(String)); + logEntry.insert("o:active", enumValueName(Bool)); + logEntry.insert("o:eventType", enumRef()); + logEntry.insert("o:errorCode", enumValueName(String)); + registerObject("LogEntry", logEntry); + + // Methods + QString description; QVariantMap params; QVariantMap returns; + description = "Get the LogEntries matching the given filter. " "The result set will contain entries matching all filter rules combined. " "If multiple options are given for a single filter type, the result set will " "contain entries matching any of those. The offset starts at the newest entry " @@ -73,38 +91,38 @@ LoggingHandler::LoggingHandler(QObject *parent) : "1) offset 0, maxCount 1000: Entries 0 to 9999\n" "2) offset 10000, maxCount 1000: Entries 10000 - 19999\n" "3) offset 20000, maxCount 1000: Entries 20000 - 29999\n" - "..."); - timeFilter.insert("o:startDate", JsonTypes::basicTypeToString(JsonTypes::Int)); - timeFilter.insert("o:endDate", JsonTypes::basicTypeToString(JsonTypes::Int)); + "..."; + QVariantMap timeFilter; + timeFilter.insert("o:startDate", enumValueName(Int)); + timeFilter.insert("o:endDate", enumValueName(Int)); params.insert("o:timeFilters", QVariantList() << timeFilter); - params.insert("o:loggingSources", QVariantList() << JsonTypes::loggingSourceRef()); - params.insert("o:loggingLevels", QVariantList() << JsonTypes::loggingLevelRef()); - params.insert("o:eventTypes", QVariantList() << JsonTypes::loggingEventTypeRef()); - params.insert("o:typeIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:deviceIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:values", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Variant)); - params.insert("o:limit", JsonTypes::basicTypeToString(JsonTypes::Int)); - params.insert("o:offset", JsonTypes::basicTypeToString(JsonTypes::Int)); - setParams("GetLogEntries", params); - returns.insert("loggingError", JsonTypes::loggingErrorRef()); - returns.insert("o:logEntries", QVariantList() << JsonTypes::logEntryRef()); - returns.insert("count", JsonTypes::basicTypeToString(JsonTypes::Int)); - returns.insert("offset", JsonTypes::basicTypeToString(JsonTypes::Int)); - setReturns("GetLogEntries", returns); + params.insert("o:loggingSources", QVariantList() << enumRef()); + params.insert("o:loggingLevels", QVariantList() << enumRef()); + params.insert("o:eventTypes", QVariantList() << enumRef()); + params.insert("o:typeIds", QVariantList() << enumValueName(Uuid)); + params.insert("o:deviceIds", QVariantList() << enumValueName(Uuid)); + params.insert("o:values", QVariantList() << enumValueName(Variant)); + params.insert("o:limit", enumValueName(Int)); + params.insert("o:offset", enumValueName(Int)); + returns.insert("loggingError", enumRef()); + returns.insert("o:logEntries", QVariantList() << objectRef("LogEntry")); + returns.insert("count", enumValueName(Int)); + returns.insert("offset", enumValueName(Int)); + registerMethod("GetLogEntries", description, params, returns); // Notifications params.clear(); - setDescription("LogEntryAdded", "Emitted whenever an entry is appended to the logging system. "); - params.insert("logEntry", JsonTypes::logEntryRef()); - setParams("LogEntryAdded", params); + description = "Emitted whenever an entry is appended to the logging system. "; + params.insert("logEntry", objectRef("LogEntry")); + registerNotification("LogEntryAdded", description, params); params.clear(); - setDescription("LogDatabaseUpdated", "Emitted whenever the database was updated. " + description = "Emitted whenever the database was updated. " "The database will be updated when a log entry was deleted. A log " "entry will be deleted when the corresponding device or a rule will " "be removed, or when the oldest entry of the database was deleted to " - "keep to database in the size limits."); - setParams("LogDatabaseUpdated", params); + "keep to database in the size limits."; + registerNotification("LogDatabaseUpdated", description, params); connect(NymeaCore::instance()->logEngine(), &LogEngine::logEntryAdded, this, &LoggingHandler::logEntryAdded); connect(NymeaCore::instance()->logEngine(), &LogEngine::logDatabaseUpdated, this, &LoggingHandler::logDatabaseUpdated); @@ -119,7 +137,7 @@ QString LoggingHandler::name() const void LoggingHandler::logEntryAdded(const LogEntry &logEntry) { QVariantMap params; - params.insert("logEntry", JsonTypes::packLogEntry(logEntry)); + params.insert("logEntry", packLogEntry(logEntry)); emit LogEntryAdded(params); } @@ -130,18 +148,136 @@ void LoggingHandler::logDatabaseUpdated() JsonReply* LoggingHandler::GetLogEntries(const QVariantMap ¶ms) const { - LogFilter filter = JsonTypes::unpackLogFilter(params); + LogFilter filter = unpackLogFilter(params); QVariantList entries; foreach (const LogEntry &entry, NymeaCore::instance()->logEngine()->logEntries(filter)) { - entries.append(JsonTypes::packLogEntry(entry)); + entries.append(packLogEntry(entry)); } - QVariantMap returns = statusToReply(Logging::LoggingErrorNoError); - + QVariantMap returns; + returns.insert("loggingError", enumValueName(Logging::LoggingErrorNoError)); returns.insert("logEntries", entries); returns.insert("offset", filter.offset()); returns.insert("count", entries.count()); return createReply(returns); } +QVariantMap LoggingHandler::packLogEntry(const LogEntry &logEntry) +{ + QVariantMap logEntryMap; + logEntryMap.insert("timestamp", logEntry.timestamp().toMSecsSinceEpoch()); + logEntryMap.insert("loggingLevel", enumValueName(logEntry.level())); + logEntryMap.insert("source", enumValueName(logEntry.source())); + logEntryMap.insert("eventType", enumValueName(logEntry.eventType())); + + if (logEntry.eventType() == Logging::LoggingEventTypeActiveChange) + logEntryMap.insert("active", logEntry.active()); + + if (logEntry.eventType() == Logging::LoggingEventTypeEnabledChange) + logEntryMap.insert("active", logEntry.active()); + + if (logEntry.level() == Logging::LoggingLevelAlert) { + switch (logEntry.source()) { + case Logging::LoggingSourceRules: + logEntryMap.insert("errorCode", enumValueName(static_cast(logEntry.errorCode()))); + break; + case Logging::LoggingSourceActions: + case Logging::LoggingSourceEvents: + case Logging::LoggingSourceStates: + case Logging::LoggingSourceBrowserActions: + logEntryMap.insert("errorCode", enumValueName(static_cast(logEntry.errorCode()))); + break; + case Logging::LoggingSourceSystem: + // FIXME: Update this once we support error codes for the general system + // logEntryMap.insert("errorCode", ""); + break; + } + } + + switch (logEntry.source()) { + case Logging::LoggingSourceActions: + case Logging::LoggingSourceEvents: + case Logging::LoggingSourceStates: + logEntryMap.insert("typeId", logEntry.typeId().toString()); + logEntryMap.insert("deviceId", logEntry.deviceId().toString()); + logEntryMap.insert("value", LogValueTool::convertVariantToString(logEntry.value())); + break; + case Logging::LoggingSourceSystem: + logEntryMap.insert("active", logEntry.active()); + break; + case Logging::LoggingSourceRules: + logEntryMap.insert("typeId", logEntry.typeId().toString()); + break; + case Logging::LoggingSourceBrowserActions: + logEntryMap.insert("itemId", logEntry.value()); + break; + } + + return logEntryMap; +} + +LogFilter LoggingHandler::unpackLogFilter(const QVariantMap &logFilterMap) +{ + LogFilter filter; + if (logFilterMap.contains("timeFilters")) { + QVariantList timeFilters = logFilterMap.value("timeFilters").toList(); + foreach (const QVariant &timeFilter, timeFilters) { + QVariantMap timeFilterMap = timeFilter.toMap(); + QDateTime startDate; QDateTime endDate; + if (timeFilterMap.contains("startDate")) + startDate = QDateTime::fromTime_t(timeFilterMap.value("startDate").toUInt()); + + if (timeFilterMap.contains("endDate")) + endDate = QDateTime::fromTime_t(timeFilterMap.value("endDate").toUInt()); + + filter.addTimeFilter(startDate, endDate); + } + } + + if (logFilterMap.contains("loggingSources")) { + QVariantList loggingSources = logFilterMap.value("loggingSources").toList(); + foreach (const QVariant &source, loggingSources) { + filter.addLoggingSource(enumNameToValue(source.toString())); + } + } + if (logFilterMap.contains("loggingLevels")) { + QVariantList loggingLevels = logFilterMap.value("loggingLevels").toList(); + foreach (const QVariant &level, loggingLevels) { + filter.addLoggingLevel(enumNameToValue(level.toString())); + } + } + if (logFilterMap.contains("eventTypes")) { + QVariantList eventTypes = logFilterMap.value("eventTypes").toList(); + foreach (const QVariant &eventType, eventTypes) { + filter.addLoggingEventType(enumNameToValue(eventType.toString())); + } + } + if (logFilterMap.contains("typeIds")) { + QVariantList typeIds = logFilterMap.value("typeIds").toList(); + foreach (const QVariant &typeId, typeIds) { + filter.addTypeId(typeId.toUuid()); + } + } + if (logFilterMap.contains("deviceIds")) { + QVariantList deviceIds = logFilterMap.value("deviceIds").toList(); + foreach (const QVariant &deviceId, deviceIds) { + filter.addDeviceId(DeviceId(deviceId.toString())); + } + } + if (logFilterMap.contains("values")) { + QVariantList values = logFilterMap.value("values").toList(); + foreach (const QVariant &value, values) { + filter.addValue(value.toString()); + } + } + if (logFilterMap.contains("limit")) { + filter.setLimit(logFilterMap.value("limit", -1).toInt()); + } + if (logFilterMap.contains("offset")) { + filter.setOffset(logFilterMap.value("offset").toInt()); + } + + return filter; +} + } diff --git a/libnymea-core/jsonrpc/logginghandler.h b/libnymea-core/jsonrpc/logginghandler.h index 595766d2..577ce90c 100644 --- a/libnymea-core/jsonrpc/logginghandler.h +++ b/libnymea-core/jsonrpc/logginghandler.h @@ -22,8 +22,9 @@ #ifndef LOGGINGHANDLER_H #define LOGGINGHANDLER_H -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" #include "logging/logentry.h" +#include "logging/logfilter.h" namespace nymeaserver { @@ -40,6 +41,11 @@ signals: void LogEntryAdded(const QVariantMap ¶ms); void LogDatabaseUpdated(const QVariantMap ¶ms); +private: + static QVariantMap packLogEntry(const LogEntry &logEntry); + + static LogFilter unpackLogFilter(const QVariantMap &logFilterMap); + private slots: void logEntryAdded(const LogEntry &entry); void logDatabaseUpdated(); diff --git a/libnymea-core/jsonrpc/networkmanagerhandler.cpp b/libnymea-core/jsonrpc/networkmanagerhandler.cpp index 47af5632..0535e621 100644 --- a/libnymea-core/jsonrpc/networkmanagerhandler.cpp +++ b/libnymea-core/jsonrpc/networkmanagerhandler.cpp @@ -68,7 +68,6 @@ #include "nymeacore.h" -#include "jsontypes.h" #include "loggingcategories.h" #include "networkmanagerhandler.h" #include "networkmanager/networkmanager.h" @@ -80,107 +79,128 @@ namespace nymeaserver { NetworkManagerHandler::NetworkManagerHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap params; QVariantMap returns; + // Enums + registerEnum(); + registerEnum(); + registerEnum(); - params.clear(); returns.clear(); - setDescription("GetNetworkStatus", "Get the current network manager status."); - setParams("GetNetworkStatus", params); + // Objects + QVariantMap wirelessAccessPoint; + wirelessAccessPoint.insert("ssid", enumValueName(String)); + wirelessAccessPoint.insert("macAddress", enumValueName(String)); + wirelessAccessPoint.insert("frequency", enumValueName(Double)); + wirelessAccessPoint.insert("signalStrength", enumValueName(Int)); + wirelessAccessPoint.insert("protected", enumValueName(Bool)); + registerObject("WirelessAccessPoint", wirelessAccessPoint); + + QVariantMap wiredNetworkDevice; + wiredNetworkDevice.insert("interface", enumValueName(String)); + wiredNetworkDevice.insert("macAddress", enumValueName(String)); + wiredNetworkDevice.insert("state", enumRef()); + wiredNetworkDevice.insert("bitRate", enumValueName(String)); + wiredNetworkDevice.insert("pluggedIn", enumValueName(Bool)); + registerObject("WiredNetworkDevice", wiredNetworkDevice); + + QVariantMap wirelessNetworkDevice; + wirelessNetworkDevice.insert("interface", enumValueName(String)); + wirelessNetworkDevice.insert("macAddress", enumValueName(String)); + wirelessNetworkDevice.insert("state", enumRef()); + wirelessNetworkDevice.insert("bitRate", enumValueName(String)); + wirelessNetworkDevice.insert("o:currentAccessPoint", objectRef("WirelessAccessPoint")); + registerObject("WirelessNetworkDevice", wirelessNetworkDevice); + + // Methods + QString description; QVariantMap params; QVariantMap returns; + description = "Get the current network manager status."; QVariantMap status; - status.insert("networkingEnabled", JsonTypes::basicTypeToString(QVariant::Bool)); - status.insert("wirelessNetworkingEnabled", JsonTypes::basicTypeToString(QVariant::Bool)); - status.insert("state", JsonTypes::networkManagerStateRef()); + status.insert("networkingEnabled", enumValueName(Bool)); + status.insert("wirelessNetworkingEnabled", enumValueName(Bool)); + status.insert("state", enumRef()); returns.insert("o:status", status); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("GetNetworkStatus", returns); + returns.insert("networkManagerError", enumRef()); + registerMethod("GetNetworkStatus", description, params, returns); params.clear(); returns.clear(); - setDescription("EnableNetworking", "Enable or disable networking in the NetworkManager."); - params.insert("enable", JsonTypes::basicTypeToString(QVariant::Bool)); - setParams("EnableNetworking", params); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("EnableNetworking", returns); + description = "Enable or disable networking in the NetworkManager."; + params.insert("enable", enumValueName(Bool)); + returns.insert("networkManagerError", enumRef()); + registerMethod("EnableNetworking", description, params, returns); params.clear(); returns.clear(); - setDescription("EnableWirelessNetworking", "Enable or disable wireless networking in the NetworkManager."); - params.insert("enable", JsonTypes::basicTypeToString(QVariant::Bool)); - setParams("EnableWirelessNetworking", params); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("EnableWirelessNetworking", returns); + description = "Enable or disable wireless networking in the NetworkManager."; + params.insert("enable", enumValueName(Bool)); + returns.insert("networkManagerError", enumRef()); + registerMethod("EnableWirelessNetworking", description, params, returns); params.clear(); returns.clear(); - setDescription("GetWirelessAccessPoints", "Get the current list of wireless network access points for the given interface. The interface has to be a WirelessNetworkDevice."); - params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); - setParams("GetWirelessAccessPoints", params); - returns.insert("o:wirelessAccessPoints", QVariantList() << JsonTypes::wirelessAccessPointRef()); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("GetWirelessAccessPoints", returns); + description = "Get the current list of wireless network access points for the given interface. The interface has to be a WirelessNetworkDevice."; + params.insert("interface", enumValueName(String)); + returns.insert("o:wirelessAccessPoints", QVariantList() << objectRef("WirelessAccessPoint")); + returns.insert("networkManagerError", enumRef()); + registerMethod("GetWirelessAccessPoints", description, params, returns); params.clear(); returns.clear(); - setDescription("DisconnectInterface", "Disconnect the given network interface. The interface will remain disconnected until the user connect it again."); - params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); - setParams("DisconnectInterface", params); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("DisconnectInterface", returns); + description = "Disconnect the given network interface. The interface will remain disconnected until the user connect it again."; + params.insert("interface", enumValueName(String)); + returns.insert("networkManagerError", enumRef()); + registerMethod("DisconnectInterface", description, params, returns); params.clear(); returns.clear(); - setDescription("GetNetworkDevices", "Get the list of current network devices."); - setParams("GetNetworkDevices", params); - returns.insert("wiredNetworkDevices", QVariantList() << JsonTypes::wiredNetworkDeviceRef()); - returns.insert("wirelessNetworkDevices", QVariantList() << JsonTypes::wirelessNetworkDeviceRef()); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("GetNetworkDevices", returns); + description = "Get the list of current network devices."; + returns.insert("wiredNetworkDevices", QVariantList() << objectRef("WiredNetworkDevice")); + returns.insert("wirelessNetworkDevices", QVariantList() << objectRef("WirelessNetworkDevice")); + returns.insert("networkManagerError", enumRef()); + registerMethod("GetNetworkDevices", description, params, returns); params.clear(); returns.clear(); - setDescription("ScanWifiNetworks", "Start a wifi scan for searching new networks."); - params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); - setParams("ScanWifiNetworks", params); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("ScanWifiNetworks", returns); + description = "Start a wifi scan for searching new networks."; + params.insert("interface", enumValueName(String)); + returns.insert("networkManagerError", enumRef()); + registerMethod("ScanWifiNetworks", description, params, returns); params.clear(); returns.clear(); - setDescription("ConnectWifiNetwork", "Connect to the wifi network with the given ssid and password."); - params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); - params.insert("ssid", JsonTypes::basicTypeToString(QVariant::String)); - params.insert("o:password", JsonTypes::basicTypeToString(QVariant::String)); - setParams("ConnectWifiNetwork", params); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); - setReturns("ConnectWifiNetwork", returns); + description = "Connect to the wifi network with the given ssid and password."; + params.insert("interface", enumValueName(String)); + params.insert("ssid", enumValueName(String)); + params.insert("o:password", enumValueName(String)); + returns.insert("networkManagerError", enumRef()); + registerMethod("ConnectWifiNetwork", description, params, returns); // Notifications params.clear(); returns.clear(); - setDescription("NetworkStatusChanged", "Emitted whenever a status of a NetworkManager changes."); + description = "Emitted whenever a status of a NetworkManager changes."; params.insert("status", status); - setParams("NetworkStatusChanged", params); + registerNotification("NetworkStatusChanged", description, params); params.clear(); returns.clear(); - setDescription("WirelessNetworkDeviceAdded", "Emitted whenever a new WirelessNetworkDevice was added."); - params.insert("wirelessNetworkDevice", JsonTypes::wirelessNetworkDeviceRef()); - setParams("WirelessNetworkDeviceAdded", params); + description = "Emitted whenever a new WirelessNetworkDevice was added."; + params.insert("wirelessNetworkDevice", objectRef("WirelessNetworkDevice")); + registerNotification("WirelessNetworkDeviceAdded", description, params); params.clear(); returns.clear(); - setDescription("WirelessNetworkDeviceRemoved", "Emitted whenever a WirelessNetworkDevice was removed."); - params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); - setParams("WirelessNetworkDeviceRemoved", params); + description = "Emitted whenever a WirelessNetworkDevice was removed."; + params.insert("interface", enumValueName(String)); + registerNotification("WirelessNetworkDeviceRemoved", description, params); params.clear(); returns.clear(); - setDescription("WirelessNetworkDeviceChanged", "Emitted whenever the given WirelessNetworkDevice has changed."); - params.insert("wirelessNetworkDevice", JsonTypes::wirelessNetworkDeviceRef()); - setParams("WirelessNetworkDeviceChanged", params); + description = "Emitted whenever the given WirelessNetworkDevice has changed."; + params.insert("wirelessNetworkDevice", objectRef("WirelessNetworkDevice")); + registerNotification("WirelessNetworkDeviceChanged", description, params); params.clear(); returns.clear(); - setDescription("WiredNetworkDeviceAdded", "Emitted whenever a new WiredNetworkDevice was added."); - params.insert("wiredNetworkDevice", JsonTypes::wiredNetworkDeviceRef()); - setParams("WiredNetworkDeviceAdded", params); + description = "Emitted whenever a new WiredNetworkDevice was added."; + params.insert("wiredNetworkDevice", objectRef("WiredNetworkDevice")); + registerNotification("WiredNetworkDeviceAdded", description, params); params.clear(); returns.clear(); - setDescription("WiredNetworkDeviceRemoved", "Emitted whenever a WiredNetworkDevice was removed."); - params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); - setParams("WiredNetworkDeviceRemoved", params); + description = "Emitted whenever a WiredNetworkDevice was removed."; + params.insert("interface", enumValueName(String)); + registerNotification("WiredNetworkDeviceRemoved", description, params); params.clear(); returns.clear(); - setDescription("WiredNetworkDeviceChanged", "Emitted whenever the given WiredNetworkDevice has changed."); - params.insert("wiredNetworkDevice", JsonTypes::wiredNetworkDeviceRef()); - setParams("WiredNetworkDeviceChanged", params); + description = "Emitted whenever the given WiredNetworkDevice has changed."; + params.insert("wiredNetworkDevice", objectRef("WiredNetworkDevice")); + registerNotification("WiredNetworkDeviceChanged", description, params); connect(NymeaCore::instance()->networkManager(), &NetworkManager::stateChanged, this, &NetworkManagerHandler::onNetworkManagerStatusChanged); connect(NymeaCore::instance()->networkManager(), &NetworkManager::networkingEnabledChanged, this, &NetworkManagerHandler::onNetworkManagerStatusChanged); @@ -203,16 +223,15 @@ QString NetworkManagerHandler::name() const JsonReply *NetworkManagerHandler::GetNetworkStatus(const QVariantMap ¶ms) { - Q_UNUSED(params); + Q_UNUSED(params) // Check available if (!NymeaCore::instance()->networkManager()->available()) return createReply(statusToReply(NetworkManager::NetworkManagerErrorNetworkManagerNotAvailable)); // Pack network manager status - QVariantMap returns; + QVariantMap returns = statusToReply(NetworkManager::NetworkManagerErrorNoError); returns.insert("status", packNetworkManagerStatus()); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorToString(NetworkManager::NetworkManagerErrorNoError)); return createReply(returns); } @@ -266,11 +285,10 @@ JsonReply *NetworkManagerHandler::GetWirelessAccessPoints(const QVariantMap &par if (networkDevice->interface() == interface) { QVariantList wirelessAccessPoints; foreach (WirelessAccessPoint *wirelessAccessPoint, networkDevice->accessPoints()) - wirelessAccessPoints.append(JsonTypes::packWirelessAccessPoint(wirelessAccessPoint)); + wirelessAccessPoints.append(packWirelessAccessPoint(wirelessAccessPoint)); - QVariantMap returns; + QVariantMap returns = statusToReply(NetworkManager::NetworkManagerErrorNoError); returns.insert("wirelessAccessPoints", wirelessAccessPoints); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorToString(NetworkManager::NetworkManagerErrorNoError)); return createReply(returns); } @@ -288,22 +306,21 @@ JsonReply *NetworkManagerHandler::GetNetworkDevices(const QVariantMap ¶ms) QVariantList wirelessNetworkDevices; foreach (WirelessNetworkDevice *networkDevice, NymeaCore::instance()->networkManager()->wirelessNetworkDevices()) - wirelessNetworkDevices.append(JsonTypes::packWirelessNetworkDevice(networkDevice)); + wirelessNetworkDevices.append(packWirelessNetworkDevice(networkDevice)); QVariantList wiredNetworkDevices; foreach (WiredNetworkDevice *networkDevice, NymeaCore::instance()->networkManager()->wiredNetworkDevices()) - wiredNetworkDevices.append(JsonTypes::packWiredNetworkDevice(networkDevice)); + wiredNetworkDevices.append(packWiredNetworkDevice(networkDevice)); - QVariantMap returns; + QVariantMap returns = statusToReply(NetworkManager::NetworkManagerErrorNoError); returns.insert("wirelessNetworkDevices", wirelessNetworkDevices); returns.insert("wiredNetworkDevices", wiredNetworkDevices); - returns.insert("networkManagerError", JsonTypes::networkManagerErrorToString(NetworkManager::NetworkManagerErrorNoError)); return createReply(returns); } JsonReply *NetworkManagerHandler::ScanWifiNetworks(const QVariantMap ¶ms) { - Q_UNUSED(params); + Q_UNUSED(params) if (!NymeaCore::instance()->networkManager()->available()) return createReply(statusToReply(NetworkManager::NetworkManagerErrorNetworkManagerNotAvailable)); @@ -388,7 +405,7 @@ void NetworkManagerHandler::onNetworkManagerStatusChanged() void NetworkManagerHandler::onWirelessNetworkDeviceAdded(WirelessNetworkDevice *networkDevice) { QVariantMap notification; - notification.insert("wirelessNetworkDevice", JsonTypes::packWirelessNetworkDevice(networkDevice)); + notification.insert("wirelessNetworkDevice", packWirelessNetworkDevice(networkDevice)); emit WirelessNetworkDeviceAdded(notification); } @@ -402,14 +419,14 @@ void NetworkManagerHandler::onWirelessNetworkDeviceRemoved(const QString &interf void NetworkManagerHandler::onWirelessNetworkDeviceChanged(WirelessNetworkDevice *networkDevice) { QVariantMap notification; - notification.insert("wirelessNetworkDevice", JsonTypes::packWirelessNetworkDevice(networkDevice)); + notification.insert("wirelessNetworkDevice", packWirelessNetworkDevice(networkDevice)); emit WirelessNetworkDeviceChanged(notification); } void NetworkManagerHandler::onWiredNetworkDeviceAdded(WiredNetworkDevice *networkDevice) { QVariantMap notification; - notification.insert("wiredNetworkDevice", JsonTypes::packWiredNetworkDevice(networkDevice)); + notification.insert("wiredNetworkDevice", packWiredNetworkDevice(networkDevice)); emit WiredNetworkDeviceAdded(notification); } @@ -423,8 +440,50 @@ void NetworkManagerHandler::onWiredNetworkDeviceRemoved(const QString &interface void NetworkManagerHandler::onWiredNetworkDeviceChanged(WiredNetworkDevice *networkDevice) { QVariantMap notification; - notification.insert("wiredNetworkDevice", JsonTypes::packWiredNetworkDevice(networkDevice)); + notification.insert("wiredNetworkDevice", packWiredNetworkDevice(networkDevice)); emit WiredNetworkDeviceChanged(notification); } +QVariantMap NetworkManagerHandler::packWirelessAccessPoint(WirelessAccessPoint *wirelessAccessPoint) +{ + QVariantMap wirelessAccessPointVariant; + wirelessAccessPointVariant.insert("ssid", wirelessAccessPoint->ssid()); + wirelessAccessPointVariant.insert("macAddress", wirelessAccessPoint->macAddress()); + wirelessAccessPointVariant.insert("frequency", wirelessAccessPoint->frequency()); + wirelessAccessPointVariant.insert("signalStrength", wirelessAccessPoint->signalStrength()); + wirelessAccessPointVariant.insert("protected", wirelessAccessPoint->isProtected()); + return wirelessAccessPointVariant; +} + +QVariantMap NetworkManagerHandler::packWiredNetworkDevice(WiredNetworkDevice *networkDevice) +{ + QVariantMap networkDeviceVariant; + networkDeviceVariant.insert("interface", networkDevice->interface()); + networkDeviceVariant.insert("macAddress", networkDevice->macAddress()); + networkDeviceVariant.insert("state", networkDevice->deviceStateString()); + networkDeviceVariant.insert("bitRate", QString("%1 [Mb/s]").arg(QString::number(networkDevice->bitRate()))); + networkDeviceVariant.insert("pluggedIn", networkDevice->pluggedIn()); + return networkDeviceVariant; +} + +QVariantMap NetworkManagerHandler::packWirelessNetworkDevice(WirelessNetworkDevice *networkDevice) +{ + QVariantMap networkDeviceVariant; + networkDeviceVariant.insert("interface", networkDevice->interface()); + networkDeviceVariant.insert("macAddress", networkDevice->macAddress()); + networkDeviceVariant.insert("state", networkDevice->deviceStateString()); + networkDeviceVariant.insert("bitRate", QString("%1 [Mb/s]").arg(QString::number(networkDevice->bitRate()))); + if (networkDevice->activeAccessPoint()) + networkDeviceVariant.insert("currentAccessPoint", packWirelessAccessPoint(networkDevice->activeAccessPoint())); + + return networkDeviceVariant; +} + +QVariantMap NetworkManagerHandler::statusToReply(NetworkManager::NetworkManagerError status) const +{ + QVariantMap returns; + returns.insert("networkManagerError", enumValueName(status)); + return returns; +} + } diff --git a/libnymea-core/jsonrpc/networkmanagerhandler.h b/libnymea-core/jsonrpc/networkmanagerhandler.h index b8834173..6ef9d93c 100644 --- a/libnymea-core/jsonrpc/networkmanagerhandler.h +++ b/libnymea-core/jsonrpc/networkmanagerhandler.h @@ -23,7 +23,8 @@ #include -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" +#include "networkmanager/networkmanager.h" namespace nymeaserver { @@ -73,6 +74,13 @@ private slots: void onWiredNetworkDeviceRemoved(const QString &interface); void onWiredNetworkDeviceChanged(WiredNetworkDevice *networkDevice); +private: + static QVariantMap packWirelessAccessPoint(WirelessAccessPoint *wirelessAccessPoint); + static QVariantMap packWiredNetworkDevice(WiredNetworkDevice *networkDevice); + static QVariantMap packWirelessNetworkDevice(WirelessNetworkDevice *networkDevice); + + QVariantMap statusToReply(NetworkManager::NetworkManagerError status) const; + }; } diff --git a/libnymea-core/jsonrpc/ruleshandler.cpp b/libnymea-core/jsonrpc/ruleshandler.cpp index c1bf8d00..0ddd8d1c 100644 --- a/libnymea-core/jsonrpc/ruleshandler.cpp +++ b/libnymea-core/jsonrpc/ruleshandler.cpp @@ -65,26 +65,123 @@ namespace nymeaserver { RulesHandler::RulesHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap params; - QVariantMap returns; + // Enums + registerEnum(); + registerEnum(); + registerEnum(); + registerEnum(); + + // Objects + QVariantMap ruleDescription; + ruleDescription.insert("id", enumValueName(Uuid)); + ruleDescription.insert("name", enumValueName(String)); + ruleDescription.insert("enabled", enumValueName(Bool)); + ruleDescription.insert("active", enumValueName(Bool)); + ruleDescription.insert("executable", enumValueName(Bool)); + registerObject("RuleDescription", ruleDescription); + + QVariantMap paramDescriptor; + paramDescriptor.insert("o:paramTypeId", enumValueName(Uuid)); + paramDescriptor.insert("o:paramName", enumValueName(Uuid)); + paramDescriptor.insert("value", enumValueName(Variant)); + paramDescriptor.insert("operator", enumRef()); + registerObject("ParamDescriptor", paramDescriptor); + + QVariantMap eventDescriptor; + eventDescriptor.insert("o:eventTypeId", enumValueName(Uuid)); + eventDescriptor.insert("o:deviceId", enumValueName(Uuid)); + eventDescriptor.insert("o:interface", enumValueName(String)); + eventDescriptor.insert("o:interfaceEvent", enumValueName(String)); + eventDescriptor.insert("o:paramDescriptors", QVariantList() << objectRef("ParamDescriptor")); + registerObject("EventDescriptor", eventDescriptor); + + QVariantMap stateDescriptor; + stateDescriptor.insert("o:stateTypeId", enumValueName(Uuid)); + stateDescriptor.insert("o:deviceId", enumValueName(Uuid)); + stateDescriptor.insert("o:interface", enumValueName(String)); + stateDescriptor.insert("o:interfaceState", enumValueName(String)); + stateDescriptor.insert("value", enumValueName(Variant)); + stateDescriptor.insert("operator", enumRef()); + registerObject("StateDescriptor", stateDescriptor); + + QVariantMap stateEvaluator; + stateEvaluator.insert("o:stateDescriptor", objectRef("StateDescriptor")); + stateEvaluator.insert("o:childEvaluators", QVariantList() << objectRef("StateEvaluator")); + stateEvaluator.insert("o:operator", enumRef()); + registerObject("StateEvaluator", stateEvaluator); + + QVariantMap repeatingOption; + repeatingOption.insert("mode", enumRef()); + repeatingOption.insert("o:weekDays", QVariantList() << enumValueName(Int)); + repeatingOption.insert("o:monthDays", QVariantList() << enumValueName(Int)); + registerObject("RepeatingOption", repeatingOption); + + QVariantMap calendarItem; + calendarItem.insert("o:datetime", enumValueName(Uint)); + calendarItem.insert("o:startTime", enumValueName(Time)); + calendarItem.insert("duration", enumValueName(Uint)); + calendarItem.insert("o:repeating", objectRef("RepeatingOption")); + registerObject("CalendarItem", calendarItem); + + QVariantMap timeEventItem; + timeEventItem.insert("o:datetime", enumValueName(Uint)); + timeEventItem.insert("o:time", enumValueName(Time)); + timeEventItem.insert("o:repeating", objectRef("RepeatingOption")); + registerObject("TimeEventItem", timeEventItem); + + QVariantMap timeDescriptor; + timeDescriptor.insert("o:calendarItems", QVariantList() << objectRef("CalendarItem")); + timeDescriptor.insert("o:timeEventItems", QVariantList() << objectRef("TimeEventItem")); + registerObject("TimeDescriptor", timeDescriptor); + + QVariantMap ruleActionParam; + ruleActionParam.insert("o:paramTypeId", enumValueName(Uuid)); + ruleActionParam.insert("o:paramName", enumValueName(String)); + ruleActionParam.insert("o:value", enumValueName(Variant)); + ruleActionParam.insert("o:eventTypeId", enumValueName(Uuid)); + ruleActionParam.insert("o:eventParamTypeId", enumValueName(Uuid)); + ruleActionParam.insert("o:stateDeviceId", enumValueName(Uuid)); + ruleActionParam.insert("o:stateTypeId", enumValueName(Uuid)); + registerObject("RuleActionParam", ruleActionParam); + + QVariantMap ruleAction; + ruleAction.insert("o:deviceId", enumValueName(Uuid)); + ruleAction.insert("o:actionTypeId", enumValueName(Uuid)); + ruleAction.insert("o:interface", enumValueName(String)); + ruleAction.insert("o:interfaceAction", enumValueName(String)); + ruleAction.insert("o:browserItemId", enumValueName(String)); + ruleAction.insert("o:ruleActionParams", QVariantList() << objectRef("RuleActionParam")); + registerObject("RuleAction", ruleAction); + + QVariantMap rule; + rule.insert("id", enumValueName(Uuid)); + rule.insert("name", enumValueName(String)); + rule.insert("enabled", enumValueName(Bool)); + rule.insert("executable", enumValueName(Bool)); + rule.insert("active", enumValueName(Bool)); + rule.insert("eventDescriptors", QVariantList() << objectRef("EventDescriptor")); + rule.insert("actions", QVariantList() << objectRef("RuleAction")); + rule.insert("exitActions", QVariantList() << objectRef("RuleAction")); + rule.insert("stateEvaluator", objectRef("StateEvaluator")); + rule.insert("timeDescriptor", objectRef("TimeDescriptor")); + registerObject("Rule", rule); + + // Methods + QString description; QVariantMap params; QVariantMap returns; + description = "Get the descriptions of all configured rules. If you need more information about a specific rule use the " + "method Rules.GetRuleDetails."; + returns.insert("ruleDescriptions", QVariantList() << objectRef("RuleDescription")); + registerMethod("GetRules", description, params, returns); params.clear(); returns.clear(); - setDescription("GetRules", "Get the descriptions of all configured rules. If you need more information about a specific rule use the " - "method Rules.GetRuleDetails."); - setParams("GetRules", params); - returns.insert("ruleDescriptions", QVariantList() << JsonTypes::ruleDescriptionRef()); - setReturns("GetRules", returns); + description = "Get details for the rule identified by ruleId"; + params.insert("ruleId", enumValueName(Uuid)); + returns.insert("o:rule", objectRef("Rule")); + returns.insert("ruleError", enumRef()); + registerMethod("GetRuleDetails", description, params, returns); params.clear(); returns.clear(); - setDescription("GetRuleDetails", "Get details for the rule identified by ruleId"); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetRuleDetails", params); - returns.insert("o:rule", JsonTypes::ruleRef()); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - setReturns("GetRuleDetails", returns); - - params.clear(); returns.clear(); - setDescription("AddRule", "Add a rule. You can describe rules by one or many EventDesciptors and a StateEvaluator. " + description = "Add a rule. You can describe rules by one or many EventDesciptors and a StateEvaluator. " "Note that only one of either eventDescriptor or eventDescriptorList may be passed at a time. " "A rule can be created but left disabled, meaning it won't actually be executed until set to enabled. " "If not given, enabled defaults to true. A rule can have a list of actions and exitActions. " @@ -94,104 +191,96 @@ RulesHandler::RulesHandler(QObject *parent) : "happens and if the stateEvaluator matches the system's state. ExitActions for such rules will be " "executed when a matching event happens and the stateEvaluator is not matching the system's state. " "A rule marked as executable can be executed via the API using Rules.ExecuteRule, that means, its " - "actions will be executed regardless of the eventDescriptor and stateEvaluators."); - params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("actions", QVariantList() << JsonTypes::ruleActionRef()); - params.insert("o:timeDescriptor", JsonTypes::timeDescriptorRef()); - params.insert("o:stateEvaluator", JsonTypes::stateEvaluatorRef()); - params.insert("o:eventDescriptors", QVariantList() << JsonTypes::eventDescriptorRef()); - params.insert("o:exitActions", QVariantList() << JsonTypes::ruleActionRef()); - params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); - params.insert("o:executable", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setParams("AddRule", params); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - returns.insert("o:ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setReturns("AddRule", returns); + "actions will be executed regardless of the eventDescriptor and stateEvaluators."; + params.insert("name", enumValueName(String)); + params.insert("actions", QVariantList() << objectRef("RuleAction")); + params.insert("o:timeDescriptor", objectRef("TimeDescriptor")); + params.insert("o:stateEvaluator", objectRef("StateEvaluator")); + params.insert("o:eventDescriptors", QVariantList() << objectRef("EventDescriptor")); + params.insert("o:exitActions", QVariantList() << objectRef("RuleAction")); + params.insert("o:enabled", enumValueName(Bool)); + params.insert("o:executable", enumValueName(Bool)); + returns.insert("ruleError", enumRef()); + returns.insert("o:ruleId", enumValueName(Uuid)); + registerMethod("AddRule", description, params, returns); params.clear(); returns.clear(); - setDescription("EditRule", "Edit the parameters of a rule. The configuration of the rule with the given ruleId " + description = "Edit the parameters of a rule. The configuration of the rule with the given ruleId " "will be replaced with the new given configuration. In ordert to enable or disable a Rule, please use the " "methods \"Rules.EnableRule\" and \"Rules.DisableRule\". If successful, the notification \"Rule.RuleConfigurationChanged\" " - "will be emitted."); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("actions", QVariantList() << JsonTypes::ruleActionRef()); - params.insert("o:timeDescriptor", JsonTypes::timeDescriptorRef()); - params.insert("o:stateEvaluator", JsonTypes::stateEvaluatorRef()); - params.insert("o:eventDescriptors", QVariantList() << JsonTypes::eventDescriptorRef()); - params.insert("o:exitActions", QVariantList() << JsonTypes::ruleActionRef()); - params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); - params.insert("o:executable", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setParams("EditRule", params); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - returns.insert("o:rule", JsonTypes::ruleRef()); - setReturns("EditRule", returns); + "will be emitted."; + params.insert("ruleId", enumValueName(Uuid)); + params.insert("name", enumValueName(String)); + params.insert("actions", QVariantList() << objectRef("RuleAction")); + params.insert("o:timeDescriptor", objectRef("TimeDescriptor")); + params.insert("o:stateEvaluator", objectRef("StateEvaluator")); + params.insert("o:eventDescriptors", QVariantList() << objectRef("EventDescriptor")); + params.insert("o:exitActions", QVariantList() << objectRef("RuleAction")); + params.insert("o:enabled", enumValueName(Bool)); + params.insert("o:executable", enumValueName(Bool)); + returns.insert("ruleError", enumRef()); + returns.insert("o:rule", objectRef("Rule")); + registerMethod("EditRule", description, params, returns); params.clear(); returns.clear(); - setDescription("RemoveRule", "Remove a rule"); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("RemoveRule", params); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - setReturns("RemoveRule", returns); + description = "Remove a rule"; + params.insert("ruleId", enumValueName(Uuid)); + returns.insert("ruleError", enumRef()); + registerMethod("RemoveRule", description, params, returns); params.clear(); returns.clear(); - setDescription("FindRules", "Find a list of rules containing any of the given parameters."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("FindRules", params); - returns.insert("ruleIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setReturns("FindRules", returns); + description = "Find a list of rules containing any of the given parameters."; + params.insert("deviceId", enumValueName(Uuid)); + returns.insert("ruleIds", QVariantList() << enumValueName(Uuid)); + registerMethod("FindRules", description, params, returns); params.clear(); returns.clear(); - setDescription("EnableRule", "Enabled a rule that has previously been disabled." - "If successful, the notification \"Rule.RuleConfigurationChanged\" will be emitted."); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("EnableRule", params); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - setReturns("EnableRule", returns); + description = "Enabled a rule that has previously been disabled." + "If successful, the notification \"Rule.RuleConfigurationChanged\" will be emitted."; + params.insert("ruleId", enumValueName(Uuid)); + returns.insert("ruleError", enumRef()); + registerMethod("EnableRule", description, params, returns); params.clear(); returns.clear(); - setDescription("DisableRule", "Disable a rule. The rule won't be triggered by it's events or state changes while it is disabled. " - "If successful, the notification \"Rule.RuleConfigurationChanged\" will be emitted."); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("DisableRule", params); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - setReturns("DisableRule", returns); + description = "Disable a rule. The rule won't be triggered by it's events or state changes while it is disabled. " + "If successful, the notification \"Rule.RuleConfigurationChanged\" will be emitted."; + params.insert("ruleId", enumValueName(Uuid)); + returns.insert("ruleError", enumRef()); + registerMethod("DisableRule", description, params, returns); params.clear(); returns.clear(); - setDescription("ExecuteActions", "Execute the action list of the rule with the given ruleId."); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("ExecuteActions", params); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - setReturns("ExecuteActions", returns); + description = "Execute the action list of the rule with the given ruleId."; + params.insert("ruleId", enumValueName(Uuid)); + returns.insert("ruleError", enumRef()); + registerMethod("ExecuteActions", description, params, returns); params.clear(); returns.clear(); - setDescription("ExecuteExitActions", "Execute the exit action list of the rule with the given ruleId."); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("ExecuteExitActions", params); - returns.insert("ruleError", JsonTypes::ruleErrorRef()); - setReturns("ExecuteExitActions", returns); + description = "Execute the exit action list of the rule with the given ruleId."; + params.insert("ruleId", enumValueName(Uuid)); + returns.insert("ruleError", enumRef()); + registerMethod("ExecuteExitActions", description, params, returns); // Notifications params.clear(); returns.clear(); - setDescription("RuleRemoved", "Emitted whenever a Rule was removed."); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("RuleRemoved", params); + description = "Emitted whenever a Rule was removed."; + params.insert("ruleId", enumValueName(Uuid)); + registerNotification("RuleRemoved", description, params); params.clear(); returns.clear(); - setDescription("RuleAdded", "Emitted whenever a Rule was added."); - params.insert("rule", JsonTypes::ruleRef()); - setParams("RuleAdded", params); + description = "Emitted whenever a Rule was added."; + params.insert("rule", objectRef("Rule")); + registerNotification("RuleAdded", description, params); params.clear(); returns.clear(); - setDescription("RuleActiveChanged", "Emitted whenever the active state of a Rule changed."); - params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("active", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setParams("RuleActiveChanged", params); + description = "Emitted whenever the active state of a Rule changed."; + params.insert("ruleId", enumValueName(Uuid)); + params.insert("active", enumValueName(Bool)); + registerNotification("RuleActiveChanged", description, params); params.clear(); returns.clear(); - setDescription("RuleConfigurationChanged", "Emitted whenever the configuration of a Rule changed."); - params.insert("rule", JsonTypes::ruleRef()); - setParams("RuleConfigurationChanged", params); + description = "Emitted whenever the configuration of a Rule changed."; + params.insert("rule", objectRef("Rule")); + registerNotification("RuleConfigurationChanged", description, params); connect(NymeaCore::instance(), &NymeaCore::ruleAdded, this, &RulesHandler::ruleAddedNotification); connect(NymeaCore::instance(), &NymeaCore::ruleRemoved, this, &RulesHandler::ruleRemovedNotification); @@ -209,9 +298,13 @@ JsonReply* RulesHandler::GetRules(const QVariantMap ¶ms) { Q_UNUSED(params) - QVariantMap returns; - returns.insert("ruleDescriptions", JsonTypes::packRuleDescriptions()); + QVariantList rulesList; + foreach (const Rule &rule, NymeaCore::instance()->ruleEngine()->rules()) { + rulesList.append(packRuleDescription(rule)); + } + QVariantMap returns; + returns.insert("ruleDescriptions", rulesList); return createReply(returns); } @@ -220,16 +313,19 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap ¶ms) RuleId ruleId = RuleId(params.value("ruleId").toString()); Rule rule = NymeaCore::instance()->ruleEngine()->findRule(ruleId); if (rule.id().isNull()) { - return createReply(statusToReply(RuleEngine::RuleErrorRuleNotFound)); + QVariantMap data; + data.insert("ruleError", enumValueName(RuleEngine::RuleErrorRuleNotFound)); + return createReply(data); } - QVariantMap returns = statusToReply(RuleEngine::RuleErrorNoError); - returns.insert("rule", JsonTypes::packRule(rule)); + QVariantMap returns; + returns.insert("ruleError", enumValueName(RuleEngine::RuleErrorNoError)); + returns.insert("rule", packRule(rule)); return createReply(returns); } JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) { - Rule rule = JsonTypes::unpackRule(params); + Rule rule = unpackRule(params); rule.setId(RuleId::createRuleId()); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->addRule(rule); @@ -237,19 +333,19 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) if (status == RuleEngine::RuleErrorNoError) { returns.insert("ruleId", rule.id().toString()); } - returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); + returns.insert("ruleError", enumValueName(status)); return createReply(returns); } JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms) { - Rule rule = JsonTypes::unpackRule(params); + Rule rule = unpackRule(params); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->editRule(rule); QVariantMap returns; if (status == RuleEngine::RuleErrorNoError) { - returns.insert("rule", JsonTypes::packRule(NymeaCore::instance()->ruleEngine()->findRule(rule.id()))); + returns.insert("rule", packRule(NymeaCore::instance()->ruleEngine()->findRule(rule.id()))); } - returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); + returns.insert("ruleError", enumValueName(status)); return createReply(returns); } @@ -258,7 +354,7 @@ JsonReply* RulesHandler::RemoveRule(const QVariantMap ¶ms) QVariantMap returns; RuleId ruleId(params.value("ruleId").toString()); RuleEngine::RuleError status = NymeaCore::instance()->removeRule(ruleId); - returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); + returns.insert("ruleError", enumValueName(status)); return createReply(returns); } @@ -279,12 +375,18 @@ JsonReply *RulesHandler::FindRules(const QVariantMap ¶ms) JsonReply *RulesHandler::EnableRule(const QVariantMap ¶ms) { - return createReply(statusToReply(NymeaCore::instance()->ruleEngine()->enableRule(RuleId(params.value("ruleId").toString())))); + RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->enableRule(RuleId(params.value("ruleId").toString())); + QVariantMap ret; + ret.insert("ruleError", enumValueName(status)); + return createReply(ret); } JsonReply *RulesHandler::DisableRule(const QVariantMap ¶ms) { - return createReply(statusToReply(NymeaCore::instance()->ruleEngine()->disableRule(RuleId(params.value("ruleId").toString())))); + RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->disableRule(RuleId(params.value("ruleId").toString())); + QVariantMap ret; + ret.insert("ruleError", enumValueName(status)); + return createReply(ret); } JsonReply *RulesHandler::ExecuteActions(const QVariantMap ¶ms) @@ -292,7 +394,7 @@ JsonReply *RulesHandler::ExecuteActions(const QVariantMap ¶ms) QVariantMap returns; RuleId ruleId(params.value("ruleId").toString()); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeActions(ruleId); - returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); + returns.insert("ruleError", enumValueName(status)); return createReply(returns); } @@ -301,7 +403,7 @@ JsonReply *RulesHandler::ExecuteExitActions(const QVariantMap ¶ms) QVariantMap returns; RuleId ruleId(params.value("ruleId").toString()); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeExitActions(ruleId); - returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); + returns.insert("ruleError", enumValueName(status)); return createReply(returns); } @@ -316,7 +418,7 @@ void RulesHandler::ruleRemovedNotification(const RuleId &ruleId) void RulesHandler::ruleAddedNotification(const Rule &rule) { QVariantMap params; - params.insert("rule", JsonTypes::packRule(rule)); + params.insert("rule", packRule(rule)); emit RuleAdded(params); } @@ -333,9 +435,484 @@ void RulesHandler::ruleActiveChangedNotification(const Rule &rule) void RulesHandler::ruleConfigurationChangedNotification(const Rule &rule) { QVariantMap params; - params.insert("rule", JsonTypes::packRule(rule)); + params.insert("rule", packRule(rule)); emit RuleConfigurationChanged(params); } +QVariantMap RulesHandler::packRuleDescription(const Rule &rule) +{ + QVariantMap ruleDescriptionMap; + ruleDescriptionMap.insert("id", rule.id().toString()); + ruleDescriptionMap.insert("name", rule.name()); + ruleDescriptionMap.insert("enabled", rule.enabled()); + ruleDescriptionMap.insert("active", rule.active()); + ruleDescriptionMap.insert("executable", rule.executable()); + return ruleDescriptionMap; +} + +QVariantMap RulesHandler::packParamDescriptor(const ParamDescriptor ¶mDescriptor) +{ + QVariantMap variantMap; + if (!paramDescriptor.paramTypeId().isNull()) { + variantMap.insert("paramTypeId", paramDescriptor.paramTypeId().toString()); + } else { + variantMap.insert("paramName", paramDescriptor.paramName()); + } + variantMap.insert("value", paramDescriptor.value()); + variantMap.insert("operator", enumValueName(paramDescriptor.operatorType())); + return variantMap; +} + +QVariantMap RulesHandler::packEventDescriptor(const EventDescriptor &eventDescriptor) +{ + QVariantMap variant; + if (eventDescriptor.type() == EventDescriptor::TypeDevice) { + variant.insert("eventTypeId", eventDescriptor.eventTypeId().toString()); + variant.insert("deviceId", eventDescriptor.deviceId().toString()); + } else { + variant.insert("interface", eventDescriptor.interface()); + variant.insert("interfaceEvent", eventDescriptor.interfaceEvent()); + } + QVariantList params; + foreach (const ParamDescriptor ¶mDescriptor, eventDescriptor.paramDescriptors()) + params.append(packParamDescriptor(paramDescriptor)); + + variant.insert("paramDescriptors", params); + return variant; +} + +QVariantMap RulesHandler::packStateEvaluator(const StateEvaluator &stateEvaluator) +{ + QVariantMap variantMap; + if (stateEvaluator.stateDescriptor().isValid()) + variantMap.insert("stateDescriptor", packStateDescriptor(stateEvaluator.stateDescriptor())); + + QVariantList childEvaluators; + foreach (const StateEvaluator &childEvaluator, stateEvaluator.childEvaluators()) + childEvaluators.append(packStateEvaluator(childEvaluator)); + + if (!childEvaluators.isEmpty() || stateEvaluator.stateDescriptor().isValid()) + variantMap.insert("operator", enumValueName(stateEvaluator.operatorType())); + + if (childEvaluators.count() > 0) + variantMap.insert("childEvaluators", childEvaluators); + + return variantMap; +} + +QVariantMap RulesHandler::packStateDescriptor(const StateDescriptor &stateDescriptor) +{ + QVariantMap variantMap; + if (stateDescriptor.type() == StateDescriptor::TypeDevice) { + variantMap.insert("stateTypeId", stateDescriptor.stateTypeId().toString()); + variantMap.insert("deviceId", stateDescriptor.deviceId().toString()); + } else { + variantMap.insert("interface", stateDescriptor.interface()); + variantMap.insert("interfaceState", stateDescriptor.interfaceState()); + } + variantMap.insert("value", stateDescriptor.stateValue()); + variantMap.insert("operator", enumValueName(stateDescriptor.operatorType())); + return variantMap; +} + +QVariantMap RulesHandler::packTimeDescriptor(const TimeDescriptor &timeDescriptor) +{ + QVariantMap timeDescriptorVariant; + + if (!timeDescriptor.calendarItems().isEmpty()) { + QVariantList calendarItems; + foreach (const CalendarItem &calendarItem, timeDescriptor.calendarItems()) + calendarItems.append(packCalendarItem(calendarItem)); + + timeDescriptorVariant.insert("calendarItems", calendarItems); + } + + if (!timeDescriptor.timeEventItems().isEmpty()) { + QVariantList timeEventItems; + foreach (const TimeEventItem &timeEventItem, timeDescriptor.timeEventItems()) + timeEventItems.append(packTimeEventItem(timeEventItem)); + + timeDescriptorVariant.insert("timeEventItems", timeEventItems); + } + + return timeDescriptorVariant; +} + +QVariantMap RulesHandler::packCalendarItem(const CalendarItem &calendarItem) +{ + QVariantMap calendarItemVariant; + calendarItemVariant.insert("duration", calendarItem.duration()); + + if (!calendarItem.dateTime().isNull() && calendarItem.dateTime().toTime_t() != 0) + calendarItemVariant.insert("datetime", calendarItem.dateTime().toTime_t()); + + if (!calendarItem.startTime().isNull()) + calendarItemVariant.insert("startTime", calendarItem.startTime().toString("hh:mm")); + + if (!calendarItem.repeatingOption().isEmtpy()) + calendarItemVariant.insert("repeating", packRepeatingOption(calendarItem.repeatingOption())); + + return calendarItemVariant; +} + +QVariantMap RulesHandler::packRepeatingOption(const RepeatingOption &option) +{ + QVariantMap optionVariant; + optionVariant.insert("mode", enumValueName(option.mode())); + if (!option.weekDays().isEmpty()) { + QVariantList weekDaysVariantList; + foreach (const int& weekDay, option.weekDays()) + weekDaysVariantList.append(QVariant(weekDay)); + + optionVariant.insert("weekDays", weekDaysVariantList); + } + + if (!option.monthDays().isEmpty()) { + QVariantList monthDaysVariantList; + foreach (const int& monthDay, option.monthDays()) + monthDaysVariantList.append(QVariant(monthDay)); + + optionVariant.insert("monthDays", monthDaysVariantList); + } + return optionVariant; +} + +QVariantMap RulesHandler::packTimeEventItem(const TimeEventItem &timeEventItem) +{ + QVariantMap timeEventItemVariant; + + if (!timeEventItem.dateTime().isNull() && timeEventItem.dateTime().toTime_t() != 0) + timeEventItemVariant.insert("datetime", timeEventItem.dateTime().toTime_t()); + + if (!timeEventItem.time().isNull()) + timeEventItemVariant.insert("time", timeEventItem.time().toString("hh:mm")); + + if (!timeEventItem.repeatingOption().isEmtpy()) + timeEventItemVariant.insert("repeating", packRepeatingOption(timeEventItem.repeatingOption())); + + return timeEventItemVariant; +} + +QVariantMap RulesHandler::packRuleActionParam(const RuleActionParam &ruleActionParam) +{ + QVariantMap variantMap; + if (!ruleActionParam.paramTypeId().isNull()) { + variantMap.insert("paramTypeId", ruleActionParam.paramTypeId().toString()); + } else { + variantMap.insert("paramName", ruleActionParam.paramName()); + } + + if (ruleActionParam.isEventBased()) { + variantMap.insert("eventTypeId", ruleActionParam.eventTypeId().toString()); + variantMap.insert("eventParamTypeId", ruleActionParam.eventParamTypeId().toString()); + } else if (ruleActionParam.isStateBased()) { + variantMap.insert("stateDeviceId", ruleActionParam.stateDeviceId().toString()); + variantMap.insert("stateTypeId", ruleActionParam.stateTypeId().toString()); + } else { + variantMap.insert("value", ruleActionParam.value()); + } + return variantMap; +} + +QVariantMap RulesHandler::packRuleAction(const RuleAction &ruleAction) +{ + QVariantMap variant; + if (ruleAction.type() == RuleAction::TypeDevice) { + variant.insert("deviceId", ruleAction.deviceId().toString()); + variant.insert("actionTypeId", ruleAction.actionTypeId().toString()); + } else if (ruleAction.type() == RuleAction::TypeBrowser) { + variant.insert("deviceId", ruleAction.deviceId().toString()); + variant.insert("browserItemId", ruleAction.browserItemId()); + } else { + variant.insert("interface", ruleAction.interface()); + variant.insert("interfaceAction", ruleAction.interfaceAction()); + } + QVariantList params; + foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) + params.append(packRuleActionParam(ruleActionParam)); + + variant.insert("ruleActionParams", params); + return variant; +} + +QVariantMap RulesHandler::packRule(const Rule &rule) +{ + QVariantMap ruleMap; + ruleMap.insert("id", rule.id().toString()); + ruleMap.insert("name", rule.name()); + ruleMap.insert("enabled", rule.enabled()); + ruleMap.insert("active", rule.active()); + ruleMap.insert("executable", rule.executable()); + ruleMap.insert("timeDescriptor", packTimeDescriptor(rule.timeDescriptor())); + + QVariantList eventDescriptorList; + foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) + eventDescriptorList.append(packEventDescriptor(eventDescriptor)); + + ruleMap.insert("eventDescriptors", eventDescriptorList); + ruleMap.insert("stateEvaluator", packStateEvaluator(rule.stateEvaluator())); + + QVariantList actionList; + foreach (const RuleAction &action, rule.actions()) + actionList.append(packRuleAction(action)); + + ruleMap.insert("actions", actionList); + + QVariantList exitActionList; + foreach (const RuleAction &action, rule.exitActions()) + exitActionList.append(packRuleAction(action)); + + ruleMap.insert("exitActions", exitActionList); + return ruleMap; +} + +QList RulesHandler::unpackParamDescriptors(const QVariantList ¶mList) +{ + QList params; + foreach (const QVariant ¶mVariant, paramList) + params.append(unpackParamDescriptor(paramVariant.toMap())); + + return params; +} + +ParamDescriptor RulesHandler::unpackParamDescriptor(const QVariantMap ¶mMap) +{ + QString operatorString = paramMap.value("operator").toString(); + Types::ValueOperator valueOperator = enumNameToValue(operatorString); + + if (paramMap.contains("paramTypeId")) { + ParamDescriptor param = ParamDescriptor(ParamTypeId(paramMap.value("paramTypeId").toString()), paramMap.value("value")); + param.setOperatorType(valueOperator); + return param; + } + ParamDescriptor param = ParamDescriptor(paramMap.value("paramName").toString(), paramMap.value("value")); + param.setOperatorType(valueOperator); + return param; +} + +EventDescriptor RulesHandler::unpackEventDescriptor(const QVariantMap &eventDescriptorMap) +{ + EventTypeId eventTypeId(eventDescriptorMap.value("eventTypeId").toString()); + DeviceId eventDeviceId(eventDescriptorMap.value("deviceId").toString()); + QString interface = eventDescriptorMap.value("interface").toString(); + QString interfaceEvent = eventDescriptorMap.value("interfaceEvent").toString(); + QList eventParams = unpackParamDescriptors(eventDescriptorMap.value("paramDescriptors").toList()); + if (!eventDeviceId.isNull() && !eventTypeId.isNull()) { + return EventDescriptor(eventTypeId, eventDeviceId, eventParams); + } + return EventDescriptor(interface, interfaceEvent, eventParams); +} + +RepeatingOption RulesHandler::unpackRepeatingOption(const QVariantMap &repeatingOptionMap) +{ + RepeatingOption::RepeatingMode mode = enumNameToValue(repeatingOptionMap.value("mode").toString()); + + QList weekDays; + if (repeatingOptionMap.contains("weekDays")) { + foreach (const QVariant weekDayVariant, repeatingOptionMap.value("weekDays").toList()) { + weekDays.append(weekDayVariant.toInt()); + } + } + + QList monthDays; + if (repeatingOptionMap.contains("monthDays")) { + foreach (const QVariant monthDayVariant, repeatingOptionMap.value("monthDays").toList()) { + monthDays.append(monthDayVariant.toInt()); + } + } + + return RepeatingOption(mode, weekDays, monthDays); +} + +CalendarItem RulesHandler::unpackCalendarItem(const QVariantMap &calendarItemMap) +{ + CalendarItem calendarItem; + calendarItem.setDuration(calendarItemMap.value("duration").toUInt()); + + if (calendarItemMap.contains("datetime")) + calendarItem.setDateTime(QDateTime::fromTime_t(calendarItemMap.value("datetime").toUInt())); + + if (calendarItemMap.contains("startTime")) + calendarItem.setStartTime(QTime::fromString(calendarItemMap.value("startTime").toString(), "hh:mm")); + + if (calendarItemMap.contains("repeating")) + calendarItem.setRepeatingOption(unpackRepeatingOption(calendarItemMap.value("repeating").toMap())); + + return calendarItem; +} + +TimeDescriptor RulesHandler::unpackTimeDescriptor(const QVariantMap &timeDescriptorMap) +{ + TimeDescriptor timeDescriptor; + + if (timeDescriptorMap.contains("calendarItems")) { + QList calendarItems; + foreach (const QVariant &calendarItemValiant, timeDescriptorMap.value("calendarItems").toList()) { + calendarItems.append(unpackCalendarItem(calendarItemValiant.toMap())); + } + timeDescriptor.setCalendarItems(calendarItems); + } + + if (timeDescriptorMap.contains("timeEventItems")) { + QList timeEventItems; + foreach (const QVariant &timeEventItemValiant, timeDescriptorMap.value("timeEventItems").toList()) { + timeEventItems.append(unpackTimeEventItem(timeEventItemValiant.toMap())); + } + timeDescriptor.setTimeEventItems(timeEventItems); + } + + return timeDescriptor; +} + +TimeEventItem RulesHandler::unpackTimeEventItem(const QVariantMap &timeEventItemMap) +{ + TimeEventItem timeEventItem; + + if (timeEventItemMap.contains("datetime")) + timeEventItem.setDateTime(timeEventItemMap.value("datetime").toUInt()); + + if (timeEventItemMap.contains("time")) + timeEventItem.setTime(timeEventItemMap.value("time").toTime()); + + if (timeEventItemMap.contains("repeating")) + timeEventItem.setRepeatingOption(unpackRepeatingOption(timeEventItemMap.value("repeating").toMap())); + + return timeEventItem; +} + +StateDescriptor RulesHandler::unpackStateDescriptor(const QVariantMap &stateDescriptorMap) +{ + StateTypeId stateTypeId(stateDescriptorMap.value("stateTypeId").toString()); + DeviceId deviceId(stateDescriptorMap.value("deviceId").toString()); + QString interface(stateDescriptorMap.value("interface").toString()); + QString interfaceState(stateDescriptorMap.value("interfaceState").toString()); + QVariant value = stateDescriptorMap.value("value"); + Types::ValueOperator operatorType = enumNameToValue(stateDescriptorMap.value("operator").toString()); + if (!deviceId.isNull() && !stateTypeId.isNull()) { + StateDescriptor stateDescriptor(stateTypeId, deviceId, value, operatorType); + return stateDescriptor; + } + StateDescriptor stateDescriptor(interface, interfaceState, value, operatorType); + return stateDescriptor; +} + +StateEvaluator RulesHandler::unpackStateEvaluator(const QVariantMap &stateEvaluatorMap) +{ + StateEvaluator ret(unpackStateDescriptor(stateEvaluatorMap.value("stateDescriptor").toMap())); + if (stateEvaluatorMap.contains("operator")) { + ret.setOperatorType(enumNameToValue(stateEvaluatorMap.value("operator").toString())); + } else { + ret.setOperatorType(Types::StateOperatorAnd); + } + + QList childEvaluators; + foreach (const QVariant &childEvaluator, stateEvaluatorMap.value("childEvaluators").toList()) + childEvaluators.append(unpackStateEvaluator(childEvaluator.toMap())); + + ret.setChildEvaluators(childEvaluators); + return ret; +} + +RuleActionParam RulesHandler::unpackRuleActionParam(const QVariantMap &ruleActionParamMap) +{ + if (ruleActionParamMap.keys().count() == 0) + return RuleActionParam(); + + ParamTypeId paramTypeId = ParamTypeId(ruleActionParamMap.value("paramTypeId").toString()); + QString paramName = ruleActionParamMap.value("paramName").toString(); + + RuleActionParam param; + if (paramTypeId.isNull()) { + param = RuleActionParam(paramName); + } else { + param = RuleActionParam(paramTypeId); + } + param.setValue(ruleActionParamMap.value("value")); + param.setEventTypeId(EventTypeId(ruleActionParamMap.value("eventTypeId").toString())); + param.setEventParamTypeId(ParamTypeId(ruleActionParamMap.value("eventParamTypeId").toString())); + param.setStateDeviceId(DeviceId(ruleActionParamMap.value("stateDeviceId").toString())); + param.setStateTypeId(StateTypeId(ruleActionParamMap.value("stateTypeId").toString())); + return param; +} + +RuleActionParamList RulesHandler::unpackRuleActionParams(const QVariantList &ruleActionParamList) +{ + RuleActionParamList ruleActionParams; + foreach (const QVariant ¶mVariant, ruleActionParamList) + ruleActionParams.append(unpackRuleActionParam(paramVariant.toMap())); + + return ruleActionParams; +} + +RuleAction RulesHandler::unpackRuleAction(const QVariantMap &ruleActionMap) +{ + ActionTypeId actionTypeId(ruleActionMap.value("actionTypeId").toString()); + DeviceId actionDeviceId(ruleActionMap.value("deviceId").toString()); + QString interface = ruleActionMap.value("interface").toString(); + QString interfaceAction = ruleActionMap.value("interfaceAction").toString(); + QString browserItemId = ruleActionMap.value("browserItemId").toString(); + RuleActionParamList actionParamList = unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList()); + + if (!actionDeviceId.isNull() && !actionTypeId.isNull()) { + return RuleAction(actionTypeId, actionDeviceId, actionParamList); + } else if (!actionDeviceId.isNull() && !browserItemId.isNull()) { + return RuleAction(actionDeviceId, browserItemId); + } + return RuleAction(interface, interfaceAction, actionParamList); +} + +Rule RulesHandler::unpackRule(const QVariantMap &ruleMap) +{ + // The rule id will only be valid if unpacking for edit + RuleId ruleId = RuleId(ruleMap.value("ruleId").toString()); + + QString name = ruleMap.value("name", QString()).toString(); + + // By default enabled + bool enabled = ruleMap.value("enabled", true).toBool(); + + // By default executable + bool executable = ruleMap.value("executable", true).toBool(); + + StateEvaluator stateEvaluator = unpackStateEvaluator(ruleMap.value("stateEvaluator").toMap()); + TimeDescriptor timeDescriptor = unpackTimeDescriptor(ruleMap.value("timeDescriptor").toMap()); + + QList eventDescriptors; + if (ruleMap.contains("eventDescriptors")) { + QVariantList eventDescriptorVariantList = ruleMap.value("eventDescriptors").toList(); + foreach (const QVariant &eventDescriptorVariant, eventDescriptorVariantList) { + eventDescriptors.append(unpackEventDescriptor(eventDescriptorVariant.toMap())); + } + } + + QList actions; + if (ruleMap.contains("actions")) { + QVariantList actionsVariantList = ruleMap.value("actions").toList(); + foreach (const QVariant &actionVariant, actionsVariantList) { + actions.append(unpackRuleAction(actionVariant.toMap())); + } + } + + QList exitActions; + if (ruleMap.contains("exitActions")) { + QVariantList exitActionsVariantList = ruleMap.value("exitActions").toList(); + foreach (const QVariant &exitActionVariant, exitActionsVariantList) { + exitActions.append(unpackRuleAction(exitActionVariant.toMap())); + } + } + + Rule rule; + rule.setId(ruleId); + rule.setName(name); + rule.setTimeDescriptor(timeDescriptor); + rule.setStateEvaluator(stateEvaluator); + rule.setEventDescriptors(eventDescriptors); + rule.setActions(actions); + rule.setExitActions(exitActions); + rule.setEnabled(enabled); + rule.setExecutable(executable); + return rule; +} + } diff --git a/libnymea-core/jsonrpc/ruleshandler.h b/libnymea-core/jsonrpc/ruleshandler.h index 0a8d504d..c6a65595 100644 --- a/libnymea-core/jsonrpc/ruleshandler.h +++ b/libnymea-core/jsonrpc/ruleshandler.h @@ -22,7 +22,9 @@ #ifndef RULESHANDLER_H #define RULESHANDLER_H -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" + +#include "ruleengine/rule.h" namespace nymeaserver { @@ -30,7 +32,7 @@ class RulesHandler : public JsonHandler { Q_OBJECT public: - explicit RulesHandler(QObject *parent = 0); + explicit RulesHandler(QObject *parent = nullptr); QString name() const override; @@ -60,6 +62,37 @@ private slots: void ruleActiveChangedNotification(const Rule &rule); void ruleConfigurationChangedNotification(const Rule &rule); +private: + static QVariantMap packRuleDescription(const Rule &rule); + static QVariantMap packParamDescriptor(const ParamDescriptor ¶mDescriptor); + static QVariantMap packEventDescriptor(const EventDescriptor &eventDescriptor); + static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator); + static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor); + static QVariantMap packTimeDescriptor(const TimeDescriptor &timeDescriptor); + static QVariantMap packCalendarItem(const CalendarItem &calendarItem); + static QVariantMap packRepeatingOption(const RepeatingOption &option); + static QVariantMap packTimeEventItem(const TimeEventItem &timeEventItem); + static QVariantMap packRuleActionParam(const RuleActionParam &ruleActionParam); + static QVariantMap packRuleAction(const RuleAction &ruleAction); + + static QVariantMap packRule(const Rule &rule); + + static QList unpackParamDescriptors(const QVariantList ¶mList); + static ParamDescriptor unpackParamDescriptor(const QVariantMap ¶mMap); + static EventDescriptor unpackEventDescriptor(const QVariantMap &eventDescriptorMap); + static RepeatingOption unpackRepeatingOption(const QVariantMap &repeatingOptionMap); + static CalendarItem unpackCalendarItem(const QVariantMap &calendarItemMap); + static TimeDescriptor unpackTimeDescriptor(const QVariantMap &timeDescriptorMap); + static TimeEventItem unpackTimeEventItem(const QVariantMap &timeEventItemMap); + static StateDescriptor unpackStateDescriptor(const QVariantMap &stateDescriptorMap); + static StateEvaluator unpackStateEvaluator(const QVariantMap &stateEvaluatorMap); + static RuleActionParam unpackRuleActionParam(const QVariantMap &ruleActionParamMap); + static RuleActionParamList unpackRuleActionParams(const QVariantList &ruleActionParamList); + static RuleAction unpackRuleAction(const QVariantMap &ruleActionMap); + + static Rule unpackRule(const QVariantMap &ruleMap); + + }; } diff --git a/libnymea-core/jsonrpc/statehandler.cpp b/libnymea-core/jsonrpc/statehandler.cpp index a25e2b52..2ede3ded 100644 --- a/libnymea-core/jsonrpc/statehandler.cpp +++ b/libnymea-core/jsonrpc/statehandler.cpp @@ -33,6 +33,7 @@ */ #include "statehandler.h" +#include "devicehandler.h" #include "nymeacore.h" #include "loggingcategories.h" @@ -42,16 +43,19 @@ namespace nymeaserver { StateHandler::StateHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap params; - QVariantMap returns; + QVariantMap state; + state.insert("stateTypeId", enumValueName(Uuid)); + state.insert("deviceId", enumValueName(Uuid)); + state.insert("value", enumValueName(Variant)); + registerObject("State", state); - params.clear(); returns.clear(); - setDescription("GetStateType", "Get the StateType for the given stateTypeId."); - params.insert("stateTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - setParams("GetStateType", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - returns.insert("o:stateType", JsonTypes::stateTypeRef()); - setReturns("GetStateType", returns); + // Methods + QString description; QVariantMap params; QVariantMap returns; + description = "Get the StateType for the given stateTypeId."; + params.insert("stateTypeId", enumValueName(Uuid)); + returns.insert("deviceError", enumRef()); + returns.insert("o:stateType", objectRef("StateType")); + registerMethod("GetStateType", description, params, returns, true); } /*! Returns the name of the \l{StateHandler}. In this case \b States.*/ @@ -67,13 +71,16 @@ JsonReply* StateHandler::GetStateType(const QVariantMap ¶ms) const foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const StateType &stateType, deviceClass.stateTypes()) { if (stateType.id() == stateTypeId) { - QVariantMap data = statusToReply(Device::DeviceErrorNoError); - data.insert("stateType", JsonTypes::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); + QVariantMap data; + data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); + data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); return createReply(data); } } } - return createReply(statusToReply(Device::DeviceErrorStateTypeNotFound)); + QVariantMap data; + data.insert("deviceError", enumValueName(Device::DeviceErrorStateTypeNotFound)); + return createReply(data); } } diff --git a/libnymea-core/jsonrpc/statehandler.h b/libnymea-core/jsonrpc/statehandler.h index 7b4589e1..4ad977ec 100644 --- a/libnymea-core/jsonrpc/statehandler.h +++ b/libnymea-core/jsonrpc/statehandler.h @@ -22,7 +22,7 @@ #ifndef STATEHANDLER_H #define STATEHANDLER_H -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" namespace nymeaserver { @@ -30,7 +30,7 @@ class StateHandler : public JsonHandler { Q_OBJECT public: - explicit StateHandler(QObject *parent = 0); + explicit StateHandler(QObject *parent = nullptr); QString name() const override; Q_INVOKABLE JsonReply *GetStateType(const QVariantMap ¶ms) const; diff --git a/libnymea-core/jsonrpc/systemhandler.cpp b/libnymea-core/jsonrpc/systemhandler.cpp index 3b16c84a..d1c3e367 100644 --- a/libnymea-core/jsonrpc/systemhandler.cpp +++ b/libnymea-core/jsonrpc/systemhandler.cpp @@ -32,146 +32,148 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): JsonHandler(parent), m_platform(platform) { + // Objects + QVariantMap package; + package.insert("id", enumValueName(String)); + package.insert("displayName", enumValueName(String)); + package.insert("summary", enumValueName(String)); + package.insert("installedVersion", enumValueName(String)); + package.insert("candidateVersion", enumValueName(String)); + package.insert("changelog", enumValueName(String)); + package.insert("updateAvailable", enumValueName(Bool)); + package.insert("rollbackAvailable", enumValueName(Bool)); + package.insert("canRemove", enumValueName(Bool)); + registerObject("Package", package); + + QVariantMap repository; + repository.insert("id", enumValueName(String)); + repository.insert("displayName", enumValueName(String)); + repository.insert("enabled", enumValueName(Bool)); + registerObject("Repository", repository); + // Methods - QVariantMap params; QVariantMap returns; - setDescription("GetCapabilities", "Get the list of capabilites on this system. This allows reading whether things like rebooting or shutting down the system running nymea:core is supported on this host."); - setParams("GetCapabilities", params); - returns.insert("powerManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("updateManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("GetCapabilities", returns); + QString description; QVariantMap params; QVariantMap returns; + description = "Get the list of capabilites on this system. This allows reading whether things like rebooting or shutting down the system running nymea:core is supported on this host."; + returns.insert("powerManagement", enumValueName(Bool)); + returns.insert("updateManagement", enumValueName(Bool)); + registerMethod("GetCapabilities", description, params, returns); params.clear(); returns.clear(); - setDescription("Reboot", "Initiate a reboot of the system. The return value will indicate whether the procedure has been initiated successfully."); - setParams("Reboot", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("Reboot", returns); + description = "Initiate a reboot of the system. The return value will indicate whether the procedure has been initiated successfully."; + returns.insert("success", enumValueName(Bool)); + registerMethod("Reboot", description, params, returns); params.clear(); returns.clear(); - setDescription("Shutdown", "Initiate a shutdown of the system. The return value will indicate whether the procedure has been initiated successfully."); - setParams("Shutdown", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("Shutdown", returns); + description = "Initiate a shutdown of the system. The return value will indicate whether the procedure has been initiated successfully."; + returns.insert("success", enumValueName(Bool)); + registerMethod("Shutdown", description, params, returns); params.clear(); returns.clear(); - setDescription("GetUpdateStatus", - "Get the current status of the update system. \"busy\" indicates that the system is current busy with " + description = "Get the current status of the update system. \"busy\" indicates that the system is current busy with " "an operation regarding updates. This does not necessarily mean an actual update is running. When this " "is true, update related functions on the client should be marked as busy and no interaction with update " "components shall be allowed. An example for such a state is when the system queries the server if there " "are updates available, typically after a call to CheckForUpdates. \"updateRunning\" on the other hand " "indicates an actual update process is ongoing. The user should be informed about it, the system also " - "might restart at any point while an update is running."); - setParams("GetUpdateStatus", params); - returns.insert("busy", JsonTypes::basicTypeToString(JsonTypes::Bool)); - returns.insert("updateRunning", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("GetUpdateStatus", returns); + "might restart at any point while an update is running."; + returns.insert("busy", enumValueName(Bool)); + returns.insert("updateRunning", enumValueName(Bool)); + registerMethod("GetUpdateStatus", description, params, returns); params.clear(); returns.clear(); - setDescription("CheckForUpdates", - "Instruct the system to poll the server for updates. Normally the system should automatically do this " + description = "Instruct the system to poll the server for updates. Normally the system should automatically do this " "in regular intervals, however, if the client wants to allow the user to manually check for new updates " "now, this can be called. Returns true if the operation has been started successfully and the update " "manager will become busy. In order to know whether there are updates available, clients should walk through " "the list of packages retrieved from GetPackages and check whether there are packages with the updateAvailable " - "flag set to true."); - setParams("CheckForUpdates", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("CheckForUpdates", returns); + "flag set to true."; + returns.insert("success", enumValueName(Bool)); + registerMethod("CheckForUpdates", description, params, returns); params.clear(); returns.clear(); - setDescription("GetPackages", - "Get the list of packages currently available to the system. This might include installed available but " - "not installed packages. Installed packages will have the installedVersion set to a non-empty value."); - setParams("GetPackages", params); - returns.insert("packages", QVariantList() << JsonTypes::packageRef()); - setReturns("GetPackages", returns); + description = "Get the list of packages currently available to the system. This might include installed available but " + "not installed packages. Installed packages will have the installedVersion set to a non-empty value."; + returns.insert("packages", QVariantList() << objectRef("Package")); + registerMethod("GetPackages", description, params, returns); params.clear(); returns.clear(); - setDescription("UpdatePackages", - "Starts updating/installing packages with the given ids. Returns true if the upgrade has been started " + description = "Starts updating/installing packages with the given ids. Returns true if the upgrade has been started " "successfully. Note that it might still fail later. Before calling this method, clients should " "check the packages whether they are in a state where they can either be installed (no installedVersion " - "set) or upgraded (updateAvailable set to true)."); - params.insert("o:packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("UpdatePackages", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("UpdatePackages", returns); + "set) or upgraded (updateAvailable set to true)."; + params.insert("o:packageIds", QVariantList() << enumValueName(String)); + returns.insert("success", enumValueName(Bool)); + registerMethod("UpdatePackages", description, params, returns); params.clear(); returns.clear(); - setDescription("RollbackPackages", - "Starts a rollback. Returns true if the rollback has been started successfully. Before calling this " - "method, clients should check whether the package can be rolled back (canRollback set to true)."); - params.insert("packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("RollbackPackages", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("RollbackPackages", returns); + description = "Starts a rollback. Returns true if the rollback has been started successfully. Before calling this " + "method, clients should check whether the package can be rolled back (canRollback set to true)."; + params.insert("packageIds", QVariantList() << enumValueName(String)); + returns.insert("success", enumValueName(Bool)); + registerMethod("RollbackPackages", description, params, returns); params.clear(); returns.clear(); - setDescription("RemovePackages", - "Starts removing a package. Returns true if the removal has been started successfully. Before calling " - "this method, clients should check whether the package can be removed (canRemove set to true)."); - params.insert("packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("RemovePackages", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("RemovePackages", returns); + description = "Starts removing a package. Returns true if the removal has been started successfully. Before calling " + "this method, clients should check whether the package can be removed (canRemove set to true)."; + params.insert("packageIds", QVariantList() << enumValueName(String)); + returns.insert("success", enumValueName(Bool)); + registerMethod("RemovePackages", description, params, returns); params.clear(); returns.clear(); - setDescription("GetRepositories", "Get the list of repositories currently available to the system."); - setParams("GetRepositories", params); - returns.insert("repositories", QVariantList() << JsonTypes::repositoryRef()); - setReturns("GetRepositories", returns); + description = "Get the list of repositories currently available to the system."; + returns.insert("repositories", QVariantList() << objectRef("Repository")); + registerMethod("GetRepositories", description, params, returns); params.clear(); returns.clear(); - setDescription("EnableRepository", "Enable or disable a repository."); - params.insert("repositoryId", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setParams("EnableRepository", params); - returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setReturns("EnableRepository", returns); + description = "Enable or disable a repository."; + params.insert("repositoryId", enumValueName(String)); + params.insert("enabled", enumValueName(Bool)); + returns.insert("success", enumValueName(Bool)); + registerMethod("EnableRepository", description, params, returns); // Notifications params.clear(); - setDescription("CapabilitiesChanged", "Emitted whenever the system capabilities change."); - params.insert("powerManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); - params.insert("updateManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setParams("CapabilitiesChanged", params); + description = "Emitted whenever the system capabilities change."; + params.insert("powerManagement", enumValueName(Bool)); + params.insert("updateManagement", enumValueName(Bool)); + registerNotification("CapabilitiesChanged", description, params); params.clear(); - setDescription("UpdateStatusChanged", "Emitted whenever the update status changes."); - params.insert("busy", JsonTypes::basicTypeToString(JsonTypes::Bool)); - params.insert("updateRunning", JsonTypes::basicTypeToString(JsonTypes::Bool)); - setParams("UpdateStatusChanged", params); + description = "Emitted whenever the update status changes."; + params.insert("busy", enumValueName(Bool)); + params.insert("updateRunning", enumValueName(Bool)); + registerNotification("UpdateStatusChanged", description, params); params.clear(); - setDescription("PackageAdded", "Emitted whenever a package is added to the list of packages."); - params.insert("package", JsonTypes::packageRef()); - setParams("PackageAdded", params); + description = "Emitted whenever a package is added to the list of packages."; + params.insert("package", objectRef("Package")); + registerNotification("PackageAdded", description, params); params.clear(); - setDescription("PackageChanged", "Emitted whenever a package in the list of packages changes."); - params.insert("package", JsonTypes::packageRef()); - setParams("PackageChanged", params); + description = "Emitted whenever a package in the list of packages changes."; + params.insert("package", objectRef("Package")); + registerNotification("PackageChanged", description, params); params.clear(); - setDescription("PackageRemoved", "Emitted whenever a package is removed from the list of packages."); - params.insert("packageId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("PackageRemoved", params); + description = "Emitted whenever a package is removed from the list of packages."; + params.insert("packageId", enumValueName(String)); + registerNotification("PackageRemoved", description, params); params.clear(); - setDescription("RepositoryAdded", "Emitted whenever a repository is added to the list of repositories."); - params.insert("repository", JsonTypes::repositoryRef()); - setParams("RepositoryAdded", params); + description = "Emitted whenever a repository is added to the list of repositories."; + params.insert("repository", objectRef("Repository")); + registerNotification("RepositoryAdded", description, params); params.clear(); - setDescription("RepositoryChanged", "Emitted whenever a repository in the list of repositories changes."); - params.insert("repository", JsonTypes::repositoryRef()); - setParams("RepositoryChanged", params); + description = "Emitted whenever a repository in the list of repositories changes."; + params.insert("repository", objectRef("Repository")); + registerNotification("RepositoryChanged", description, params); params.clear(); - setDescription("RepositoryRemoved", "Emitted whenever a repository is removed from the list of repositories."); - params.insert("repositoryId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("RepositoryRemoved", params); + description = "Emitted whenever a repository is removed from the list of repositories."; + params.insert("repositoryId", enumValueName(String)); + registerNotification("RepositoryRemoved", description, params); connect(m_platform->systemController(), &PlatformSystemController::availableChanged, this, &SystemHandler::onCapabilitiesChanged); @@ -190,12 +192,12 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): }); connect(m_platform->updateController(), &PlatformUpdateController::packageAdded, this, [this](const Package &package){ QVariantMap params; - params.insert("package", JsonTypes::packPackage(package)); + params.insert("package", packPackage(package)); emit PackageAdded(params); }); connect(m_platform->updateController(), &PlatformUpdateController::packageChanged, this, [this](const Package &package){ QVariantMap params; - params.insert("package", JsonTypes::packPackage(package)); + params.insert("package", packPackage(package)); emit PackageChanged(params); }); connect(m_platform->updateController(), &PlatformUpdateController::packageRemoved, this, [this](const QString &packageId){ @@ -205,12 +207,12 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): }); connect(m_platform->updateController(), &PlatformUpdateController::repositoryAdded, this, [this](const Repository &repository){ QVariantMap params; - params.insert("repository", JsonTypes::packRepository(repository)); + params.insert("repository", packRepository(repository)); emit RepositoryAdded(params); }); connect(m_platform->updateController(), &PlatformUpdateController::repositoryChanged, this, [this](const Repository &repository){ QVariantMap params; - params.insert("repository", JsonTypes::packRepository(repository)); + params.insert("repository", packRepository(repository)); emit RepositoryChanged(params); }); connect(m_platform->updateController(), &PlatformUpdateController::repositoryRemoved, this, [this](const QString &repositoryId){ @@ -236,7 +238,7 @@ JsonReply *SystemHandler::GetCapabilities(const QVariantMap ¶ms) JsonReply *SystemHandler::Reboot(const QVariantMap ¶ms) const { - Q_UNUSED(params); + Q_UNUSED(params) bool status = m_platform->systemController()->reboot(); QVariantMap returns; returns.insert("success", status); @@ -245,7 +247,7 @@ JsonReply *SystemHandler::Reboot(const QVariantMap ¶ms) const JsonReply *SystemHandler::Shutdown(const QVariantMap ¶ms) const { - Q_UNUSED(params); + Q_UNUSED(params) bool status = m_platform->systemController()->shutdown(); QVariantMap returns; returns.insert("success", status); @@ -275,7 +277,7 @@ JsonReply *SystemHandler::GetPackages(const QVariantMap ¶ms) const Q_UNUSED(params) QVariantList packagelist; foreach (const Package &package, m_platform->updateController()->packages()) { - packagelist.append(JsonTypes::packPackage(package)); + packagelist.append(packPackage(package)); } QVariantMap returns; returns.insert("packages", packagelist); @@ -308,10 +310,10 @@ JsonReply *SystemHandler::RemovePackages(const QVariantMap ¶ms) const JsonReply *SystemHandler::GetRepositories(const QVariantMap ¶ms) const { - Q_UNUSED(params); + Q_UNUSED(params) QVariantList repos; foreach (const Repository &repository, m_platform->updateController()->repositories()) { - repos.append(JsonTypes::packRepository(repository)); + repos.append(packRepository(repository)); } QVariantMap returns; returns.insert("repositories", repos); @@ -335,4 +337,28 @@ void SystemHandler::onCapabilitiesChanged() emit CapabilitiesChanged(caps); } +QVariantMap SystemHandler::packPackage(const Package &package) +{ + QVariantMap ret; + ret.insert("id", package.packageId()); + ret.insert("displayName", package.displayName()); + ret.insert("summary", package.summary()); + ret.insert("installedVersion", package.installedVersion()); + ret.insert("candidateVersion", package.candidateVersion()); + ret.insert("changelog", package.changelog()); + ret.insert("updateAvailable", package.updateAvailable()); + ret.insert("rollbackAvailable", package.rollbackAvailable()); + ret.insert("canRemove", package.canRemove()); + return ret; +} + +QVariantMap SystemHandler::packRepository(const Repository &repository) +{ + QVariantMap ret; + ret.insert("id", repository.id()); + ret.insert("displayName", repository.displayName()); + ret.insert("enabled", repository.enabled()); + return ret; +} + } diff --git a/libnymea-core/jsonrpc/systemhandler.h b/libnymea-core/jsonrpc/systemhandler.h index 36dc09df..3a73bd6b 100644 --- a/libnymea-core/jsonrpc/systemhandler.h +++ b/libnymea-core/jsonrpc/systemhandler.h @@ -23,9 +23,11 @@ #include -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" #include "platform/platform.h" +#include "platform/package.h" +#include "platform/repository.h" namespace nymeaserver { @@ -64,6 +66,10 @@ signals: private slots: void onCapabilitiesChanged(); +private: + static QVariantMap packPackage(const Package &package); + static QVariantMap packRepository(const Repository &repository); + private: Platform *m_platform = nullptr; }; diff --git a/libnymea-core/jsonrpc/tagshandler.cpp b/libnymea-core/jsonrpc/tagshandler.cpp index 601b296b..913ca9a5 100644 --- a/libnymea-core/jsonrpc/tagshandler.cpp +++ b/libnymea-core/jsonrpc/tagshandler.cpp @@ -27,51 +27,58 @@ namespace nymeaserver { TagsHandler::TagsHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap params; - QVariantMap returns; + // Enums + registerEnum(); + + // Objects + QVariantMap tag; + tag.insert("o:deviceId", enumValueName(Uuid)); + tag.insert("o:ruleId", enumValueName(Uuid)); + tag.insert("appId", enumValueName(String)); + tag.insert("tagId", enumValueName(String)); + tag.insert("o:value", enumValueName(String)); + registerObject("Tag", tag); + + // Methods + QString description; QVariantMap params; QVariantMap returns; + description = "Get the Tags matching the given filter. Tags can be filtered by a deviceID, a ruleId, an appId, a tagId or a combination of any (however, combining deviceId and ruleId will return an empty result set)."; + params.insert("o:deviceId", enumValueName(Uuid)); + params.insert("o:ruleId", enumValueName(Uuid)); + params.insert("o:appId", enumValueName(String)); + params.insert("o:tagId", enumValueName(String)); + returns.insert("tagError", enumRef()); + returns.insert("o:tags", QVariantList() << objectRef("Tag")); + registerMethod("GetTags", description, params, returns); params.clear(); returns.clear(); - setDescription("GetTags", "Get the Tags matching the given filter. Tags can be filtered by a deviceID, a ruleId, an appId, a tagId or a combination of any (however, combining deviceId and ruleId will return an empty result set)."); - params.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:appId", JsonTypes::basicTypeToString(JsonTypes::String)); - params.insert("o:tagId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("GetTags", params); - returns.insert("tagError", JsonTypes::tagErrorRef()); - returns.insert("o:tags", QVariantList() << JsonTypes::tagRef()); - setReturns("GetTags", returns); + description = "Add a Tag. A Tag must have a deviceId OR a ruleId (call this method twice if you want to attach the same tag to a device and a rule), an appId (Use the appId of your app), a tagId (e.g. \"favorites\") and a value. Upon success, a TagAdded notification will be emitted. Calling this method twice for the same ids (device/rule, appId and tagId) but with a different value will update the tag's value and the TagValueChanged notification will be emitted."; + params.insert("tag", objectRef("Tag")); + returns.insert("tagError", enumRef()); + registerMethod("AddTag", description, params, returns); params.clear(); returns.clear(); - setDescription("AddTag", "Add a Tag. A Tag must have a deviceId OR a ruleId (call this method twice if you want to attach the same tag to a device and a rule), an appId (Use the appId of your app), a tagId (e.g. \"favorites\") and a value. Upon success, a TagAdded notification will be emitted. Calling this method twice for the same ids (device/rule, appId and tagId) but with a different value will update the tag's value and the TagValueChanged notification will be emitted."); - params.insert("tag", JsonTypes::tagRef()); - setParams("AddTag", params); - returns.insert("tagError", JsonTypes::tagErrorRef()); - setReturns("AddTag", returns); - - params.clear(); returns.clear(); - setDescription("RemoveTag", "Remove a Tag. Tag value is optional and will be disregarded. If the ids match, the tag will be deleted and a TagRemoved notification will be emitted."); - params.insert("tag", JsonTypes::tagRef()); - setParams("RemoveTag", params); - returns.insert("tagError", JsonTypes::tagErrorRef()); - setReturns("RemoveTag", returns); + description = "Remove a Tag. Tag value is optional and will be disregarded. If the ids match, the tag will be deleted and a TagRemoved notification will be emitted."; + params.insert("tag", objectRef("Tag")); + returns.insert("tagError", enumRef()); + registerMethod("RemoveTag", description, params, returns); // Notifications params.clear(); - setDescription("TagAdded", "Emitted whenever a tag is added to the system. "); - params.insert("tag", JsonTypes::tagRef()); - setParams("TagAdded", params); + description = "Emitted whenever a tag is added to the system. "; + params.insert("tag", objectRef("Tag")); + registerNotification("TagAdded", description, params); connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagAdded, this, &TagsHandler::onTagAdded); params.clear(); - setDescription("TagRemoved", "Emitted whenever a tag is removed from the system. "); - params.insert("tag", JsonTypes::tagRef()); - setParams("TagRemoved", params); + description = "Emitted whenever a tag is removed from the system. "; + params.insert("tag", objectRef("Tag")); + registerNotification("TagRemoved", description, params); connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagRemoved, this, &TagsHandler::onTagRemoved); params.clear(); - setDescription("TagValueChanged", "Emitted whenever a tag's value is changed in the system. "); - params.insert("tag", JsonTypes::tagRef()); - setParams("TagValueChanged", params); + description = "Emitted whenever a tag's value is changed in the system. "; + params.insert("tag", objectRef("Tag")); + registerNotification("TagValueChanged", description, params); connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagValueChanged, this, &TagsHandler::onTagValueChanged); } @@ -96,7 +103,7 @@ JsonReply *TagsHandler::GetTags(const QVariantMap ¶ms) const if (params.contains("tagId") && params.value("tagId").toString() != tag.tagId()) { continue; } - ret.append(JsonTypes::packTag(tag)); + ret.append(packTag(tag)); } QVariantMap returns = statusToReply(TagsStorage::TagErrorNoError); returns.insert("tags", ret); @@ -106,7 +113,7 @@ JsonReply *TagsHandler::GetTags(const QVariantMap ¶ms) const JsonReply *TagsHandler::AddTag(const QVariantMap ¶ms) const { - Tag tag = JsonTypes::unpackTag(params.value("tag").toMap()); + Tag tag = unpackTag(params.value("tag").toMap()); TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->addTag(tag); QVariantMap returns = statusToReply(error); return createReply(returns); @@ -114,7 +121,7 @@ JsonReply *TagsHandler::AddTag(const QVariantMap ¶ms) const JsonReply *TagsHandler::RemoveTag(const QVariantMap ¶ms) const { - Tag tag = JsonTypes::unpackTag(params.value("tag").toMap()); + Tag tag = unpackTag(params.value("tag").toMap()); TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->removeTag(tag); QVariantMap returns = statusToReply(error); return createReply(returns); @@ -124,7 +131,7 @@ void TagsHandler::onTagAdded(const Tag &tag) { qCDebug(dcJsonRpc) << "Notify \"Tags.TagAdded\""; QVariantMap params; - params.insert("tag", JsonTypes::packTag(tag)); + params.insert("tag", packTag(tag)); emit TagAdded(params); } @@ -132,7 +139,7 @@ void TagsHandler::onTagRemoved(const Tag &tag) { qCDebug(dcJsonRpc) << "Notify \"Tags.TagRemoved\""; QVariantMap params; - params.insert("tag", JsonTypes::packTag(tag)); + params.insert("tag", packTag(tag)); emit TagRemoved(params); } @@ -140,8 +147,42 @@ void TagsHandler::onTagValueChanged(const Tag &tag) { qCDebug(dcJsonRpc) << "Notify \"Tags.TagValueChanged\""; QVariantMap params; - params.insert("tag", JsonTypes::packTag(tag)); + params.insert("tag", packTag(tag)); emit TagValueChanged(params); } +QVariantMap TagsHandler::packTag(const Tag &tag) +{ + QVariantMap ret; + if (!tag.deviceId().isNull()){ + ret.insert("deviceId", tag.deviceId().toString()); + } else { + ret.insert("ruleId", tag.ruleId().toString()); + } + ret.insert("appId", tag.appId()); + ret.insert("tagId", tag.tagId()); + ret.insert("value", tag.value()); + return ret; +} + +Tag TagsHandler::unpackTag(const QVariantMap &tagMap) +{ + DeviceId deviceId = DeviceId(tagMap.value("deviceId").toString()); + RuleId ruleId = RuleId(tagMap.value("ruleId").toString()); + QString appId = tagMap.value("appId").toString(); + QString tagId = tagMap.value("tagId").toString(); + QString value = tagMap.value("value").toString(); + if (!deviceId.isNull()) { + return Tag(deviceId, appId, tagId, value); + } + return Tag(ruleId, appId, tagId, value); +} + +QVariantMap TagsHandler::statusToReply(TagsStorage::TagError status) const +{ + QVariantMap returns; + returns.insert("tagError", enumValueName(status)); + return returns; +} + } diff --git a/libnymea-core/jsonrpc/tagshandler.h b/libnymea-core/jsonrpc/tagshandler.h index 6bbc7124..c8af320d 100644 --- a/libnymea-core/jsonrpc/tagshandler.h +++ b/libnymea-core/jsonrpc/tagshandler.h @@ -23,7 +23,8 @@ #include -#include "jsonhandler.h" +#include "jsonrpc/jsonhandler.h" +#include "tagging/tagsstorage.h" namespace nymeaserver { @@ -47,6 +48,13 @@ private slots: void onTagAdded(const Tag &tag); void onTagRemoved(const Tag &tag); void onTagValueChanged(const Tag &tag); + +private: + static QVariantMap packTag(const Tag &tag); + static Tag unpackTag(const QVariantMap &tagMap); + + QVariantMap statusToReply(TagsStorage::TagError status) const; + }; } diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro index 43dd82b9..69a9807c 100644 --- a/libnymea-core/libnymea-core.pro +++ b/libnymea-core/libnymea-core.pro @@ -35,9 +35,8 @@ HEADERS += nymeacore.h \ servers/websocketserver.h \ servers/mqttbroker.h \ jsonrpc/jsonrpcserver.h \ - jsonrpc/jsonhandler.h \ + jsonrpc/jsonvalidator.h \ jsonrpc/devicehandler.h \ - jsonrpc/jsontypes.h \ jsonrpc/ruleshandler.h \ jsonrpc/actionhandler.h \ jsonrpc/eventhandler.h \ @@ -113,9 +112,8 @@ SOURCES += nymeacore.cpp \ servers/bluetoothserver.cpp \ servers/mqttbroker.cpp \ jsonrpc/jsonrpcserver.cpp \ - jsonrpc/jsonhandler.cpp \ + jsonrpc/jsonvalidator.cpp \ jsonrpc/devicehandler.cpp \ - jsonrpc/jsontypes.cpp \ jsonrpc/ruleshandler.cpp \ jsonrpc/actionhandler.cpp \ jsonrpc/eventhandler.cpp \ diff --git a/libnymea-core/logging/logentry.cpp b/libnymea-core/logging/logentry.cpp index 1ebe8cca..c22eb2b9 100644 --- a/libnymea-core/logging/logentry.cpp +++ b/libnymea-core/logging/logentry.cpp @@ -38,9 +38,9 @@ #include "logentry.h" #include "nymeacore.h" -#include "jsonrpc/jsontypes.h" #include +#include namespace nymeaserver { @@ -156,13 +156,17 @@ int LogEntry::errorCode() const QDebug operator<<(QDebug dbg, const LogEntry &entry) { + QMetaEnum metaEnum; dbg.nospace() << "LogEntry (" << entry.timestamp().toString() << ")" << endl; dbg.nospace() << " time stamp: " << entry.timestamp().toTime_t() << endl; dbg.nospace() << " DeviceId: " << entry.deviceId().toString() << endl; dbg.nospace() << " type id: " << entry.typeId().toString() << endl; - dbg.nospace() << " source: " << JsonTypes::loggingSourceToString(entry.source()) << endl; - dbg.nospace() << " level: " << JsonTypes::loggingLevelToString(entry.level()) << endl; - dbg.nospace() << " eventType: " << JsonTypes::loggingEventTypeToString(entry.eventType()) << endl; + metaEnum = QMetaEnum::fromType(); + dbg.nospace() << " source: " << metaEnum.valueToKey(entry.source()) << endl; + metaEnum = QMetaEnum::fromType(); + dbg.nospace() << " level: " << metaEnum.valueToKey(entry.level()) << endl; + metaEnum = QMetaEnum::fromType(); + dbg.nospace() << " eventType: " << metaEnum.valueToKey(entry.eventType()) << endl; dbg.nospace() << " error code: " << entry.errorCode() << endl; dbg.nospace() << " active: " << entry.active() << endl; dbg.nospace() << " value: " << entry.value() << endl; diff --git a/libnymea/devices/pluginmetadata.cpp b/libnymea/devices/pluginmetadata.cpp index 00c8b3cb..e5830391 100644 --- a/libnymea/devices/pluginmetadata.cpp +++ b/libnymea/devices/pluginmetadata.cpp @@ -112,6 +112,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) hasError = true; } + if (m_pluginId.isNull()) { + m_validationErrors.append("Plugin \"" + m_pluginName + "\" has invalid UUID: " + jsonObject.value("id").toString()); + hasError = true; + } if (!verifyDuplicateUuid(m_pluginId)) { m_validationErrors.append("Plugin \"" + m_pluginName + "\" has duplicate UUID: " + m_pluginId.toString()); hasError = true; @@ -153,6 +157,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) hasError = true; } + if (vendorId.isNull()) { + m_validationErrors.append("Vendor \"" + vendorName + "\" has invalid UUID: " + vendorObject.value("id").toString()); + hasError = true; + } if (!verifyDuplicateUuid(vendorId)) { m_validationErrors.append("Vendor \"" + vendorName + "\" has duplicate UUID: " + vendorId.toString()); hasError = true; @@ -193,6 +201,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) hasError = true; } + if (deviceClassId.isNull()) { + m_validationErrors.append("Device class \"" + deviceClassName + "\" has invalid UUID: " + deviceClassObject.value("id").toString()); + hasError = true; + } if (!verifyDuplicateUuid(deviceClassId)) { m_validationErrors.append("Device class \"" + deviceClassName + "\" has duplicate UUID: " + deviceClassName); hasError = true; @@ -316,6 +328,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) hasError = true; } + if (stateTypeId.isNull()) { + m_validationErrors.append("Device class \"" + deviceClass.name() + "\" state type \"" + stateTypeName + "\" has invalid UUID: " + st.value("id").toString()); + hasError = true; + } if (!verifyDuplicateUuid(stateTypeId)) { m_validationErrors.append("Device class \"" + deviceClass.name() + "\" state type \"" + stateTypeName + "\" has duplicate UUID: " + stateTypeId.toString()); hasError = true; @@ -408,6 +424,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) hasError = true; } + if (actionTypeId.isNull()) { + m_validationErrors.append("Device class \"" + deviceClass.name() + "\" action type \"" + actionTypeName + "\" has invalid UUID: " + at.value("id").toString()); + hasError = true; + } if (!verifyDuplicateUuid(actionTypeId)) { m_validationErrors.append("Device class \"" + deviceClass.name() + "\" action type \"" + actionTypeName + "\" has duplicate UUID: " + actionTypeId.toString()); hasError = true; @@ -452,6 +472,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) hasError = true; } + if (eventTypeId.isNull()) { + m_validationErrors.append("Device class \"" + deviceClass.name() + "\" event type \"" + eventTypeName + "\" has invalid UUID: " + et.value("id").toString()); + hasError = true; + } if (!verifyDuplicateUuid(eventTypeId)) { m_validationErrors.append("Device class \"" + deviceClass.name() + "\" event type \"" + eventTypeName + "\" has duplicate UUID: " + eventTypeId.toString()); hasError = true; @@ -493,6 +517,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) hasError = true; } + if (actionTypeId.isNull()) { + m_validationErrors.append("Device class \"" + deviceClass.name() + "\" browser action type \"" + actionTypeName + "\" has invalid UUID: " + at.value("id").toString()); + hasError = true; + } if (!verifyDuplicateUuid(actionTypeId)) { m_validationErrors.append("Device class \"" + deviceClass.name() + "\" browser action type \"" + actionTypeName + "\" has duplicate UUID: " + actionTypeId.toString()); hasError = true; @@ -710,6 +738,10 @@ QPair PluginMetadata::parseParamTypes(const QJsonArray &array) hasErrors = true; } + if (paramTypeId.isNull()) { + m_validationErrors.append("Param type \"" + paramName + "\" has invalid UUID: " + pt.value("id").toString()); + hasErrors = true; + } if (!verifyDuplicateUuid(paramTypeId)) { m_validationErrors.append("Param type \"" + paramName + "\" has duplicate UUID: " + paramTypeId.toString()); hasErrors = true; diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp new file mode 100644 index 00000000..3b5e728e --- /dev/null +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -0,0 +1,134 @@ +#include "jsonhandler.h" + +#include "loggingcategories.h" + +#include + +JsonHandler::JsonHandler(QObject *parent) : QObject(parent) +{ +} + +QVariantMap JsonHandler::jsonEnums() const +{ + return m_enums; +} + +QVariantMap JsonHandler::jsonObjects() const +{ + return m_objects; +} + +QVariantMap JsonHandler::jsonMethods() const +{ + return m_methods; +} + +QVariantMap JsonHandler::jsonNotifications() const +{ + return m_notifications; +} + +//QString JsonHandler::basicTypeName(JsonHandler::BasicType type) +//{ +// QMetaEnum metaEnum = QMetaEnum::fromType(); +// return metaEnum.valueToKey(type); +//} + +QString JsonHandler::objectRef(const QString &objectName) +{ + return "$ref:" + objectName; +} + +JsonHandler::BasicType JsonHandler::variantTypeToBasicType(QVariant::Type variantType) +{ + switch (variantType) { + case QVariant::Uuid: + return Uuid; + case QVariant::String: + return String; + case QVariant::StringList: + return StringList; + case QVariant::Int: + return Int; + case QVariant::UInt: + return Uint; + case QVariant::Double: + return Double; + case QVariant::Bool: + return Bool; + case QVariant::Color: + return Color; + case QVariant::Time: + return Time; + case QVariant::Map: + return Object; + default: + return Variant; + } +} + +QVariant::Type JsonHandler::basicTypeToVariantType(JsonHandler::BasicType basicType) +{ + switch (basicType) { + case Uuid: + return QVariant::Uuid; + case String: + return QVariant::String; + case StringList: + return QVariant::StringList; + case Int: + return QVariant::Int; + case Uint: + return QVariant::UInt; + case Double: + return QVariant::Double; + case Bool: + return QVariant::Bool; + case Color: + return QVariant::Color; + case Time: + return QVariant::Time; + case Object: + return QVariant::Map; + case Variant: + return QVariant::Invalid; + } + return QVariant::Invalid; +} + +void JsonHandler::registerObject(const QString &name, const QVariantMap &object) +{ + m_objects.insert(name, object); +} + +void JsonHandler::registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool /*deprecated*/) +{ + QVariantMap methodData; + methodData.insert("description", description); + methodData.insert("params", params); + methodData.insert("returns", returns); +// methodData.insert("deprecated", deprecated); + + m_methods.insert(name, methodData); +} + +void JsonHandler::registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool /*deprecated*/) +{ + QVariantMap notificationData; + notificationData.insert("description", description); + notificationData.insert("params", params); +// notificationData.insert("deprecated", deprecated); + + m_notifications.insert(name, notificationData); +} + +JsonReply *JsonHandler::createReply(const QVariantMap &data) const +{ + return JsonReply::createReply(const_cast(this), data); +} + +JsonReply *JsonHandler::createAsyncReply(const QString &method) const +{ + return JsonReply::createAsyncReply(const_cast(this), method); +} + diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h new file mode 100644 index 00000000..09b509c5 --- /dev/null +++ b/libnymea/jsonrpc/jsonhandler.h @@ -0,0 +1,99 @@ +#ifndef JSONHANDLER_H +#define JSONHANDLER_H + +#include +#include +#include + +#include "jsonreply.h" + +class JsonHandler : public QObject +{ + Q_OBJECT +public: + enum BasicType { + Uuid, + String, + StringList, + Int, + Uint, + Double, + Bool, + Variant, + Color, + Time, + Object + }; + Q_ENUM(BasicType) + + explicit JsonHandler(QObject *parent = nullptr); + virtual ~JsonHandler() = default; + + virtual QString name() const = 0; + + QVariantMap jsonEnums() const; + QVariantMap jsonObjects() const; + QVariantMap jsonMethods() const; + QVariantMap jsonNotifications() const; + + + template static QString enumRef(); + static QString objectRef(const QString &objectName); + + template static QString enumValueName(T value); + template static T enumNameToValue(const QString &name); + + static BasicType variantTypeToBasicType(QVariant::Type variantType); + static QVariant::Type basicTypeToVariantType(BasicType basicType); + +protected: + template void registerEnum(); + void registerObject(const QString &name, const QVariantMap &object); + void registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool deprecated = false); + void registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool deprecated = false); + + JsonReply *createReply(const QVariantMap &data) const; + JsonReply *createAsyncReply(const QString &method) const; + + +private: + QVariantMap m_enums; + QVariantMap m_objects; + QVariantMap m_methods; + QVariantMap m_notifications; +}; + +template +void JsonHandler::registerEnum() +{ + QMetaEnum metaEnum = QMetaEnum::fromType(); + QStringList values; + for (int i = 0; i < metaEnum.keyCount(); i++) { + values << metaEnum.key(i); + } + m_enums.insert(metaEnum.name(), values); + +} + +template +QString JsonHandler::enumRef() +{ + QMetaEnum metaEnum = QMetaEnum::fromType(); + return QString("$ref:%1").arg(metaEnum.name()); +} + +template +QString JsonHandler::enumValueName(T value) +{ + QMetaEnum metaEnum = QMetaEnum::fromType(); + return metaEnum.valueToKey(value); +} + +template +T JsonHandler::enumNameToValue(const QString &name) +{ + QMetaEnum metaEnum = QMetaEnum::fromType(); + return static_cast(metaEnum.keyToValue(name.toUtf8())); +} + +#endif // JSONHANDLER_H diff --git a/libnymea/jsonrpc/jsonreply.cpp b/libnymea/jsonrpc/jsonreply.cpp new file mode 100644 index 00000000..e917af44 --- /dev/null +++ b/libnymea/jsonrpc/jsonreply.cpp @@ -0,0 +1,123 @@ +#include "jsonreply.h" + +/*! + \class JsonReply + \brief This class represents a reply for the JSON-RPC API request. + + \ingroup json + \inmodule core + + \sa JsonHandler +*/ + +/*! \enum JsonReply::Type + + This enum type specifies the type of a JsonReply. + + \value TypeSync + The response is synchronous. + \value TypeAsync + The response is asynchronous. +*/ + +/*! \fn void JsonReply::finished(); + This signal will be emitted when a JsonReply is finished. A JsonReply is finished when + the response is ready or then the reply timed out. +*/ + + + +/*! Constructs a new \l JsonReply with the given \a type, \a handler, \a method and \a data. */ +JsonReply::JsonReply(Type type, JsonHandler *handler, const QString &method, const QVariantMap &data): + m_type(type), + m_data(data), + m_handler(handler), + m_method(method), + m_timedOut(false) +{ + connect(&m_timeout, &QTimer::timeout, this, &JsonReply::timeout); +} + +/*! Returns the pointer to a new \l{JsonReply} for the given \a handler and \a data. */ +JsonReply *JsonReply::createReply(JsonHandler *handler, const QVariantMap &data) +{ + return new JsonReply(TypeSync, handler, QString(), data); +} + +/*! Returns the pointer to a new asynchronous \l{JsonReply} for the given \a handler and \a method. */ +JsonReply *JsonReply::createAsyncReply(JsonHandler *handler, const QString &method) +{ + return new JsonReply(TypeAsync, handler, method); +} + +/*! Returns the type of this \l{JsonReply}.*/ +JsonReply::Type JsonReply::type() const +{ + return m_type; +} + +/*! Returns the data of this \l{JsonReply}.*/ +QVariantMap JsonReply::data() const +{ + return m_data; +} + +/*! Sets the \a data of this \l{JsonReply}.*/ +void JsonReply::setData(const QVariantMap &data) +{ + m_data = data; +} + +/*! Returns the handler of this \l{JsonReply}.*/ +JsonHandler *JsonReply::handler() const +{ + return m_handler; +} + +/*! Returns the method of this \l{JsonReply}.*/ +QString JsonReply::method() const +{ + return m_method; +} + +/*! Returns the client ID of this \l{JsonReply}.*/ +QUuid JsonReply::clientId() const +{ + return m_clientId; +} + +/*! Sets the \a clientId of this \l{JsonReply}.*/ +void JsonReply::setClientId(const QUuid &clientId) +{ + m_clientId = clientId; +} + +/*! Returns the command ID of this \l{JsonReply}.*/ +int JsonReply::commandId() const +{ + return m_commandId; +} + +/*! Returns the \a commandId of this \l{JsonReply}.*/ +void JsonReply::setCommandId(int commandId) +{ + m_commandId = commandId; +} + +/*! Start the timeout timer for this \l{JsonReply}. The default timeout is 15 seconds. */ +void JsonReply::startWait() +{ + m_timeout.start(30000); +} + +void JsonReply::timeout() +{ + m_timedOut = true; + emit finished(); +} + +/*! Returns true if this \l{JsonReply} timed out.*/ +bool JsonReply::timedOut() const +{ + return m_timedOut; +} diff --git a/libnymea/jsonrpc/jsonreply.h b/libnymea/jsonrpc/jsonreply.h new file mode 100644 index 00000000..0a33f611 --- /dev/null +++ b/libnymea/jsonrpc/jsonreply.h @@ -0,0 +1,62 @@ +#ifndef JSONREPLY_H +#define JSONREPLY_H + +#include +#include +#include +#include + +class JsonHandler; + +class JsonReply: public QObject +{ + Q_OBJECT +public: + enum Type { + TypeSync, + TypeAsync + }; + + static JsonReply *createReply(JsonHandler *handler, const QVariantMap &data); + static JsonReply *createAsyncReply(JsonHandler *handler, const QString &method); + + Type type() const; + QVariantMap data() const; + void setData(const QVariantMap &data); + + JsonHandler *handler() const; + QString method() const; + + QUuid clientId() const; + void setClientId(const QUuid &clientId); + + int commandId() const; + void setCommandId(int commandId); + + bool timedOut() const; + +public slots: + void startWait(); + +signals: + void finished(); + +private slots: + void timeout(); + +private: + JsonReply(Type type, JsonHandler *handler, const QString &method, const QVariantMap &data = QVariantMap()); + Type m_type; + QVariantMap m_data; + + JsonHandler *m_handler; + QString m_method; + QUuid m_clientId; + int m_commandId; + bool m_timedOut; + + QTimer m_timeout; + +}; + +#endif // JSONREPLY_H diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index 78bdbae1..4d19b679 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -24,6 +24,8 @@ HEADERS += \ devices/devicepairinginfo.h \ devices/deviceactioninfo.h \ devices/browseresult.h \ + jsonrpc/jsonhandler.h \ + jsonrpc/jsonreply.h \ libnymea.h \ platform/package.h \ platform/repository.h \ @@ -98,6 +100,8 @@ SOURCES += \ devices/devicepairinginfo.cpp \ devices/deviceactioninfo.cpp \ devices/browseresult.cpp \ + jsonrpc/jsonhandler.cpp \ + jsonrpc/jsonreply.cpp \ loggingcategories.cpp \ nymeasettings.cpp \ platform/package.cpp \ diff --git a/plugins/mock/devicepluginmock.json b/plugins/mock/devicepluginmock.json index 94bc0551..cf305ab8 100644 --- a/plugins/mock/devicepluginmock.json +++ b/plugins/mock/devicepluginmock.json @@ -279,7 +279,7 @@ ], "actionTypes": [ { - "id": "e6a22f52-1818-46a7-9d15-5ca08b0612c", + "id": "07cd8d5f-2f65-4955-b1f9-05d7f4da488a", "name": "withParams", "displayName": "Mock Action 1 (with params)", "paramTypes": [ diff --git a/plugins/mock/plugininfo.h b/plugins/mock/plugininfo.h index 4930526d..b2c280f2 100644 --- a/plugins/mock/plugininfo.h +++ b/plugins/mock/plugininfo.h @@ -69,7 +69,7 @@ ParamTypeId mockDeviceAutoBoolValueEventBoolValueParamTypeId = ParamTypeId("{978 EventTypeId mockDeviceAutoEvent1EventTypeId = EventTypeId("{00f81fca-26f1-4a84-aa2b-4c6a3d953ec6}"); EventTypeId mockDeviceAutoEvent2EventTypeId = EventTypeId("{6e27922d-aa9d-44d1-b9b4-9faf31b6bd97}"); ParamTypeId mockDeviceAutoEvent2EventIntParamParamTypeId = ParamTypeId("{12ed5a15-96b4-4381-9d9c-a24875283d4f}"); -ActionTypeId mockDeviceAutoWithParamsActionTypeId = ActionTypeId("{00000000-0000-0000-0000-000000000000}"); +ActionTypeId mockDeviceAutoWithParamsActionTypeId = ActionTypeId("{07cd8d5f-2f65-4955-b1f9-05d7f4da488a}"); ParamTypeId mockDeviceAutoWithParamsActionMockActionParam1ParamTypeId = ParamTypeId("{b8126ba6-3a54-45a3-be4d-63feb0ddb77b}"); ParamTypeId mockDeviceAutoWithParamsActionMockActionParam2ParamTypeId = ParamTypeId("{df41ba71-e43b-4854-91d1-b19d8066d4f9}"); ActionTypeId mockDeviceAutoMockActionNoParmsActionTypeId = ActionTypeId("{ef518d53-50e2-4ca5-a4b1-e9a8b9309d44}"); @@ -348,7 +348,7 @@ const QString translations[] { //: The name of the ParamType (DeviceClass: mockInputType, Type: device, ID: {a8494faf-3a0f-4cf3-84b7-4b39148a838d}) QT_TRANSLATE_NOOP("mockDevice", "Mail address"), - //: The name of the ActionType ({00000000-0000-0000-0000-000000000000}) of DeviceClass mockDeviceAuto + //: The name of the ActionType ({07cd8d5f-2f65-4955-b1f9-05d7f4da488a}) of DeviceClass mockDeviceAuto QT_TRANSLATE_NOOP("mockDevice", "Mock Action 1 (with params)"), //: The name of the ActionType ({dea0f4e1-65e3-4981-8eaa-2701c53a9185}) of DeviceClass mock diff --git a/tests/auto/actions/testactions.cpp b/tests/auto/actions/testactions.cpp index afb721d3..574561db 100644 --- a/tests/auto/actions/testactions.cpp +++ b/tests/auto/actions/testactions.cpp @@ -20,6 +20,7 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include "nymeatestbase.h" +#include "devices/device.h" using namespace nymeaserver; @@ -75,7 +76,7 @@ void TestActions::executeAction() params.insert("params", actionParams); QVariant response = injectAndWait("Actions.ExecuteAction", params); qDebug() << "executeActionresponse" << response; - verifyDeviceError(response, error); + verifyError(response, "deviceError", enumValueName(error)); // Fetch action execution history from mock device QNetworkAccessManager nam; @@ -132,7 +133,7 @@ void TestActions::getActionType() params.insert("actionTypeId", actionTypeId.toString()); QVariant response = injectAndWait("Actions.GetActionType", params); - verifyDeviceError(response, error); + verifyError(response, "deviceError", enumValueName(error)); if (error == Device::DeviceErrorNoError) { QVERIFY2(ActionTypeId(response.toMap().value("params").toMap().value("actionType").toMap().value("id").toString()) == actionTypeId, "Didn't get a reply for the same actionTypeId as requested."); diff --git a/tests/auto/configurations/testconfigurations.cpp b/tests/auto/configurations/testconfigurations.cpp index 5680e6d0..3412f670 100644 --- a/tests/auto/configurations/testconfigurations.cpp +++ b/tests/auto/configurations/testconfigurations.cpp @@ -30,6 +30,11 @@ class TestConfigurations: public NymeaTestBase { Q_OBJECT +private: + inline void verifyConfigurationError(const QVariant &response, NymeaConfiguration::ConfigurationError error = NymeaConfiguration::ConfigurationErrorNoError) { + verifyError(response, "configurationError", enumValueName(error)); + } + protected slots: void initTestCase(); diff --git a/tests/auto/devices/testdevices.cpp b/tests/auto/devices/testdevices.cpp index 33120650..bfca2cea 100644 --- a/tests/auto/devices/testdevices.cpp +++ b/tests/auto/devices/testdevices.cpp @@ -35,6 +35,10 @@ class TestDevices : public NymeaTestBase private: DeviceId m_mockDeviceAsyncId; + inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) { + verifyError(response, "deviceError", enumValueName(error)); + } + private slots: void initTestCase(); @@ -832,7 +836,7 @@ void TestDevices::getStateValue() params.insert("stateTypeId", stateTypeId); QVariant response = injectAndWait("Devices.GetStateValue", params); - QCOMPARE(response.toMap().value("params").toMap().value("deviceError").toString(), JsonTypes::deviceErrorToString(statusCode)); + QCOMPARE(response.toMap().value("params").toMap().value("deviceError").toString(), enumValueName(statusCode)); if (statusCode == Device::DeviceErrorNoError) { QVariant value = response.toMap().value("params").toMap().value("value"); QCOMPARE(value.toInt(), 10); // Mock device has value 10 by default... @@ -857,7 +861,7 @@ void TestDevices::getStateValues() params.insert("deviceId", deviceId); QVariant response = injectAndWait("Devices.GetStateValues", params); - QCOMPARE(response.toMap().value("params").toMap().value("deviceError").toString(), JsonTypes::deviceErrorToString(statusCode)); + QCOMPARE(response.toMap().value("params").toMap().value("deviceError").toString(), enumValueName(statusCode)); if (statusCode == Device::DeviceErrorNoError) { QVariantList values = response.toMap().value("params").toMap().value("values").toList(); QCOMPARE(values.count(), 6); // Mock device has 6 states... diff --git a/tests/auto/events/testevents.cpp b/tests/auto/events/testevents.cpp index d18c124d..63005268 100644 --- a/tests/auto/events/testevents.cpp +++ b/tests/auto/events/testevents.cpp @@ -128,7 +128,7 @@ void TestEvents::getEventType() params.insert("eventTypeId", eventTypeId.toString()); QVariant response = injectAndWait("Events.GetEventType", params); - verifyDeviceError(response, error); + verifyError(response, "deviceError", enumValueName(error)); if (error == Device::DeviceErrorNoError) { QVERIFY2(EventTypeId(response.toMap().value("params").toMap().value("eventType").toMap().value("id").toString()) == eventTypeId, "Didn't get a reply for the same actionTypeId as requested."); diff --git a/tests/auto/jsonrpc/testjsonrpc.cpp b/tests/auto/jsonrpc/testjsonrpc.cpp index fd03a559..e875b661 100644 --- a/tests/auto/jsonrpc/testjsonrpc.cpp +++ b/tests/auto/jsonrpc/testjsonrpc.cpp @@ -23,6 +23,7 @@ #include "../../utils/pushbuttonagent.h" #include "nymeacore.h" #include "servers/mocktcpserver.h" +#include "usermanager/usermanager.h" using namespace nymeaserver; @@ -30,6 +31,14 @@ class TestJSONRPC: public NymeaTestBase { Q_OBJECT +private: + inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) { + verifyError(response, "deviceError", enumValueName(error)); + } + inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) { + verifyError(response, "ruleError", enumValueName(error)); + } + private slots: void initTestCase(); @@ -714,7 +723,7 @@ void TestJSONRPC::ruleAddedRemovedNotifications() QVariantMap stateDescriptor; stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); + stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess)); stateDescriptor.insert("value", "20"); QVariantMap stateEvaluator; @@ -778,7 +787,7 @@ void TestJSONRPC::ruleActiveChangedNotifications() QVariantMap stateDescriptor; stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptor.insert("value", "20"); QVariantMap stateEvaluator; diff --git a/tests/auto/logging/testlogging.cpp b/tests/auto/logging/testlogging.cpp index 8fc94b9e..79ce347b 100644 --- a/tests/auto/logging/testlogging.cpp +++ b/tests/auto/logging/testlogging.cpp @@ -35,6 +35,13 @@ class TestLogging : public NymeaTestBase private: + inline void verifyLoggingError(const QVariant &response, Logging::LoggingError error = Logging::LoggingErrorNoError) { + verifyError(response, "loggingError", enumValueName(error)); + } + inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) { + verifyError(response, "deviceError", enumValueName(error)); + } + private slots: void initTestCase(); @@ -148,8 +155,8 @@ void TestLogging::systemLogs() { // check the active system log at boot QVariantMap params; - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceSystem)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeActiveChange)); + params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceSystem)); + params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeActiveChange)); // there should be 2 logs, one for shutdown, one for startup (from server restart) QVariant response = injectAndWait("Logging.GetLogEntries", params); @@ -166,15 +173,15 @@ void TestLogging::systemLogs() } QCOMPARE(logEntryShutdown.value("active").toBool(), false); - QCOMPARE(logEntryShutdown.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeActiveChange)); - QCOMPARE(logEntryShutdown.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceSystem)); - QCOMPARE(logEntryShutdown.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); + QCOMPARE(logEntryShutdown.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeActiveChange)); + QCOMPARE(logEntryShutdown.value("source").toString(), enumValueName(Logging::LoggingSourceSystem)); + QCOMPARE(logEntryShutdown.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); QCOMPARE(logEntryStartup.value("active").toBool(), true); - QCOMPARE(logEntryStartup.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeActiveChange)); - QCOMPARE(logEntryStartup.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceSystem)); - QCOMPARE(logEntryStartup.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); + QCOMPARE(logEntryStartup.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeActiveChange)); + QCOMPARE(logEntryStartup.value("source").toString(), enumValueName(Logging::LoggingSourceSystem)); + QCOMPARE(logEntryStartup.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); } void TestLogging::invalidFilter_data() @@ -189,7 +196,7 @@ void TestLogging::invalidFilter_data() invalidTypeIds.insert("typeId", QVariantList() << "bla" << "blub"); QVariantMap invalidEventTypes; - invalidEventTypes.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger) << "blub"); + invalidEventTypes.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger) << "blub"); QTest::addColumn("filter"); @@ -247,9 +254,9 @@ void TestLogging::eventLogs() found = true; // Make sure the notification contains all the stuff we expect QCOMPARE(logEntry.value("typeId").toString(), mockEvent1EventTypeId.toString()); - QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents)); - QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); + QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); + QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceEvents)); + QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); break; } } @@ -261,8 +268,8 @@ void TestLogging::eventLogs() // get this logentry with filter QVariantMap params; params.insert("deviceIds", QVariantList() << device->id()); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); + params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceEvents)); + params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger)); params.insert("typeIds", QVariantList() << mockEvent1EventTypeId); QVariant response = injectAndWait("Logging.GetLogEntries", params); @@ -317,9 +324,9 @@ void TestLogging::actionLog() found = true; // Make sure the notification contains all the stuff we expect QCOMPARE(logEntry.value("typeId").toString(), mockWithParamsActionTypeId.toString()); - QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); + QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); + QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions)); + QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); break; } } @@ -343,8 +350,8 @@ void TestLogging::actionLog() // get this logentry with filter params.clear(); params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); + params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions)); + params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger)); // FIXME: currently is filtering for values not supported //params.insert("values", QVariantList() << "7, true"); @@ -376,10 +383,10 @@ void TestLogging::actionLog() found = true; // Make sure the notification contains all the stuff we expect QCOMPARE(logEntry.value("typeId").toString(), mockFailingActionTypeId.toString()); - QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); - QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelAlert)); - QCOMPARE(logEntry.value("errorCode").toString(), JsonTypes::deviceErrorToString(Device::DeviceErrorSetupFailed)); + QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); + QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions)); + QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelAlert)); + QCOMPARE(logEntry.value("errorCode").toString(), enumValueName(Device::DeviceErrorSetupFailed)); break; } } @@ -391,8 +398,8 @@ void TestLogging::actionLog() // get this logentry with filter params.clear(); params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); + params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions)); + params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger)); // FIXME: filter for values currently not working //params.insert("values", QVariantList() << "7, true"); @@ -406,8 +413,8 @@ void TestLogging::actionLog() // check different filters params.clear(); params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); + params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions)); + params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger)); params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId); response = injectAndWait("Logging.GetLogEntries", params); @@ -418,8 +425,8 @@ void TestLogging::actionLog() params.clear(); params.insert("deviceIds", QVariantList() << m_mockDeviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); - params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); + params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions)); + params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger)); params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId << mockWithParamsActionTypeId << mockFailingActionTypeId); response = injectAndWait("Logging.GetLogEntries", params); @@ -447,11 +454,11 @@ void TestLogging::deviceLogs() // get this logentry with filter params.clear(); params.insert("deviceIds", QVariantList() << m_mockDeviceId << deviceId); - params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions) - << JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents) - << JsonTypes::loggingSourceToString(Logging::LoggingSourceStates)); - params.insert("loggingLevels", QVariantList() << JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo) - << JsonTypes::loggingLevelToString(Logging::LoggingLevelAlert)); + params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions) + << enumValueName(Logging::LoggingSourceEvents) + << enumValueName(Logging::LoggingSourceStates)); + params.insert("loggingLevels", QVariantList() << enumValueName(Logging::LoggingLevelInfo) + << enumValueName(Logging::LoggingLevelAlert)); params.insert("values", QVariantList() << "7, true" << "9, false"); QVariantMap timeFilter; @@ -539,14 +546,14 @@ void TestLogging::testDoubleValues() if (logNotification.value("typeId").toString() == mockDisplayPinDoubleActionDoubleParamTypeId.toString()) { // If state source - if (logNotification.value("source").toString() == JsonTypes::loggingSourceToString(Logging::LoggingSourceStates)) { + if (logNotification.value("source").toString() == enumValueName(Logging::LoggingSourceStates)) { QString logValue = logNotification.value("value").toString(); qDebug() << QString::number(value) << logValue; QCOMPARE(logValue, QString::number(value)); } // If action source notification - if (logNotification.value("source").toString() == JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)) { + if (logNotification.value("source").toString() == enumValueName(Logging::LoggingSourceActions)) { QString logValue = logNotification.value("value").toString(); qDebug() << QString::number(value) << logValue; QCOMPARE(logValue, QString::number(value)); diff --git a/tests/auto/rules/testrules.cpp b/tests/auto/rules/testrules.cpp index 3d6ddc4f..2487482c 100644 --- a/tests/auto/rules/testrules.cpp +++ b/tests/auto/rules/testrules.cpp @@ -23,6 +23,7 @@ #include "nymeasettings.h" #include "servers/mocktcpserver.h" #include "nymeacore.h" +#include "jsonrpc/jsonhandler.h" using namespace nymeaserver; @@ -49,6 +50,13 @@ private: void generateEvent(const EventTypeId &eventTypeId); + inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) { + verifyError(response, "ruleError", enumValueName(error)); + } + inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) { + verifyError(response, "deviceError", enumValueName(error)); + } + private slots: void initTestCase(); @@ -331,13 +339,13 @@ QVariant TestRules::validIntStateBasedRule(const QString &name, const bool &exec QVariantMap stateDescriptor; stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); + stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess)); stateDescriptor.insert("value", 25); // StateEvaluator QVariantMap stateEvaluator; stateEvaluator.insert("stateDescriptor", stateDescriptor); - stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd)); // RuleAction QVariantMap action; @@ -423,13 +431,13 @@ void TestRules::addRemoveRules_data() QVariantMap stateDescriptor; stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); + stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess)); stateDescriptor.insert("value", 20); // StateEvaluator QVariantMap validStateEvaluator; validStateEvaluator.insert("stateDescriptor", stateDescriptor); - validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + validStateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap invalidStateEvaluator; stateDescriptor.remove("deviceId"); @@ -448,7 +456,7 @@ void TestRules::addRemoveRules_data() QVariantMap param1; param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); param1.insert("value", 3); - param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + param1.insert("operator", enumValueName(Types::ValueOperatorEquals)); params.append(param1); validEventDescriptor2.insert("paramDescriptors", params); @@ -667,13 +675,13 @@ void TestRules::editRules_data() QVariantMap stateDescriptor; stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); + stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess)); stateDescriptor.insert("value", 20); // StateEvaluator QVariantMap validStateEvaluator; validStateEvaluator.insert("stateDescriptor", stateDescriptor); - validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + validStateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap invalidStateEvaluator; stateDescriptor.remove("deviceId"); @@ -692,7 +700,7 @@ void TestRules::editRules_data() QVariantMap param1; param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); param1.insert("value", 3); - param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + param1.insert("operator", enumValueName(Types::ValueOperatorEquals)); params.append(param1); validEventDescriptor2.insert("paramDescriptors", params); @@ -807,7 +815,7 @@ void TestRules::editRules() QVariantMap eventParam1; eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); eventParam1.insert("value", 3); - eventParam1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + eventParam1.insert("operator", enumValueName(Types::ValueOperatorEquals)); eventParamDescriptors.append(eventParam1); eventDescriptor2.insert("paramDescriptors", eventParamDescriptors); @@ -818,25 +826,25 @@ void TestRules::editRules() QVariantMap stateEvaluator0; QVariantMap stateDescriptor1; stateDescriptor1.insert("deviceId", m_mockDeviceId); - stateDescriptor1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptor1.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptor1.insert("stateTypeId", mockIntStateTypeId); stateDescriptor1.insert("value", 1); QVariantMap stateDescriptor2; stateDescriptor2.insert("deviceId", m_mockDeviceId); - stateDescriptor2.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptor2.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptor2.insert("stateTypeId", mockBoolStateTypeId); stateDescriptor2.insert("value", true); QVariantMap stateEvaluator1; stateEvaluator1.insert("stateDescriptor", stateDescriptor1); - stateEvaluator1.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator1.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap stateEvaluator2; stateEvaluator2.insert("stateDescriptor", stateDescriptor2); - stateEvaluator2.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator2.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantList childEvaluators; childEvaluators.append(stateEvaluator1); childEvaluators.append(stateEvaluator2); stateEvaluator0.insert("childEvaluators", childEvaluators); - stateEvaluator0.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator0.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap action1; action1.insert("actionTypeId", mockWithoutParamsActionTypeId); @@ -1103,7 +1111,7 @@ void TestRules::loadStoreConfig() QVariantMap eventParam1; eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); eventParam1.insert("value", 3); - eventParam1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + eventParam1.insert("operator", enumValueName(Types::ValueOperatorEquals)); eventParamDescriptors.append(eventParam1); eventDescriptor2.insert("paramDescriptors", eventParamDescriptors); @@ -1116,38 +1124,38 @@ void TestRules::loadStoreConfig() QVariantMap stateDescriptor2; stateDescriptor2.insert("deviceId", m_mockDeviceId); - stateDescriptor2.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptor2.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptor2.insert("stateTypeId", mockIntStateTypeId); stateDescriptor2.insert("value", 1); QVariantMap stateEvaluator2; stateEvaluator2.insert("stateDescriptor", stateDescriptor2); - stateEvaluator2.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator2.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap stateDescriptor3; stateDescriptor3.insert("deviceId", m_mockDeviceId); - stateDescriptor3.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptor3.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptor3.insert("stateTypeId", mockBoolStateTypeId); stateDescriptor3.insert("value", true); QVariantMap stateEvaluator3; stateEvaluator3.insert("stateDescriptor", stateDescriptor3); - stateEvaluator3.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator3.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap stateDescriptor4; stateDescriptor4.insert("interface", "battery"); stateDescriptor4.insert("interfaceState", "batteryCritical"); - stateDescriptor4.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptor4.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptor4.insert("value", true); QVariantMap stateEvaluator4; stateEvaluator4.insert("stateDescriptor", stateDescriptor4); - stateEvaluator4.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator4.insert("operator", enumValueName(Types::StateOperatorAnd)); childEvaluators.append(stateEvaluator2); childEvaluators.append(stateEvaluator3); childEvaluators.append(stateEvaluator4); stateEvaluator1.insert("childEvaluators", childEvaluators); - stateEvaluator1.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator1.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap action1; action1.insert("actionTypeId", mockWithoutParamsActionTypeId); @@ -1657,7 +1665,7 @@ void TestRules::testStateChange() { QVariantMap stateEvaluator; QVariantMap stateDescriptor; stateDescriptor.insert("deviceId", m_mockDeviceId); - stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorGreaterOrEqual)); + stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorGreaterOrEqual)); stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("value", 42); stateEvaluator.insert("stateDescriptor", stateDescriptor); @@ -1884,38 +1892,38 @@ void TestRules::testChildEvaluator_data() // Stateevaluators QVariantMap stateDescriptorPercentage; stateDescriptorPercentage.insert("deviceId", testDeviceId); - stateDescriptorPercentage.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorGreaterOrEqual)); + stateDescriptorPercentage.insert("operator", enumValueName(Types::ValueOperatorGreaterOrEqual)); stateDescriptorPercentage.insert("stateTypeId", mockDisplayPinPercentageStateTypeId); stateDescriptorPercentage.insert("value", 50); QVariantMap stateDescriptorDouble; stateDescriptorDouble.insert("deviceId", testDeviceId); - stateDescriptorDouble.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptorDouble.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptorDouble.insert("stateTypeId", mockDisplayPinDoubleActionDoubleParamTypeId); stateDescriptorDouble.insert("value", 20.5); QVariantMap stateDescriptorAllowedValues; stateDescriptorAllowedValues.insert("deviceId", testDeviceId); - stateDescriptorAllowedValues.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptorAllowedValues.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptorAllowedValues.insert("stateTypeId", mockDisplayPinAllowedValuesStateTypeId); stateDescriptorAllowedValues.insert("value", "String value 2"); QVariantMap stateDescriptorColor; stateDescriptorColor.insert("deviceId", testDeviceId); - stateDescriptorColor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptorColor.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptorColor.insert("stateTypeId", mockDisplayPinColorStateTypeId); stateDescriptorColor.insert("value", "#00FF00"); QVariantMap firstStateEvaluator; - firstStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorOr)); + firstStateEvaluator.insert("operator", enumValueName(Types::StateOperatorOr)); firstStateEvaluator.insert("childEvaluators", QVariantList() << createStateEvaluatorFromSingleDescriptor(stateDescriptorPercentage) << createStateEvaluatorFromSingleDescriptor(stateDescriptorDouble)); QVariantMap secondStateEvaluator; - secondStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + secondStateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd)); secondStateEvaluator.insert("childEvaluators", QVariantList() << createStateEvaluatorFromSingleDescriptor(stateDescriptorAllowedValues) << createStateEvaluatorFromSingleDescriptor(stateDescriptorColor)); QVariantMap stateEvaluator; - stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd)); stateEvaluator.insert("childEvaluators", QVariantList() << firstStateEvaluator << secondStateEvaluator); // The rule diff --git a/tests/auto/states/teststates.cpp b/tests/auto/states/teststates.cpp index 16ba8e73..18b34bdd 100644 --- a/tests/auto/states/teststates.cpp +++ b/tests/auto/states/teststates.cpp @@ -73,7 +73,7 @@ void TestStates::getStateValue() QVariant response = injectAndWait("Devices.GetStateValue", params); - verifyDeviceError(response, error); + verifyError(response, "deviceError", enumValueName(error)); } void TestStates::save_load_states() diff --git a/tests/auto/tags/testtags.cpp b/tests/auto/tags/testtags.cpp index a626dbe4..2a25e28a 100644 --- a/tests/auto/tags/testtags.cpp +++ b/tests/auto/tags/testtags.cpp @@ -20,6 +20,7 @@ #include "nymeatestbase.h" #include "servers/mocktcpserver.h" +#include "tagging/tagsstorage.h" using namespace nymeaserver; @@ -27,6 +28,11 @@ class TestTags: public NymeaTestBase { Q_OBJECT +private: + inline void verifyTagError(const QVariant &response, TagsStorage::TagError error = TagsStorage::TagErrorNoError) { + verifyError(response, "tagError", enumValueName(error)); + } + private slots: void addTag_data(); void addTag(); diff --git a/tests/auto/timemanager/testtimemanager.cpp b/tests/auto/timemanager/testtimemanager.cpp index c5fd81c9..c917042e 100644 --- a/tests/auto/timemanager/testtimemanager.cpp +++ b/tests/auto/timemanager/testtimemanager.cpp @@ -29,6 +29,11 @@ class TestTimeManager: public NymeaTestBase { Q_OBJECT +private: + inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) { + verifyError(response, "ruleError", enumValueName(error)); + } + private slots: void initTestCase(); @@ -1078,25 +1083,25 @@ void TestTimeManager::testCalendarItemStates_data() QVariantMap stateEvaluator; QVariantMap stateDescriptorInt; stateDescriptorInt.insert("deviceId", m_mockDeviceId); - stateDescriptorInt.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorGreaterOrEqual)); + stateDescriptorInt.insert("operator", enumValueName(Types::ValueOperatorGreaterOrEqual)); stateDescriptorInt.insert("stateTypeId", mockIntStateTypeId); stateDescriptorInt.insert("value", 65); QVariantMap stateDescriptorBool; stateDescriptorBool.insert("deviceId", m_mockDeviceId); - stateDescriptorBool.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptorBool.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId); stateDescriptorBool.insert("value", true); QVariantMap stateEvaluatorInt; stateEvaluatorInt.insert("stateDescriptor", stateDescriptorInt); - stateEvaluatorInt.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluatorInt.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantMap stateEvaluatorBool; stateEvaluatorBool.insert("stateDescriptor", stateDescriptorBool); - stateEvaluatorBool.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluatorBool.insert("operator", enumValueName(Types::StateOperatorAnd)); QVariantList childEvaluators; childEvaluators.append(stateEvaluatorInt); childEvaluators.append(stateEvaluatorBool); stateEvaluator.insert("childEvaluators", childEvaluators); - stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); + stateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd)); // The rule @@ -1246,7 +1251,7 @@ void TestTimeManager::testCalendarItemStatesEvent_data() // State evaluator QVariantMap stateDescriptorBool; stateDescriptorBool.insert("deviceId", m_mockDeviceId); - stateDescriptorBool.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptorBool.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId); stateDescriptorBool.insert("value", true); @@ -1880,7 +1885,7 @@ void TestTimeManager::testEventItemStates_data() // State evaluator QVariantMap stateDescriptorBool; stateDescriptorBool.insert("deviceId", m_mockDeviceId); - stateDescriptorBool.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); + stateDescriptorBool.insert("operator", enumValueName(Types::ValueOperatorEquals)); stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId); stateDescriptorBool.insert("value", true); @@ -2078,7 +2083,7 @@ void TestTimeManager::setIntState(const int &value) params.insert("deviceId", m_mockDeviceId); params.insert("stateTypeId", mockIntStateTypeId); QVariant response = injectAndWait("Devices.GetStateValue", params); - verifyDeviceError(response); + verifyError(response, "deviceError", "DeviceErrorNoError"); int currentStateValue = response.toMap().value("params").toMap().value("value").toInt(); bool shouldGetNotification = currentStateValue != value; @@ -2119,7 +2124,7 @@ void TestTimeManager::setBoolState(const bool &value) params.insert("deviceId", m_mockDeviceId); params.insert("stateTypeId", mockBoolStateTypeId); QVariant response = injectAndWait("Devices.GetStateValue", params); - verifyDeviceError(response); + verifyError(response, "deviceError", "DeviceErrorNoError"); bool currentStateValue = response.toMap().value("params").toMap().value("value").toBool(); bool shouldGetNotification = currentStateValue != value; diff --git a/tests/auto/usermanager/testusermanager.cpp b/tests/auto/usermanager/testusermanager.cpp index d9f9b150..629139e0 100644 --- a/tests/auto/usermanager/testusermanager.cpp +++ b/tests/auto/usermanager/testusermanager.cpp @@ -23,6 +23,7 @@ #include "logging/logengine.h" #include "nymeacore.h" #include "nymeatestbase.h" +#include "usermanager/usermanager.h" using namespace nymeaserver; diff --git a/tests/auto/webserver/testwebserver.cpp b/tests/auto/webserver/testwebserver.cpp index 24b896c9..264479c1 100644 --- a/tests/auto/webserver/testwebserver.cpp +++ b/tests/auto/webserver/testwebserver.cpp @@ -586,7 +586,7 @@ void TestWebserver::getDebugServer() QVariantMap params; QVariant response; params.insert("enabled", serverEnabled); response = injectAndWait("Configuration.SetDebugServerEnabled", params); - verifyConfigurationError(response); + verifyError(response, "configurationError", "ConfigurationErrorNoError"); QNetworkAccessManager nam; bool ok = false; diff --git a/tests/scripts/introspect.sh b/tests/scripts/introspect.sh index f1b90091..dc3f7b4c 100755 --- a/tests/scripts/introspect.sh +++ b/tests/scripts/introspect.sh @@ -2,11 +2,12 @@ if [ -z $1 ]; then echo "usage: $0 host" -else + exit 1 +fi -cat < #include #include @@ -78,25 +76,17 @@ protected: .toLatin1().data()); } - inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) { - verifyError(response, "ruleError", JsonTypes::ruleErrorToString(error)); + template QString enumValueName(T value) + { + QMetaEnum metaEnum = QMetaEnum::fromType(); + return metaEnum.valueToKey(value); } - inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) { - verifyError(response, "deviceError", JsonTypes::deviceErrorToString(error)); + template T enumNameToValue(const QString &name) { + QMetaEnum metaEnum = QMetaEnum::fromType(); + return static_cast(metaEnum.keyToValue(name.toUtf8())); } - inline void verifyLoggingError(const QVariant &response, Logging::LoggingError error = Logging::LoggingErrorNoError) { - verifyError(response, "loggingError", JsonTypes::loggingErrorToString(error)); - } - - inline void verifyConfigurationError(const QVariant &response, NymeaConfiguration::ConfigurationError error = NymeaConfiguration::ConfigurationErrorNoError) { - verifyError(response, "configurationError", JsonTypes::configurationErrorToString(error)); - } - - inline void verifyTagError(const QVariant &response, TagsStorage::TagError error = TagsStorage::TagErrorNoError) { - verifyError(response, "tagError", JsonTypes::tagErrorToString(error)); - } inline void verifyParams(const QVariantList &requestList, const QVariantList &responseList, bool allRequired = true) { From f1ca2a5b863ec6e04d4ecc349551758aa8517e66 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Thu, 10 Oct 2019 11:39:51 +0200 Subject: [PATCH 02/22] Add experience mode plugins --- .../experiences/experiencemanager.cpp | 11 ++++++++++ libnymea-core/experiences/experiencemanager.h | 22 +++++++++++++++++++ libnymea-core/jsonrpc/jsonrpcserver.h | 4 ++-- libnymea-core/libnymea-core.pro | 2 ++ libnymea-core/nymeacore.cpp | 3 +++ libnymea/experiences/experienceplugin.cpp | 6 +++++ libnymea/experiences/experienceplugin.h | 18 +++++++++++++++ libnymea/libnymea.pro | 2 ++ 8 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 libnymea-core/experiences/experiencemanager.cpp create mode 100644 libnymea-core/experiences/experiencemanager.h create mode 100644 libnymea/experiences/experienceplugin.cpp create mode 100644 libnymea/experiences/experienceplugin.h diff --git a/libnymea-core/experiences/experiencemanager.cpp b/libnymea-core/experiences/experiencemanager.cpp new file mode 100644 index 00000000..90e9e5e4 --- /dev/null +++ b/libnymea-core/experiences/experiencemanager.cpp @@ -0,0 +1,11 @@ +#include "experiencemanager.h" + +#include "jsonrpc/jsonrpcserver.h" +namespace nymeaserver { +ExperienceManager::ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent) +{ +// jsonRpcServer->registerHandler(); + +} + +} diff --git a/libnymea-core/experiences/experiencemanager.h b/libnymea-core/experiences/experiencemanager.h new file mode 100644 index 00000000..2b0b25bc --- /dev/null +++ b/libnymea-core/experiences/experiencemanager.h @@ -0,0 +1,22 @@ +#ifndef EXPERIENCEMANAGER_H +#define EXPERIENCEMANAGER_H + +#include + +namespace nymeaserver { + +class JsonRPCServer; + +class ExperienceManager : public QObject +{ + Q_OBJECT +public: + explicit ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent = nullptr); + +signals: + +public slots: +}; + +} +#endif // EXPERIENCEMANAGER_H diff --git a/libnymea-core/jsonrpc/jsonrpcserver.h b/libnymea-core/jsonrpc/jsonrpcserver.h index 28ee036a..d3709afa 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.h +++ b/libnymea-core/jsonrpc/jsonrpcserver.h @@ -71,6 +71,8 @@ public: void registerTransportInterface(TransportInterface *interface, bool authenticationRequired); void unregisterTransportInterface(TransportInterface *interface); + void registerHandler(JsonHandler *handler); + private: QHash handlers() const; @@ -117,8 +119,6 @@ private: int m_notificationId; - void registerHandler(JsonHandler *handler); - QString formatAssertion(const QString &targetNamespace, const QString &method, QMetaMethod::MethodType methodType, JsonHandler *handler, const QVariantMap &data) const; }; diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro index 69a9807c..f99e9dcf 100644 --- a/libnymea-core/libnymea-core.pro +++ b/libnymea-core/libnymea-core.pro @@ -18,6 +18,7 @@ RESOURCES += $$top_srcdir/icons.qrc \ HEADERS += nymeacore.h \ devices/devicemanagerimplementation.h \ devices/translator.h \ + experiences/experiencemanager.h \ ruleengine/ruleengine.h \ ruleengine/rule.h \ ruleengine/stateevaluator.h \ @@ -95,6 +96,7 @@ HEADERS += nymeacore.h \ SOURCES += nymeacore.cpp \ devices/devicemanagerimplementation.cpp \ devices/translator.cpp \ + experiences/experiencemanager.cpp \ ruleengine/ruleengine.cpp \ ruleengine/rule.cpp \ ruleengine/stateevaluator.cpp \ diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index 6068d8d5..f4089ea9 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -171,6 +171,9 @@ void NymeaCore::init() { qCDebug(dcApplication) << "Creating Cloud Manager"; m_cloudManager = new CloudManager(m_configuration, m_networkManager, this); + qCDebug(dcApplication()) << "Loading experiences"; + + CloudNotifications *cloudNotifications = m_cloudManager->createNotificationsPlugin(); m_deviceManager->registerStaticPlugin(cloudNotifications, cloudNotifications->metaData()); diff --git a/libnymea/experiences/experienceplugin.cpp b/libnymea/experiences/experienceplugin.cpp new file mode 100644 index 00000000..2e7233a4 --- /dev/null +++ b/libnymea/experiences/experienceplugin.cpp @@ -0,0 +1,6 @@ +#include "experienceplugin.h" + +ExperiencePlugin::ExperiencePlugin(QObject *parent) : JsonHandler(parent) +{ + +} diff --git a/libnymea/experiences/experienceplugin.h b/libnymea/experiences/experienceplugin.h new file mode 100644 index 00000000..c6242672 --- /dev/null +++ b/libnymea/experiences/experienceplugin.h @@ -0,0 +1,18 @@ +#ifndef EXPERIENCEPLUGIN_H +#define EXPERIENCEPLUGIN_H + +#include +#include "jsonrpc/jsonhandler.h" + +class ExperiencePlugin : public JsonHandler +{ + Q_OBJECT +public: + explicit ExperiencePlugin(QObject *parent = nullptr); + +signals: + +public slots: +}; + +#endif // EXPERIENCEPLUGIN_H diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index 4d19b679..a3d6c0dd 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -26,6 +26,7 @@ HEADERS += \ devices/browseresult.h \ jsonrpc/jsonhandler.h \ jsonrpc/jsonreply.h \ + experiences/experienceplugin.h \ libnymea.h \ platform/package.h \ platform/repository.h \ @@ -102,6 +103,7 @@ SOURCES += \ devices/browseresult.cpp \ jsonrpc/jsonhandler.cpp \ jsonrpc/jsonreply.cpp \ + experiences/experienceplugin.cpp \ loggingcategories.cpp \ nymeasettings.cpp \ platform/package.cpp \ From a47bded031bd70f1b7e58eccd55ec9295d636966 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Fri, 18 Oct 2019 15:28:42 +0200 Subject: [PATCH 03/22] add loading of plugins --- .../experiences/experiencemanager.cpp | 63 +++++++++++++++++++ libnymea-core/experiences/experiencemanager.h | 10 +++ libnymea-core/nymeacore.cpp | 2 + libnymea/loggingcategories.cpp | 1 + libnymea/loggingcategories.h | 1 + 5 files changed, 77 insertions(+) diff --git a/libnymea-core/experiences/experiencemanager.cpp b/libnymea-core/experiences/experiencemanager.cpp index 90e9e5e4..78559ef5 100644 --- a/libnymea-core/experiences/experiencemanager.cpp +++ b/libnymea-core/experiences/experiencemanager.cpp @@ -1,11 +1,74 @@ #include "experiencemanager.h" +#include "experiences/experienceplugin.h" #include "jsonrpc/jsonrpcserver.h" +#include "loggingcategories.h" + +#include +#include +#include +#include + namespace nymeaserver { + ExperienceManager::ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent) { // jsonRpcServer->registerHandler(); + foreach (const QString &path, pluginSearchDirs()) { + QDir dir(path); + qCDebug(dcExperiences) << "Loading platform plugins from:" << dir.absolutePath(); + foreach (const QString &entry, dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot)) { + QFileInfo fi(path + "/" + entry); + if (fi.isFile()) { + if (entry.startsWith("libnymea_experienceplugin") && entry.endsWith(".so")) { + loadExperiencePlugin(path + "/" + entry); + } + } else if (fi.isDir()) { + if (QFileInfo::exists(path + "/" + entry + "/libnymea_experienceplugin" + entry + ".so")) { + loadExperiencePlugin(path + "/" + entry + "/libnymea_experienceplugin" + entry + ".so"); + } + } + } + } +} + +QStringList ExperienceManager::pluginSearchDirs() const +{ + QStringList searchDirs; + QByteArray envPath = qgetenv("NYMEA_EXPERIENCE_PLUGINS_PATH"); + if (!envPath.isEmpty()) { + searchDirs << QString(envPath).split(':'); + } + + foreach (QString libraryPath, QCoreApplication::libraryPaths()) { + searchDirs << libraryPath.replace("qt5", "nymea").replace("plugins", "experiences"); + } + searchDirs << QCoreApplication::applicationDirPath() + "/../lib/nymea/experiences"; + searchDirs << QCoreApplication::applicationDirPath() + "/../experiences/"; + searchDirs << QCoreApplication::applicationDirPath() + "/../../../experiences/"; + return searchDirs; +} + +void ExperienceManager::loadExperiencePlugin(const QString &file) +{ + QPluginLoader loader; + loader.setFileName(file); + loader.setLoadHints(QLibrary::ResolveAllSymbolsHint); + if (!loader.load()) { + qCWarning(dcExperiences()) << loader.errorString(); + return; + } + ExperiencePlugin *plugin = qobject_cast(loader.instance()); + if (!plugin) { + qCWarning(dcExperiences()) << "Could not get plugin instance of" << loader.fileName(); + loader.unload(); + return; + } + qCDebug(dcExperiences()) << "Loaded experience plugin:" << loader.fileName(); + plugin->setParent(this); + + m_plugins.append(plugin); } } diff --git a/libnymea-core/experiences/experiencemanager.h b/libnymea-core/experiences/experiencemanager.h index 2b0b25bc..62218095 100644 --- a/libnymea-core/experiences/experiencemanager.h +++ b/libnymea-core/experiences/experiencemanager.h @@ -3,6 +3,8 @@ #include +class ExperiencePlugin; + namespace nymeaserver { class JsonRPCServer; @@ -16,6 +18,14 @@ public: signals: public slots: + +private: + QStringList pluginSearchDirs() const; + + void loadExperiencePlugin(const QString &file); + +private: + QList m_plugins; }; } diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index f4089ea9..3562b891 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -97,6 +97,7 @@ #include "nymeasettings.h" #include "tagging/tagsstorage.h" #include "platform/platform.h" +#include "experiences/experiencemanager.h" #include "devices/devicemanagerimplementation.h" #include "devices/device.h" @@ -172,6 +173,7 @@ void NymeaCore::init() { m_cloudManager = new CloudManager(m_configuration, m_networkManager, this); qCDebug(dcApplication()) << "Loading experiences"; + new ExperienceManager(m_serverManager->jsonServer(), this); CloudNotifications *cloudNotifications = m_cloudManager->createNotificationsPlugin(); diff --git a/libnymea/loggingcategories.cpp b/libnymea/loggingcategories.cpp index e879bd6d..4b8cc66e 100644 --- a/libnymea/loggingcategories.cpp +++ b/libnymea/loggingcategories.cpp @@ -30,6 +30,7 @@ Q_LOGGING_CATEGORY(dcSystem, "System") Q_LOGGING_CATEGORY(dcPlatform, "Platform") Q_LOGGING_CATEGORY(dcPlatformUpdate, "PlatformUpdate") Q_LOGGING_CATEGORY(dcPlatformZeroConf, "PlatformZeroConf") +Q_LOGGING_CATEGORY(dcExperiences, "Experiences") Q_LOGGING_CATEGORY(dcTimeManager, "TimeManager") Q_LOGGING_CATEGORY(dcRuleEngine, "RuleEngine") Q_LOGGING_CATEGORY(dcRuleEngineDebug, "RuleEngineDebug") diff --git a/libnymea/loggingcategories.h b/libnymea/loggingcategories.h index 1da7b91c..fec359bc 100644 --- a/libnymea/loggingcategories.h +++ b/libnymea/loggingcategories.h @@ -35,6 +35,7 @@ Q_DECLARE_LOGGING_CATEGORY(dcSystem) Q_DECLARE_LOGGING_CATEGORY(dcPlatform) Q_DECLARE_LOGGING_CATEGORY(dcPlatformUpdate) Q_DECLARE_LOGGING_CATEGORY(dcPlatformZeroConf) +Q_DECLARE_LOGGING_CATEGORY(dcExperiences) Q_DECLARE_LOGGING_CATEGORY(dcTimeManager) Q_DECLARE_LOGGING_CATEGORY(dcRuleEngine) Q_DECLARE_LOGGING_CATEGORY(dcRuleEngineDebug) From fab1871ea1e1f28671a00105b353759bff168ce9 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 19 Oct 2019 20:52:01 +0200 Subject: [PATCH 04/22] loading plugins working --- libnymea-core/experiences/experiencemanager.cpp | 2 +- libnymea-core/nymeacore.cpp | 1 + libnymea/experiences/experienceplugin.cpp | 2 +- libnymea/experiences/experienceplugin.h | 4 +++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/libnymea-core/experiences/experiencemanager.cpp b/libnymea-core/experiences/experiencemanager.cpp index 78559ef5..ec481007 100644 --- a/libnymea-core/experiences/experiencemanager.cpp +++ b/libnymea-core/experiences/experiencemanager.cpp @@ -17,7 +17,7 @@ ExperienceManager::ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *pare foreach (const QString &path, pluginSearchDirs()) { QDir dir(path); - qCDebug(dcExperiences) << "Loading platform plugins from:" << dir.absolutePath(); + qCDebug(dcExperiences) << "Loading experience plugins from:" << dir.absolutePath(); foreach (const QString &entry, dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot)) { QFileInfo fi(path + "/" + entry); if (fi.isFile()) { diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index 3562b891..97b3ac00 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -655,6 +655,7 @@ QStringList NymeaCore::loggingFilters() "Platform", "PlatformUpdate", "PlatformZeroConf", + "Experiences", "Device", "DeviceManager", "RuleEngine", diff --git a/libnymea/experiences/experienceplugin.cpp b/libnymea/experiences/experienceplugin.cpp index 2e7233a4..7714259a 100644 --- a/libnymea/experiences/experienceplugin.cpp +++ b/libnymea/experiences/experienceplugin.cpp @@ -1,6 +1,6 @@ #include "experienceplugin.h" -ExperiencePlugin::ExperiencePlugin(QObject *parent) : JsonHandler(parent) +ExperiencePlugin::ExperiencePlugin(QObject *parent) : QObject(parent) { } diff --git a/libnymea/experiences/experienceplugin.h b/libnymea/experiences/experienceplugin.h index c6242672..54614fab 100644 --- a/libnymea/experiences/experienceplugin.h +++ b/libnymea/experiences/experienceplugin.h @@ -2,7 +2,6 @@ #define EXPERIENCEPLUGIN_H #include -#include "jsonrpc/jsonhandler.h" class ExperiencePlugin : public JsonHandler { @@ -15,4 +14,7 @@ signals: public slots: }; +Q_DECLARE_INTERFACE(ExperiencePlugin, "io.nymea.ExperiencePlugin") + + #endif // EXPERIENCEPLUGIN_H From f8d23db584abf0e471179d6bb34a8634c999e669 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 22 Oct 2019 20:53:37 +0200 Subject: [PATCH 05/22] allow registering json handlers in experience plugins --- libnymea-core/experiences/experiencemanager.cpp | 12 ++++++++++-- libnymea-core/experiences/experiencemanager.h | 6 ++++++ libnymea/experiences/experienceplugin.cpp | 10 ++++++++++ libnymea/experiences/experienceplugin.h | 12 +++++++++--- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/libnymea-core/experiences/experiencemanager.cpp b/libnymea-core/experiences/experiencemanager.cpp index ec481007..4b11eabc 100644 --- a/libnymea-core/experiences/experiencemanager.cpp +++ b/libnymea-core/experiences/experiencemanager.cpp @@ -11,10 +11,14 @@ namespace nymeaserver { -ExperienceManager::ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent) +ExperienceManager::ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent), + m_jsonRpcServer(jsonRpcServer) { -// jsonRpcServer->registerHandler(); + staticMetaObject.invokeMethod(this, "loadPlugins", Qt::QueuedConnection); +} +void ExperienceManager::loadPlugins() +{ foreach (const QString &path, pluginSearchDirs()) { QDir dir(path); qCDebug(dcExperiences) << "Loading experience plugins from:" << dir.absolutePath(); @@ -69,6 +73,10 @@ void ExperienceManager::loadExperiencePlugin(const QString &file) plugin->setParent(this); m_plugins.append(plugin); + + foreach (JsonHandler *handler, plugin->jsonHandlers()) { + m_jsonRpcServer->registerHandler(handler); + } } } diff --git a/libnymea-core/experiences/experiencemanager.h b/libnymea-core/experiences/experiencemanager.h index 62218095..cfb0a3aa 100644 --- a/libnymea-core/experiences/experiencemanager.h +++ b/libnymea-core/experiences/experiencemanager.h @@ -19,9 +19,15 @@ signals: public slots: +private slots: + void loadPlugins(); + private: QStringList pluginSearchDirs() const; +private: + JsonRPCServer *m_jsonRpcServer = nullptr; + void loadExperiencePlugin(const QString &file); private: diff --git a/libnymea/experiences/experienceplugin.cpp b/libnymea/experiences/experienceplugin.cpp index 7714259a..c589c12b 100644 --- a/libnymea/experiences/experienceplugin.cpp +++ b/libnymea/experiences/experienceplugin.cpp @@ -4,3 +4,13 @@ ExperiencePlugin::ExperiencePlugin(QObject *parent) : QObject(parent) { } + +QList ExperiencePlugin::jsonHandlers() const +{ + return m_jsonHandlers; +} + +void ExperiencePlugin::registerJsonHandler(JsonHandler *handler) +{ + m_jsonHandlers.append(handler); +} diff --git a/libnymea/experiences/experienceplugin.h b/libnymea/experiences/experienceplugin.h index 54614fab..845f34cd 100644 --- a/libnymea/experiences/experienceplugin.h +++ b/libnymea/experiences/experienceplugin.h @@ -3,15 +3,21 @@ #include -class ExperiencePlugin : public JsonHandler +class JsonHandler; + +class ExperiencePlugin : public QObject { Q_OBJECT public: explicit ExperiencePlugin(QObject *parent = nullptr); -signals: + QList jsonHandlers() const; -public slots: +protected: + void registerJsonHandler(JsonHandler *handler); + +private: + QList m_jsonHandlers; }; Q_DECLARE_INTERFACE(ExperiencePlugin, "io.nymea.ExperiencePlugin") From e2cf9cb5c3321cf59dd01e1658d589e2d6052afd Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 23 Oct 2019 16:23:28 +0200 Subject: [PATCH 06/22] More work on the experience mode framework --- .../experiences/experiencemanager.cpp | 12 +- libnymea-core/experiences/experiencemanager.h | 6 +- ...er.cpp => jsonrpcserverimplementation.cpp} | 105 +++++++++--------- ...server.h => jsonrpcserverimplementation.h} | 14 ++- libnymea-core/libnymea-core.pro | 12 +- libnymea-core/nymeacore.cpp | 6 +- libnymea-core/nymeacore.h | 4 +- libnymea-core/servermanager.cpp | 6 +- libnymea-core/servermanager.h | 6 +- libnymea/experiences/experienceplugin.cpp | 26 ++++- libnymea/experiences/experienceplugin.h | 18 ++- libnymea/jsonrpc/jsonrpcserver.cpp | 5 + libnymea/jsonrpc/jsonrpcserver.h | 16 +++ libnymea/libnymea.pro | 12 ++ .../time/calendaritem.cpp | 0 .../time/calendaritem.h | 0 .../time/repeatingoption.cpp | 0 .../time/repeatingoption.h | 0 .../time/timedescriptor.cpp | 0 .../time/timedescriptor.h | 0 .../time/timeeventitem.cpp | 0 .../time/timeeventitem.h | 0 22 files changed, 152 insertions(+), 96 deletions(-) rename libnymea-core/jsonrpc/{jsonrpcserver.cpp => jsonrpcserverimplementation.cpp} (91%) rename libnymea-core/jsonrpc/{jsonrpcserver.h => jsonrpcserverimplementation.h} (92%) create mode 100644 libnymea/jsonrpc/jsonrpcserver.cpp create mode 100644 libnymea/jsonrpc/jsonrpcserver.h rename {libnymea-core => libnymea}/time/calendaritem.cpp (100%) rename {libnymea-core => libnymea}/time/calendaritem.h (100%) rename {libnymea-core => libnymea}/time/repeatingoption.cpp (100%) rename {libnymea-core => libnymea}/time/repeatingoption.h (100%) rename {libnymea-core => libnymea}/time/timedescriptor.cpp (100%) rename {libnymea-core => libnymea}/time/timedescriptor.h (100%) rename {libnymea-core => libnymea}/time/timeeventitem.cpp (100%) rename {libnymea-core => libnymea}/time/timeeventitem.h (100%) diff --git a/libnymea-core/experiences/experiencemanager.cpp b/libnymea-core/experiences/experiencemanager.cpp index 4b11eabc..e0582898 100644 --- a/libnymea-core/experiences/experiencemanager.cpp +++ b/libnymea-core/experiences/experiencemanager.cpp @@ -1,7 +1,7 @@ #include "experiencemanager.h" #include "experiences/experienceplugin.h" -#include "jsonrpc/jsonrpcserver.h" +#include "jsonrpc/jsonrpcserverimplementation.h" #include "loggingcategories.h" #include @@ -11,7 +11,8 @@ namespace nymeaserver { -ExperienceManager::ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent), +ExperienceManager::ExperienceManager(DeviceManager *deviceManager, JsonRPCServer *jsonRpcServer, QObject *parent) : QObject(parent), + m_deviceManager(deviceManager), m_jsonRpcServer(jsonRpcServer) { staticMetaObject.invokeMethod(this, "loadPlugins", Qt::QueuedConnection); @@ -70,13 +71,10 @@ void ExperienceManager::loadExperiencePlugin(const QString &file) return; } qCDebug(dcExperiences()) << "Loaded experience plugin:" << loader.fileName(); - plugin->setParent(this); - m_plugins.append(plugin); + plugin->setParent(this); + plugin->initPlugin(m_deviceManager, m_jsonRpcServer); - foreach (JsonHandler *handler, plugin->jsonHandlers()) { - m_jsonRpcServer->registerHandler(handler); - } } } diff --git a/libnymea-core/experiences/experiencemanager.h b/libnymea-core/experiences/experiencemanager.h index cfb0a3aa..1231d456 100644 --- a/libnymea-core/experiences/experiencemanager.h +++ b/libnymea-core/experiences/experiencemanager.h @@ -4,16 +4,17 @@ #include class ExperiencePlugin; +class JsonRPCServer; +class DeviceManager; namespace nymeaserver { -class JsonRPCServer; class ExperienceManager : public QObject { Q_OBJECT public: - explicit ExperienceManager(JsonRPCServer *jsonRpcServer, QObject *parent = nullptr); + explicit ExperienceManager(DeviceManager *deviceManager, JsonRPCServer *jsonRpcServer, QObject *parent = nullptr); signals: @@ -26,6 +27,7 @@ private: QStringList pluginSearchDirs() const; private: + DeviceManager *m_deviceManager = nullptr; JsonRPCServer *m_jsonRpcServer = nullptr; void loadExperiencePlugin(const QString &file); diff --git a/libnymea-core/jsonrpc/jsonrpcserver.cpp b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp similarity index 91% rename from libnymea-core/jsonrpc/jsonrpcserver.cpp rename to libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp index 6ad3d6f8..1f6c8bb4 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp @@ -36,7 +36,7 @@ */ -#include "jsonrpcserver.h" +#include "jsonrpcserverimplementation.h" #include "jsonrpc/jsonhandler.h" #include "jsonvalidator.h" #include "nymeacore.h" @@ -67,7 +67,7 @@ namespace nymeaserver { /*! Constructs a \l{JsonRPCServer} with the given \a sslConfiguration and \a parent. */ -JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject *parent): +JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration &sslConfiguration, QObject *parent): JsonHandler(parent), m_notificationId(0) { @@ -235,16 +235,16 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection); - connect(NymeaCore::instance()->userManager(), &UserManager::pushButtonAuthFinished, this, &JsonRPCServer::onPushButtonAuthFinished); + connect(NymeaCore::instance()->userManager(), &UserManager::pushButtonAuthFinished, this, &JsonRPCServerImplementation::onPushButtonAuthFinished); } /*! Returns the \e namespace of \l{JsonHandler}. */ -QString JsonRPCServer::name() const +QString JsonRPCServerImplementation::name() const { return QStringLiteral("JSONRPC"); } -JsonReply *JsonRPCServer::Hello(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::Hello(const QVariantMap ¶ms) { TransportInterface *interface = reinterpret_cast(property("transportInterface").toLongLong()); @@ -264,13 +264,13 @@ JsonReply *JsonRPCServer::Hello(const QVariantMap ¶ms) return createReply(createWelcomeMessage(interface, clientId)); } -JsonReply* JsonRPCServer::Introspect(const QVariantMap ¶ms) const +JsonReply* JsonRPCServerImplementation::Introspect(const QVariantMap ¶ms) const { Q_UNUSED(params) return createReply(m_api); } -JsonReply* JsonRPCServer::Version(const QVariantMap ¶ms) const +JsonReply* JsonRPCServerImplementation::Version(const QVariantMap ¶ms) const { Q_UNUSED(params) @@ -280,7 +280,7 @@ JsonReply* JsonRPCServer::Version(const QVariantMap ¶ms) const return createReply(data); } -JsonReply* JsonRPCServer::SetNotificationStatus(const QVariantMap ¶ms) +JsonReply* JsonRPCServerImplementation::SetNotificationStatus(const QVariantMap ¶ms) { QUuid clientId = this->property("clientId").toUuid(); Q_ASSERT_X(m_clientTransports.contains(clientId), "JsonRPCServer", "Invalid client ID."); @@ -307,7 +307,7 @@ JsonReply* JsonRPCServer::SetNotificationStatus(const QVariantMap ¶ms) return createReply(returns); } -JsonReply *JsonRPCServer::CreateUser(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::CreateUser(const QVariantMap ¶ms) { QString username = params.value("username").toString(); QString password = params.value("password").toString(); @@ -319,7 +319,7 @@ JsonReply *JsonRPCServer::CreateUser(const QVariantMap ¶ms) return createReply(returns); } -JsonReply *JsonRPCServer::Authenticate(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::Authenticate(const QVariantMap ¶ms) { QString username = params.value("username").toString(); QString password = params.value("password").toString(); @@ -334,7 +334,7 @@ JsonReply *JsonRPCServer::Authenticate(const QVariantMap ¶ms) return createReply(ret); } -JsonReply *JsonRPCServer::RequestPushButtonAuth(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::RequestPushButtonAuth(const QVariantMap ¶ms) { QString deviceName = params.value("deviceName").toString(); QUuid clientId = this->property("clientId").toUuid(); @@ -349,7 +349,7 @@ JsonReply *JsonRPCServer::RequestPushButtonAuth(const QVariantMap ¶ms) return createReply(data); } -JsonReply *JsonRPCServer::Tokens(const QVariantMap ¶ms) const +JsonReply *JsonRPCServerImplementation::Tokens(const QVariantMap ¶ms) const { Q_UNUSED(params) QByteArray token = property("token").toByteArray(); @@ -369,7 +369,7 @@ JsonReply *JsonRPCServer::Tokens(const QVariantMap ¶ms) const return createReply(retMap); } -JsonReply *JsonRPCServer::RemoveToken(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::RemoveToken(const QVariantMap ¶ms) { QUuid tokenId = params.value("tokenId").toUuid(); UserManager::UserError error = NymeaCore::instance()->userManager()->removeToken(tokenId); @@ -378,7 +378,7 @@ JsonReply *JsonRPCServer::RemoveToken(const QVariantMap ¶ms) return createReply(ret); } -JsonReply *JsonRPCServer::SetupCloudConnection(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::SetupCloudConnection(const QVariantMap ¶ms) { if (NymeaCore::instance()->cloudManager()->connectionState() != CloudManager::CloudConnectionStateUnconfigured) { qCDebug(dcCloud) << "Cloud already configured. Not changing configuration as it won't work anyways. If you want to reconfigure this instance to a different cloud, change the system UUID and wipe the cloud settings from the config."; @@ -397,7 +397,7 @@ JsonReply *JsonRPCServer::SetupCloudConnection(const QVariantMap ¶ms) return createReply(ret); } -JsonReply *JsonRPCServer::SetupRemoteAccess(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::SetupRemoteAccess(const QVariantMap ¶ms) { QString idToken = params.value("idToken").toString(); QString userId = params.value("userId").toString(); @@ -410,7 +410,7 @@ JsonReply *JsonRPCServer::SetupRemoteAccess(const QVariantMap ¶ms) return reply; } -JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::IsCloudConnected(const QVariantMap ¶ms) { Q_UNUSED(params) bool connected = NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected; @@ -421,7 +421,7 @@ JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap ¶ms) } /*! A client may use this as a ping/pong mechanism to check server connectivity. */ -JsonReply *JsonRPCServer::KeepAlive(const QVariantMap ¶ms) +JsonReply *JsonRPCServerImplementation::KeepAlive(const QVariantMap ¶ms) { QString sessionId = params.value("sessionId").toString(); qCDebug(dcJsonRpc()) << "KeepAlive received" << sessionId; @@ -432,36 +432,36 @@ JsonReply *JsonRPCServer::KeepAlive(const QVariantMap ¶ms) } /*! Returns the list of registered \l{JsonHandler}{JsonHandlers} and their name.*/ -QHash JsonRPCServer::handlers() const +QHash JsonRPCServerImplementation::handlers() const { return m_handlers; } /*! Register a new \l{TransportInterface} to the JSON server. If the given interface is already registered, just the authenticationRequired flag will be updated. */ -void JsonRPCServer::registerTransportInterface(TransportInterface *interface, bool authenticationRequired) +void JsonRPCServerImplementation::registerTransportInterface(TransportInterface *interface, bool authenticationRequired) { if (!m_interfaces.contains(interface)) { - connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected); - connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected); - connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData); + connect(interface, &TransportInterface::clientConnected, this, &JsonRPCServerImplementation::clientConnected); + connect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServerImplementation::clientDisconnected); + connect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServerImplementation::processData); m_interfaces.insert(interface, authenticationRequired); } else { m_interfaces[interface] = authenticationRequired; } } -void JsonRPCServer::unregisterTransportInterface(TransportInterface *interface) +void JsonRPCServerImplementation::unregisterTransportInterface(TransportInterface *interface) { - disconnect(interface, &TransportInterface::clientConnected, this, &JsonRPCServer::clientConnected); - disconnect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServer::clientDisconnected); - disconnect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServer::processData); + disconnect(interface, &TransportInterface::clientConnected, this, &JsonRPCServerImplementation::clientConnected); + disconnect(interface, &TransportInterface::clientDisconnected, this, &JsonRPCServerImplementation::clientDisconnected); + disconnect(interface, &TransportInterface::dataAvailable, this, &JsonRPCServerImplementation::processData); m_interfaces.take(interface); } /*! Send a JSON success response to the client with the given \a clientId, * \a commandId and \a params to the inerted \l{TransportInterface}. */ -void JsonRPCServer::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms) +void JsonRPCServerImplementation::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms) { QVariantMap response; response.insert("id", commandId); @@ -476,7 +476,7 @@ void JsonRPCServer::sendResponse(TransportInterface *interface, const QUuid &cli /*! Send a JSON error response to the client with the given \a clientId, * \a commandId and \a error to the inerted \l{TransportInterface}. */ -void JsonRPCServer::sendErrorResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) +void JsonRPCServerImplementation::sendErrorResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) { QVariantMap errorResponse; errorResponse.insert("id", commandId); @@ -488,7 +488,7 @@ void JsonRPCServer::sendErrorResponse(TransportInterface *interface, const QUuid interface->sendData(clientId, data); } -void JsonRPCServer::sendUnauthorizedResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) +void JsonRPCServerImplementation::sendUnauthorizedResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error) { QVariantMap errorResponse; errorResponse.insert("id", commandId); @@ -500,7 +500,7 @@ void JsonRPCServer::sendUnauthorizedResponse(TransportInterface *interface, cons interface->sendData(clientId, data); } -QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const +QVariantMap JsonRPCServerImplementation::createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const { QVariantMap handshake; handshake.insert("server", "nymea"); @@ -517,7 +517,7 @@ QVariantMap JsonRPCServer::createWelcomeMessage(TransportInterface *interface, c return handshake; } -void JsonRPCServer::setup() +void JsonRPCServerImplementation::setup() { registerHandler(this); registerHandler(new DeviceHandler(this)); @@ -531,11 +531,11 @@ void JsonRPCServer::setup() registerHandler(new TagsHandler(this)); registerHandler(new SystemHandler(NymeaCore::instance()->platform(), this)); - connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServer::pairingFinished); - connect(NymeaCore::instance()->cloudManager(), &CloudManager::connectionStateChanged, this, &JsonRPCServer::onCloudConnectionStateChanged); + connect(NymeaCore::instance()->cloudManager(), &CloudManager::pairingReply, this, &JsonRPCServerImplementation::pairingFinished); + connect(NymeaCore::instance()->cloudManager(), &CloudManager::connectionStateChanged, this, &JsonRPCServerImplementation::onCloudConnectionStateChanged); } -void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &data) +void JsonRPCServerImplementation::processData(const QUuid &clientId, const QByteArray &data) { qCDebug(dcJsonRpcTraffic()) << "Incoming data:" << data; @@ -562,7 +562,7 @@ void JsonRPCServer::processData(const QUuid &clientId, const QByteArray &data) } } -void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data) +void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data) { QJsonParseError error; QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); @@ -670,7 +670,7 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid m_asyncReplies.insert(reply, interface); reply->setClientId(clientId); reply->setCommandId(commandId); - connect(reply, &JsonReply::finished, this, &JsonRPCServer::asyncReplyFinished); + connect(reply, &JsonReply::finished, this, &JsonRPCServerImplementation::asyncReplyFinished); reply->startWait(); } else { JsonValidator validator; @@ -682,7 +682,7 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid } } -QVariantMap JsonRPCServer::packTokenInfo(const TokenInfo &tokenInfo) +QVariantMap JsonRPCServerImplementation::packTokenInfo(const TokenInfo &tokenInfo) { QVariantMap ret; ret.insert("id", tokenInfo.id().toString()); @@ -692,7 +692,7 @@ QVariantMap JsonRPCServer::packTokenInfo(const TokenInfo &tokenInfo) return ret; } -void JsonRPCServer::sendNotification(const QVariantMap ¶ms) +void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms) { JsonHandler *handler = qobject_cast(sender()); QMetaMethod method = handler->metaObject()->method(senderSignalIndex()); @@ -717,7 +717,7 @@ void JsonRPCServer::sendNotification(const QVariantMap ¶ms) } } -void JsonRPCServer::asyncReplyFinished() +void JsonRPCServerImplementation::asyncReplyFinished() { JsonReply *reply = qobject_cast(sender()); TransportInterface *interface = m_asyncReplies.take(reply); @@ -740,7 +740,7 @@ void JsonRPCServer::asyncReplyFinished() reply->deleteLater(); } -void JsonRPCServer::pairingFinished(QString cognitoUserId, int status, const QString &message) +void JsonRPCServerImplementation::pairingFinished(QString cognitoUserId, int status, const QString &message) { JsonReply *reply = m_pairingRequests.take(cognitoUserId); if (!reply) { @@ -753,7 +753,7 @@ void JsonRPCServer::pairingFinished(QString cognitoUserId, int status, const QSt reply->finished(); } -void JsonRPCServer::onCloudConnectionStateChanged() +void JsonRPCServerImplementation::onCloudConnectionStateChanged() { QVariantMap params; params.insert("connected", NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected); @@ -761,7 +761,7 @@ void JsonRPCServer::onCloudConnectionStateChanged() emit CloudConnectedChanged(params); } -void JsonRPCServer::onPushButtonAuthFinished(int transactionId, bool success, const QByteArray &token) +void JsonRPCServerImplementation::onPushButtonAuthFinished(int transactionId, bool success, const QByteArray &token) { QUuid clientId = m_pushButtonTransactions.take(transactionId); if (clientId.isNull()) { @@ -790,7 +790,7 @@ void JsonRPCServer::onPushButtonAuthFinished(int transactionId, bool success, co transport->sendData(clientId, QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact)); } -void JsonRPCServer::registerHandler(JsonHandler *handler) +bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler) { // Sanity checks on API: // * Make sure all $ref: entries are valid. A Handler can reference Types from previously loaded handlers or own ones. @@ -804,7 +804,7 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QVariantList list = handler->jsonEnums().value(enumName).toList(); if (types.contains(enumName)) { qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name(); - return; + return false; } types.insert(enumName, list); } @@ -817,12 +817,12 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) // Check for name clashes if (types.contains(objectName)) { qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name(); - return; + return false; } // Check for invalid $ref: entries if (!JsonValidator::checkRefs(object, typesIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name(); - return; + return false; } } types = typesIncludingThis; @@ -833,15 +833,15 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QVariantMap method = handler->jsonMethods().value(methodName).toMap(); if (handler->metaObject()->indexOfMethod(methodName.toUtf8() + "(QVariantMap)") < 0) { qCWarning(dcJsonRpc()).nospace().noquote() << "Invalid method \"" << methodName << "\". Method \"JsonReply* " + methodName + "(QVariantMap)\" does not exist. Not registering handler " << handler->name(); - return; + return false; } if (!JsonValidator::checkRefs(method.value("params").toMap(), types)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of method " << methodName << ". Not registering handler " << handler->name(); - return; + return false; } if (!JsonValidator::checkRefs(method.value("returns").toMap(), types)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in return value of method " << methodName << ". Not registering handler " << handler->name(); - return; + return false; } newMethods.insert(handler->name() + '.' + methodName, method); } @@ -853,7 +853,7 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap(); if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name(); - return; + return false; } newNotifications.insert(handler->name() + '.' + notificationName, notification); } @@ -872,9 +872,10 @@ void JsonRPCServer::registerHandler(JsonHandler *handler) QObject::connect(handler, method, this, metaObject()->method(metaObject()->indexOfSlot("sendNotification(QVariantMap)"))); } } + return true; } -void JsonRPCServer::clientConnected(const QUuid &clientId) +void JsonRPCServerImplementation::clientConnected(const QUuid &clientId) { qCDebug(dcJsonRpc()) << "Client connected with uuid" << clientId.toString(); TransportInterface *interface = qobject_cast(sender()); @@ -895,7 +896,7 @@ void JsonRPCServer::clientConnected(const QUuid &clientId) timer->start(10000); } -void JsonRPCServer::clientDisconnected(const QUuid &clientId) +void JsonRPCServerImplementation::clientDisconnected(const QUuid &clientId) { qCDebug(dcJsonRpc()) << "Client disconnected:" << clientId; m_clientTransports.remove(clientId); diff --git a/libnymea-core/jsonrpc/jsonrpcserver.h b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h similarity index 92% rename from libnymea-core/jsonrpc/jsonrpcserver.h rename to libnymea-core/jsonrpc/jsonrpcserverimplementation.h index d3709afa..4f5741bc 100644 --- a/libnymea-core/jsonrpc/jsonrpcserver.h +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h @@ -19,9 +19,10 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ -#ifndef JSONRPCSERVER_H -#define JSONRPCSERVER_H +#ifndef JSONRPCSERVERIMPLEMENTATION_H +#define JSONRPCSERVERIMPLEMENTATION_H +#include "jsonrpc/jsonrpcserver.h" #include "jsonrpc/jsonhandler.h" #include "transportinterface.h" #include "usermanager/usermanager.h" @@ -39,11 +40,11 @@ class Device; namespace nymeaserver { -class JsonRPCServer: public JsonHandler +class JsonRPCServerImplementation: public JsonHandler, public JsonRPCServer { Q_OBJECT public: - JsonRPCServer(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = nullptr); + JsonRPCServerImplementation(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = nullptr); // JsonHandler API implementation QString name() const; @@ -71,7 +72,7 @@ public: void registerTransportInterface(TransportInterface *interface, bool authenticationRequired); void unregisterTransportInterface(TransportInterface *interface); - void registerHandler(JsonHandler *handler); + bool registerHandler(JsonHandler *handler) override; private: QHash handlers() const; @@ -124,4 +125,5 @@ private: } -#endif // JSONRPCSERVER_H +#endif // JSONRPCSERVERIMPLEMENTATION_H + diff --git a/libnymea-core/libnymea-core.pro b/libnymea-core/libnymea-core.pro index f99e9dcf..5e5fbf32 100644 --- a/libnymea-core/libnymea-core.pro +++ b/libnymea-core/libnymea-core.pro @@ -19,6 +19,7 @@ HEADERS += nymeacore.h \ devices/devicemanagerimplementation.h \ devices/translator.h \ experiences/experiencemanager.h \ + jsonrpc/jsonrpcserverimplementation.h \ ruleengine/ruleengine.h \ ruleengine/rule.h \ ruleengine/stateevaluator.h \ @@ -35,7 +36,6 @@ HEADERS += nymeacore.h \ servers/bluetoothserver.h \ servers/websocketserver.h \ servers/mqttbroker.h \ - jsonrpc/jsonrpcserver.h \ jsonrpc/jsonvalidator.h \ jsonrpc/devicehandler.h \ jsonrpc/ruleshandler.h \ @@ -50,10 +50,6 @@ HEADERS += nymeacore.h \ logging/logfilter.h \ logging/logentry.h \ logging/logvaluetool.h \ - time/timedescriptor.h \ - time/calendaritem.h \ - time/repeatingoption.h \ - time/timeeventitem.h \ time/timemanager.h \ networkmanager/dbus-interfaces.h \ networkmanager/networkmanager.h \ @@ -97,6 +93,7 @@ SOURCES += nymeacore.cpp \ devices/devicemanagerimplementation.cpp \ devices/translator.cpp \ experiences/experiencemanager.cpp \ + jsonrpc/jsonrpcserverimplementation.cpp \ ruleengine/ruleengine.cpp \ ruleengine/rule.cpp \ ruleengine/stateevaluator.cpp \ @@ -113,7 +110,6 @@ SOURCES += nymeacore.cpp \ servers/websocketserver.cpp \ servers/bluetoothserver.cpp \ servers/mqttbroker.cpp \ - jsonrpc/jsonrpcserver.cpp \ jsonrpc/jsonvalidator.cpp \ jsonrpc/devicehandler.cpp \ jsonrpc/ruleshandler.cpp \ @@ -127,10 +123,6 @@ SOURCES += nymeacore.cpp \ logging/logfilter.cpp \ logging/logentry.cpp \ logging/logvaluetool.cpp \ - time/timedescriptor.cpp \ - time/calendaritem.cpp \ - time/repeatingoption.cpp \ - time/timeeventitem.cpp \ time/timemanager.cpp \ networkmanager/networkmanager.cpp \ networkmanager/networkdevice.cpp \ diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index 97b3ac00..eb382c48 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -91,7 +91,7 @@ #include "nymeacore.h" #include "loggingcategories.h" #include "platform/platform.h" -#include "jsonrpc/jsonrpcserver.h" +#include "jsonrpc/jsonrpcserverimplementation.h" #include "ruleengine/ruleengine.h" #include "networkmanager/networkmanager.h" #include "nymeasettings.h" @@ -173,7 +173,7 @@ void NymeaCore::init() { m_cloudManager = new CloudManager(m_configuration, m_networkManager, this); qCDebug(dcApplication()) << "Loading experiences"; - new ExperienceManager(m_serverManager->jsonServer(), this); + new ExperienceManager(m_deviceManager, m_serverManager->jsonServer(), this); CloudNotifications *cloudNotifications = m_cloudManager->createNotificationsPlugin(); @@ -854,7 +854,7 @@ LogEngine* NymeaCore::logEngine() const } /*! Returns the pointer to the \l{JsonRPCServer} of this instance. */ -JsonRPCServer *NymeaCore::jsonRPCServer() const +JsonRPCServerImplementation *NymeaCore::jsonRPCServer() const { return m_serverManager->jsonServer(); } diff --git a/libnymea-core/nymeacore.h b/libnymea-core/nymeacore.h index a49c5576..06c7c2f0 100644 --- a/libnymea-core/nymeacore.h +++ b/libnymea-core/nymeacore.h @@ -46,7 +46,7 @@ class Device; namespace nymeaserver { -class JsonRPCServer; +class JsonRPCServerImplementation; class LogEngine; class NetworkManager; class NymeaConfiguration; @@ -81,7 +81,7 @@ public: NymeaConfiguration *configuration() const; LogEngine* logEngine() const; - JsonRPCServer *jsonRPCServer() const; + JsonRPCServerImplementation *jsonRPCServer() const; DeviceManager *deviceManager() const; RuleEngine *ruleEngine() const; TimeManager *timeManager() const; diff --git a/libnymea-core/servermanager.cpp b/libnymea-core/servermanager.cpp index ceb023d8..c2406080 100644 --- a/libnymea-core/servermanager.cpp +++ b/libnymea-core/servermanager.cpp @@ -40,7 +40,7 @@ #include "platform/platform.h" #include "platform/platformzeroconfcontroller.h" -#include "jsonrpc/jsonrpcserver.h" +#include "jsonrpc/jsonrpcserverimplementation.h" #include "servers/mocktcpserver.h" #include "servers/tcpserver.h" #include "servers/websocketserver.h" @@ -99,7 +99,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati } // Interfaces - m_jsonServer = new JsonRPCServer(m_sslConfiguration, this); + m_jsonServer = new JsonRPCServerImplementation(m_sslConfiguration, this); // Transports MockTcpServer *tcpServer = new MockTcpServer(this); @@ -158,7 +158,7 @@ ServerManager::ServerManager(Platform *platform, NymeaConfiguration *configurati } /*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */ -JsonRPCServer *ServerManager::jsonServer() const +JsonRPCServerImplementation *ServerManager::jsonServer() const { return m_jsonServer; } diff --git a/libnymea-core/servermanager.h b/libnymea-core/servermanager.h index 78a4cc26..17831f96 100644 --- a/libnymea-core/servermanager.h +++ b/libnymea-core/servermanager.h @@ -34,7 +34,7 @@ namespace nymeaserver { class Platform; class NymeaConfiguration; -class JsonRPCServer; +class JsonRPCServerImplementation; class TcpServer; class WebSocketServer; class WebServer; @@ -50,7 +50,7 @@ public: explicit ServerManager(Platform *platform, NymeaConfiguration *configuration, QObject *parent = nullptr); // Interfaces - JsonRPCServer *jsonServer() const; + JsonRPCServerImplementation *jsonServer() const; BluetoothServer* bluetoothServer() const; @@ -78,7 +78,7 @@ private: Platform *m_platform = nullptr; // Interfaces - JsonRPCServer *m_jsonServer; + JsonRPCServerImplementation *m_jsonServer; BluetoothServer *m_bluetoothServer; QHash m_tcpServers; diff --git a/libnymea/experiences/experienceplugin.cpp b/libnymea/experiences/experienceplugin.cpp index c589c12b..098a7824 100644 --- a/libnymea/experiences/experienceplugin.cpp +++ b/libnymea/experiences/experienceplugin.cpp @@ -5,12 +5,30 @@ ExperiencePlugin::ExperiencePlugin(QObject *parent) : QObject(parent) } -QList ExperiencePlugin::jsonHandlers() const +/*! This method will be called when the plugin has been completely loaded and experience + logic may start operating. A plugin can reimplment this to do initialisation code. */ +void ExperiencePlugin::init() { - return m_jsonHandlers; + } -void ExperiencePlugin::registerJsonHandler(JsonHandler *handler) +/*! Returns a pointer to the DeviceManager. The pointer won't be valid unless init() has been called. */ +DeviceManager *ExperiencePlugin::deviceManager() { - m_jsonHandlers.append(handler); + return m_deviceManager; +} + +/*! Returns a pointer to the JsonRPCServer. The pointer won't be valid unless init() has been called. */ +JsonRPCServer *ExperiencePlugin::jsonRpcServer() +{ + return m_jsonRpcServer; +} + + +void ExperiencePlugin::initPlugin(DeviceManager *deviceManager, JsonRPCServer *jsonRPCServer) +{ + m_deviceManager = deviceManager; + m_jsonRpcServer = jsonRPCServer; + + init(); } diff --git a/libnymea/experiences/experienceplugin.h b/libnymea/experiences/experienceplugin.h index 845f34cd..1dd7c401 100644 --- a/libnymea/experiences/experienceplugin.h +++ b/libnymea/experiences/experienceplugin.h @@ -3,21 +3,31 @@ #include -class JsonHandler; +class DeviceManager; +class JsonRPCServer; +namespace nymeaserver { +class ExperienceManager; +} class ExperiencePlugin : public QObject { Q_OBJECT public: explicit ExperiencePlugin(QObject *parent = nullptr); - QList jsonHandlers() const; + virtual void init() = 0; protected: - void registerJsonHandler(JsonHandler *handler); + DeviceManager* deviceManager(); + JsonRPCServer* jsonRpcServer(); private: - QList m_jsonHandlers; + friend class nymeaserver::ExperienceManager; + void initPlugin(DeviceManager *deviceManager, JsonRPCServer *jsonRPCServer); + + DeviceManager *m_deviceManager = nullptr; + JsonRPCServer *m_jsonRpcServer = nullptr; + }; Q_DECLARE_INTERFACE(ExperiencePlugin, "io.nymea.ExperiencePlugin") diff --git a/libnymea/jsonrpc/jsonrpcserver.cpp b/libnymea/jsonrpc/jsonrpcserver.cpp new file mode 100644 index 00000000..3bcc03f2 --- /dev/null +++ b/libnymea/jsonrpc/jsonrpcserver.cpp @@ -0,0 +1,5 @@ +#include "jsonrpcserver.h" + +/*! \fn void JsonRPCServer::registerJsonHandler(JsonHandler *handler) + Register a JSON RPC handler on the JSON RPC server. +*/ diff --git a/libnymea/jsonrpc/jsonrpcserver.h b/libnymea/jsonrpc/jsonrpcserver.h new file mode 100644 index 00000000..b83c3a47 --- /dev/null +++ b/libnymea/jsonrpc/jsonrpcserver.h @@ -0,0 +1,16 @@ +#ifndef JSONRPCSERVER_H +#define JSONRPCSERVER_H + +class JsonHandler; + +class JsonRPCServer +{ +public: + explicit JsonRPCServer() = default; + virtual ~JsonRPCServer() = default; + + virtual bool registerHandler(JsonHandler *handler) = 0; + +}; + +#endif // JSONRPCSERVER_H diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index a3d6c0dd..b00b7833 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -27,6 +27,7 @@ HEADERS += \ jsonrpc/jsonhandler.h \ jsonrpc/jsonreply.h \ experiences/experienceplugin.h \ + jsonrpc/jsonrpcserver.h \ libnymea.h \ platform/package.h \ platform/repository.h \ @@ -76,6 +77,10 @@ HEADERS += \ types/paramdescriptor.h \ types/statedescriptor.h \ types/interface.h \ + time/timedescriptor.h \ + time/calendaritem.h \ + time/repeatingoption.h \ + time/timeeventitem.h \ hardwareresource.h \ plugintimer.h \ hardwaremanager.h \ @@ -85,6 +90,7 @@ HEADERS += \ platform/platformsystemcontroller.h \ platform/platformupdatecontroller.h \ platform/platformzeroconfcontroller.h \ + experiences/experienceplugin.h \ SOURCES += \ devices/browseractioninfo.cpp \ @@ -104,6 +110,7 @@ SOURCES += \ jsonrpc/jsonhandler.cpp \ jsonrpc/jsonreply.cpp \ experiences/experienceplugin.cpp \ + jsonrpc/jsonrpcserver.cpp \ loggingcategories.cpp \ nymeasettings.cpp \ platform/package.cpp \ @@ -151,6 +158,10 @@ SOURCES += \ types/paramdescriptor.cpp \ types/statedescriptor.cpp \ types/interface.cpp \ + time/timedescriptor.cpp \ + time/calendaritem.cpp \ + time/repeatingoption.cpp \ + time/timeeventitem.cpp \ hardwareresource.cpp \ plugintimer.cpp \ hardwaremanager.cpp \ @@ -160,6 +171,7 @@ SOURCES += \ platform/platformsystemcontroller.cpp \ platform/platformupdatecontroller.cpp \ platform/platformzeroconfcontroller.cpp \ + experiences/experienceplugin.cpp \ RESOURCES += \ diff --git a/libnymea-core/time/calendaritem.cpp b/libnymea/time/calendaritem.cpp similarity index 100% rename from libnymea-core/time/calendaritem.cpp rename to libnymea/time/calendaritem.cpp diff --git a/libnymea-core/time/calendaritem.h b/libnymea/time/calendaritem.h similarity index 100% rename from libnymea-core/time/calendaritem.h rename to libnymea/time/calendaritem.h diff --git a/libnymea-core/time/repeatingoption.cpp b/libnymea/time/repeatingoption.cpp similarity index 100% rename from libnymea-core/time/repeatingoption.cpp rename to libnymea/time/repeatingoption.cpp diff --git a/libnymea-core/time/repeatingoption.h b/libnymea/time/repeatingoption.h similarity index 100% rename from libnymea-core/time/repeatingoption.h rename to libnymea/time/repeatingoption.h diff --git a/libnymea-core/time/timedescriptor.cpp b/libnymea/time/timedescriptor.cpp similarity index 100% rename from libnymea-core/time/timedescriptor.cpp rename to libnymea/time/timedescriptor.cpp diff --git a/libnymea-core/time/timedescriptor.h b/libnymea/time/timedescriptor.h similarity index 100% rename from libnymea-core/time/timedescriptor.h rename to libnymea/time/timedescriptor.h diff --git a/libnymea-core/time/timeeventitem.cpp b/libnymea/time/timeeventitem.cpp similarity index 100% rename from libnymea-core/time/timeeventitem.cpp rename to libnymea/time/timeeventitem.cpp diff --git a/libnymea-core/time/timeeventitem.h b/libnymea/time/timeeventitem.h similarity index 100% rename from libnymea-core/time/timeeventitem.h rename to libnymea/time/timeeventitem.h From bdd9876a880301f6cd42c36fb1b008e122d9fec9 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Fri, 25 Oct 2019 13:13:06 +0200 Subject: [PATCH 07/22] Allow registering QMetaObjects on JSON api --- .../devices/devicemanagerimplementation.cpp | 37 ++ .../devices/devicemanagerimplementation.h | 3 + libnymea-core/jsonrpc/actionhandler.cpp | 20 +- .../jsonrpc/configurationhandler.cpp | 71 +--- libnymea-core/jsonrpc/configurationhandler.h | 3 - libnymea-core/jsonrpc/devicehandler.cpp | 320 +++--------------- libnymea-core/jsonrpc/devicehandler.h | 17 +- libnymea-core/jsonrpc/eventhandler.cpp | 27 +- .../jsonrpc/jsonrpcserverimplementation.cpp | 77 +++-- .../jsonrpc/jsonrpcserverimplementation.h | 3 - libnymea-core/jsonrpc/jsonvalidator.cpp | 67 ++-- libnymea-core/jsonrpc/jsonvalidator.h | 6 +- libnymea-core/jsonrpc/logginghandler.cpp | 17 +- libnymea-core/jsonrpc/ruleshandler.cpp | 7 +- libnymea-core/jsonrpc/statehandler.cpp | 3 +- libnymea-core/logging/logentry.h | 10 + libnymea-core/nymeaconfiguration.h | 16 + libnymea-core/usermanager/tokeninfo.h | 7 + libnymea/devices/device.h | 13 +- libnymea/devices/devicedescriptor.h | 7 + libnymea/devices/devicemanager.h | 4 +- libnymea/devices/deviceplugin.h | 10 +- libnymea/devices/pluginmetadata.cpp | 6 +- libnymea/jsonrpc/jsonhandler.cpp | 78 +++++ libnymea/jsonrpc/jsonhandler.h | 104 +++++- libnymea/libnymea.pro | 6 +- libnymea/time/calendaritem.cpp | 7 +- libnymea/time/calendaritem.h | 8 +- libnymea/time/repeatingoption.cpp | 4 - libnymea/time/repeatingoption.h | 3 - libnymea/time/timedescriptor.cpp | 4 - libnymea/time/timedescriptor.h | 3 - libnymea/time/timeeventitem.cpp | 3 - libnymea/time/timeeventitem.h | 3 - libnymea/types/action.cpp | 10 + libnymea/types/action.h | 7 + libnymea/types/actiontype.cpp | 5 + libnymea/types/actiontype.h | 12 + libnymea/types/browseritem.h | 10 + libnymea/types/deviceclass.h | 17 + libnymea/types/event.cpp | 2 +- libnymea/types/event.h | 4 + libnymea/types/eventtype.cpp | 10 + libnymea/types/eventtype.h | 13 + libnymea/types/mediabrowseritem.h | 2 + libnymea/types/param.cpp | 5 + libnymea/types/param.h | 8 +- libnymea/types/paramtype.cpp | 5 + libnymea/types/paramtype.h | 19 ++ libnymea/types/state.cpp | 20 ++ libnymea/types/state.h | 17 + libnymea/types/statetype.cpp | 10 + libnymea/types/statetype.h | 18 + libnymea/types/vendor.h | 5 + libnymea/typeutils.h | 2 +- tests/scripts/getactiontype.sh | 8 +- tests/scripts/getactiontypes.sh | 9 +- tests/scripts/getconfigureddevices.sh | 20 +- tests/scripts/geteventtype.sh | 11 + tests/scripts/geteventtypes.sh | 8 +- tests/scripts/getpluginconfig.sh | 9 +- tests/scripts/getplugins.sh | 8 +- tests/scripts/getsupporteddevices.sh | 22 +- tests/scripts/token.sh | 11 + 64 files changed, 762 insertions(+), 519 deletions(-) create mode 100755 tests/scripts/geteventtype.sh create mode 100755 tests/scripts/token.sh diff --git a/libnymea-core/devices/devicemanagerimplementation.cpp b/libnymea-core/devices/devicemanagerimplementation.cpp index bb079ad6..6148930a 100644 --- a/libnymea-core/devices/devicemanagerimplementation.cpp +++ b/libnymea-core/devices/devicemanagerimplementation.cpp @@ -865,6 +865,43 @@ QString DeviceManagerImplementation::translate(const PluginId &pluginId, const Q return m_translator->translate(pluginId, string, locale); } +ParamType DeviceManagerImplementation::translateParamType(const PluginId &pluginId, const ParamType ¶mType, const QLocale &locale) +{ + ParamType translatedParamType = paramType; + translatedParamType.setDisplayName(translate(pluginId, paramType.displayName(), locale)); + return translatedParamType; +} + +DeviceClass DeviceManagerImplementation::translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) +{ + DeviceClass translatedDeviceClass = deviceClass; + translatedDeviceClass.setDisplayName(translate(deviceClass.pluginId(), deviceClass.displayName(), locale)); + + ParamTypes translatedSettingsTypes; + foreach (const ParamType ¶mType, deviceClass.settingsTypes()) { + translatedSettingsTypes.append(translateParamType(deviceClass.pluginId(), paramType, locale)); + } + translatedDeviceClass.setSettingsTypes(translatedSettingsTypes); + return translatedDeviceClass; +} + +Vendor DeviceManagerImplementation::translateVendor(const Vendor &vendor, const QLocale &locale) +{ + DevicePlugin *plugin = nullptr; + foreach (DevicePlugin *p, m_devicePlugins) { + if (p->supportedVendors().contains(vendor)) { + plugin = p; + } + } + if (!plugin) { + return vendor; + } + + Vendor translatedVendor = vendor; + translatedVendor.setDisplayName(translate(plugin->pluginId(), vendor.displayName(), locale)); + return translatedVendor; +} + /*! Returns the \l{Device} with the given \a id. Null if the id couldn't be found. */ Device *DeviceManagerImplementation::findConfiguredDevice(const DeviceId &id) const { diff --git a/libnymea-core/devices/devicemanagerimplementation.h b/libnymea-core/devices/devicemanagerimplementation.h index 0d40756d..b3e7918e 100644 --- a/libnymea-core/devices/devicemanagerimplementation.h +++ b/libnymea-core/devices/devicemanagerimplementation.h @@ -107,6 +107,9 @@ public: BrowserItemActionInfo *executeBrowserItemAction(const BrowserItemAction &browserItemAction) override; QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override; + ParamType translateParamType(const PluginId &pluginId, const ParamType ¶mType, const QLocale &locale) override; + DeviceClass translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) override; + Vendor translateVendor(const Vendor &vendor, const QLocale &locale) override; signals: void loaded(); diff --git a/libnymea-core/jsonrpc/actionhandler.cpp b/libnymea-core/jsonrpc/actionhandler.cpp index 19c204e7..22e721dc 100644 --- a/libnymea-core/jsonrpc/actionhandler.cpp +++ b/libnymea-core/jsonrpc/actionhandler.cpp @@ -41,6 +41,7 @@ #include "devices/browseractioninfo.h" #include "devices/browseritemactioninfo.h" #include "types/action.h" +#include "types/actiontype.h" #include "loggingcategories.h" namespace nymeaserver { @@ -49,12 +50,15 @@ namespace nymeaserver { ActionHandler::ActionHandler(QObject *parent) : JsonHandler(parent) { + // Enums + registerEnum(); + registerEnum(); + // Objects - QVariantMap action; - action.insert("actionTypeId", enumValueName(Uuid)); - action.insert("deviceId", enumValueName(Uuid)); - action.insert("o:params", QVariantList() << objectRef("Param")); - registerObject("Action", action); + registerObject(); + registerObject(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -125,14 +129,18 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap ¶ms) JsonReply *ActionHandler::GetActionType(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); qCDebug(dcJsonRpc) << "asked for action type" << params; ActionTypeId actionTypeId(params.value("actionTypeId").toString()); foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const ActionType &actionType, deviceClass.actionTypes()) { if (actionType.id() == actionTypeId) { + ActionType translatedActionType = actionType; + translatedActionType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), actionType.displayName(), locale)); + QVariantMap data; data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); - data.insert("actionType", DeviceHandler::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); + data.insert("actionType", pack(translatedActionType)); return createReply(data); } } diff --git a/libnymea-core/jsonrpc/configurationhandler.cpp b/libnymea-core/jsonrpc/configurationhandler.cpp index 597d50a7..4a3f4f64 100644 --- a/libnymea-core/jsonrpc/configurationhandler.cpp +++ b/libnymea-core/jsonrpc/configurationhandler.cpp @@ -72,25 +72,9 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): registerEnum(); // Objects - QVariantMap serverConfiguration; - serverConfiguration.insert("id", enumValueName(String)); - serverConfiguration.insert("address", enumValueName(String)); - serverConfiguration.insert("port", enumValueName(Uint)); - serverConfiguration.insert("sslEnabled", enumValueName(Bool)); - serverConfiguration.insert("authenticationEnabled", enumValueName(Bool)); - registerObject("ServerConfiguration", serverConfiguration); - - QVariantMap webServerConfiguration = serverConfiguration; - webServerConfiguration.insert("publicFolder", enumValueName(String)); - registerObject("WebServerConfiguration", webServerConfiguration); - - QVariantMap mqttPolicy; - mqttPolicy.insert("clientId", enumValueName(String)); - mqttPolicy.insert("username", enumValueName(String)); - mqttPolicy.insert("password", enumValueName(String)); - mqttPolicy.insert("allowedPublishTopicFilters", enumValueName(StringList)); - mqttPolicy.insert("allowedSubscribeTopicFilters", enumValueName(StringList)); - registerObject("MqttPolicy", mqttPolicy); + registerObject(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -327,20 +311,20 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap ¶ms) co returns.insert("basicConfiguration", packBasicConfiguration()); QVariantList tcpServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) { - tcpServerConfigs.append(packServerConfiguration(config)); + tcpServerConfigs.append(pack(config)); } returns.insert("tcpServerConfigurations", tcpServerConfigs); QVariantList webServerConfigs; foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - webServerConfigs.append(packWebServerConfiguration(config)); + webServerConfigs.append(pack(config)); } returns.insert("webServerConfigurations", webServerConfigs); QVariantList webSocketServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) { - webSocketServerConfigs.append(packServerConfiguration(config)); + webSocketServerConfigs.append(pack(config)); } returns.insert("webSocketServerConfigurations", webSocketServerConfigs); @@ -503,7 +487,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap & QVariantMap ret; QVariantList mqttServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->mqttServerConfigurations()) { - mqttServerConfigs << packServerConfiguration(config); + mqttServerConfigs << pack(config); } ret.insert("mqttServerConfigurations", mqttServerConfigs); return createReply(ret); @@ -545,7 +529,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap ¶ms) cons Q_UNUSED(params) QVariantList mqttPolicies; foreach (const MqttPolicy &policy, NymeaCore::instance()->configuration()->mqttPolicies()) { - mqttPolicies << packMqttPolicy(policy); + mqttPolicies << pack(policy); } QVariantMap ret; ret.insert("mqttPolicies", mqttPolicies); @@ -592,7 +576,7 @@ void ConfigurationHandler::onTcpServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: TCP server configuration changed"; QVariantMap params; - params.insert("tcpServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id))); + params.insert("tcpServerConfiguration", pack(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id))); emit TcpServerConfigurationChanged(params); } @@ -608,7 +592,7 @@ void ConfigurationHandler::onWebServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: web server configuration changed"; QVariantMap params; - params.insert("webServerConfiguration", packWebServerConfiguration(NymeaCore::instance()->configuration()->webServerConfigurations().value(id))); + params.insert("webServerConfiguration", pack(NymeaCore::instance()->configuration()->webServerConfigurations().value(id))); emit WebServerConfigurationChanged(params); } @@ -624,7 +608,7 @@ void ConfigurationHandler::onWebSocketServerConfigurationChanged(const QString & { qCDebug(dcJsonRpc()) << "Notification: web socket server configuration changed"; QVariantMap params; - params.insert("webSocketServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id))); + params.insert("webSocketServerConfiguration", pack(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id))); emit WebSocketServerConfigurationChanged(params); } @@ -640,7 +624,7 @@ void ConfigurationHandler::onMqttServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed"; QVariantMap params; - params.insert("mqttServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id))); + params.insert("mqttServerConfiguration", pack(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id))); emit MqttServerConfigurationChanged(params); } @@ -656,7 +640,7 @@ void ConfigurationHandler::onMqttPolicyChanged(const QString &clientId) { qCDebug(dcJsonRpc()) << "Notification: MQTT policy changed"; QVariantMap params; - params.insert("policy", packMqttPolicy(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId))); + params.insert("policy", pack(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId))); emit MqttPolicyChanged(params); } @@ -680,34 +664,6 @@ QVariantMap ConfigurationHandler::packBasicConfiguration() return basicConfiguration; } -QVariantMap ConfigurationHandler::packServerConfiguration(const ServerConfiguration &config) -{ - QVariantMap serverConfiguration; - serverConfiguration.insert("id", config.id); - serverConfiguration.insert("address", config.address.toString()); - serverConfiguration.insert("port", config.port); - serverConfiguration.insert("sslEnabled", config.sslEnabled); - serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled); - return serverConfiguration; -} - -QVariantMap ConfigurationHandler::packWebServerConfiguration(const WebServerConfiguration &config) -{ - QVariantMap webServerConfiguration = packServerConfiguration(config); - webServerConfiguration.insert("publicFolder", config.publicFolder); - return webServerConfiguration; -} - -QVariantMap ConfigurationHandler::packMqttPolicy(const MqttPolicy &policy) -{ - QVariantMap policyMap; - policyMap.insert("clientId", policy.clientId); - policyMap.insert("username", policy.username); - policyMap.insert("password", policy.password); - policyMap.insert("allowedPublishTopicFilters", policy.allowedPublishTopicFilters); - policyMap.insert("allowedSubscribeTopicFilters", policy.allowedSubscribeTopicFilters); - return policyMap; -} MqttPolicy ConfigurationHandler::unpackMqttPolicy(const QVariantMap &mqttPolicyMap) { @@ -741,6 +697,7 @@ WebServerConfiguration ConfigurationHandler::unpackWebServerConfiguration(const webServerConfiguration.sslEnabled = tmp.sslEnabled; webServerConfiguration.authenticationEnabled = tmp.authenticationEnabled; webServerConfiguration.publicFolder = webServerConfigurationMap.value("publicFolder").toString(); + qWarning() << "Unpacking web server config:" << webServerConfigurationMap; return webServerConfiguration; } diff --git a/libnymea-core/jsonrpc/configurationhandler.h b/libnymea-core/jsonrpc/configurationhandler.h index df15a937..578debdb 100644 --- a/libnymea-core/jsonrpc/configurationhandler.h +++ b/libnymea-core/jsonrpc/configurationhandler.h @@ -92,9 +92,6 @@ private slots: private: static QVariantMap packBasicConfiguration(); - static QVariantMap packServerConfiguration(const ServerConfiguration &config); - static QVariantMap packWebServerConfiguration(const WebServerConfiguration &config); - static QVariantMap packMqttPolicy(const MqttPolicy &policy); static ServerConfiguration unpackServerConfiguration(const QVariantMap &serverConfigurationMap); static WebServerConfiguration unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap); diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 20383cd7..37429bee 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -80,7 +80,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : // Enums registerEnum(); registerEnum(); - registerEnum(); + registerEnum(); registerEnum(); registerEnum(); registerEnum(); @@ -88,109 +88,20 @@ DeviceHandler::DeviceHandler(QObject *parent) : registerEnum(); // Objects - QVariantMap paramType; - paramType.insert("id", enumValueName(Uuid)); - paramType.insert("name", enumValueName(String)); - paramType.insert("displayName", enumValueName(String)); - paramType.insert("type", enumRef()); - paramType.insert("index", enumValueName(Int)); - paramType.insert("o:defaultValue", enumValueName(Variant)); - paramType.insert("o:minValue", enumValueName(Variant)); - paramType.insert("o:maxValue", enumValueName(Variant)); - paramType.insert("o:allowedValues", QVariantList() << enumValueName(Variant)); - paramType.insert("o:inputType", enumRef()); - paramType.insert("o:unit", enumRef()); - paramType.insert("o:readOnly", enumValueName(Bool)); - registerObject("ParamType", paramType); - - QVariantMap param; - param.insert("paramTypeId", enumValueName(Uuid)); - param.insert("value", enumValueName(Variant)); - registerObject("Param", param); - - QVariantMap plugin; - plugin.insert("id", enumValueName(Uuid)); - plugin.insert("name", enumValueName(String)); - plugin.insert("displayName", enumValueName(String)); - plugin.insert("paramTypes", QVariantList() << objectRef("ParamType")); - registerObject("Plugin", plugin); - - QVariantMap vendor; - vendor.insert("id", enumValueName(Uuid)); - vendor.insert("name", enumValueName(String)); - vendor.insert("displayName", enumValueName(String)); - registerObject("Vendor", vendor); - - QVariantMap eventType; - eventType.insert("id", enumValueName(Uuid)); - eventType.insert("name", enumValueName(String)); - eventType.insert("displayName", enumValueName(String)); - eventType.insert("index", enumValueName(Int)); - eventType.insert("paramTypes", QVariantList() << objectRef("ParamType")); - registerObject("EventType", eventType); - - QVariantMap stateType; - stateType.insert("id", enumValueName(Uuid)); - stateType.insert("name", enumValueName(String)); - stateType.insert("displayName", enumValueName(String)); - stateType.insert("type", enumRef()); - stateType.insert("index", enumValueName(Int)); - stateType.insert("defaultValue", enumValueName(Variant)); - stateType.insert("o:unit", enumRef()); - stateType.insert("o:minValue", enumValueName(Variant)); - stateType.insert("o:maxValue", enumValueName(Variant)); - stateType.insert("o:possibleValues", QVariantList() << enumValueName(Variant)); - registerObject("StateType", stateType); - - QVariantMap actionType; - actionType.insert("id", enumValueName(Uuid)); - actionType.insert("name", enumValueName(String)); - actionType.insert("displayName", enumValueName(String)); - actionType.insert("index", enumValueName(Int)); - actionType.insert("paramTypes", QVariantList() << objectRef("ParamType")); - registerObject("ActionType", actionType); - - QVariantMap deviceClass; - deviceClass.insert("id", enumValueName(Uuid)); - deviceClass.insert("vendorId", enumValueName(Uuid)); - deviceClass.insert("pluginId", enumValueName(Uuid)); - deviceClass.insert("name", enumValueName(String)); - deviceClass.insert("displayName", enumValueName(String)); - deviceClass.insert("interfaces", QVariantList() << enumValueName(String)); - deviceClass.insert("browsable", enumValueName(Bool)); - deviceClass.insert("setupMethod", enumRef()); - deviceClass.insert("createMethods", QVariantList() << enumRef()); - deviceClass.insert("stateTypes", QVariantList() << objectRef("StateType")); - deviceClass.insert("eventTypes", QVariantList() << objectRef("EventType")); - deviceClass.insert("actionTypes", QVariantList() << objectRef("ActionType")); - deviceClass.insert("browserItemActionTypes", QVariantList() << objectRef("ActionType")); - deviceClass.insert("paramTypes", QVariantList() << objectRef("ParamType")); - deviceClass.insert("settingsTypes", QVariantList() << objectRef("ParamType")); - deviceClass.insert("discoveryParamTypes", QVariantList() << objectRef("ParamType")); - registerObject("DeviceClass", deviceClass); - - QVariantMap deviceDescriptor; - deviceDescriptor.insert("id", enumValueName(Uuid)); - deviceDescriptor.insert("deviceId", enumValueName(Uuid)); - deviceDescriptor.insert("title", enumValueName(String)); - deviceDescriptor.insert("description", enumValueName(String)); - deviceDescriptor.insert("deviceParams", QVariantList() << objectRef("Param")); - registerObject("DeviceDescriptor", deviceDescriptor); - - QVariantMap device; - device.insert("id", enumValueName(Uuid)); - device.insert("deviceClassId", enumValueName(Uuid)); - device.insert("name", enumValueName(String)); - device.insert("params", QVariantList() << objectRef("Param")); - device.insert("settings", QVariantList() << objectRef("Param")); - QVariantMap stateValues; - stateValues.insert("stateTypeId", enumValueName(Uuid)); - stateValues.insert("value", enumValueName(Variant)); - device.insert("states", QVariantList() << stateValues); - device.insert("setupComplete", enumValueName(Bool)); - device.insert("o:parentId", enumValueName(Uuid)); - registerObject("Device", device); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + // Regsitering browseritem manually for now. Not sure how to deal with the + // polymorphism in int (e.g MediaBrowserItem) QVariantMap browserItem; browserItem.insert("id", enumValueName(String)); browserItem.insert("displayName", enumValueName(String)); @@ -219,7 +130,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Returns a list of loaded plugins."; - returns.insert("plugins", QVariantList() << objectRef("Plugin")); + returns.insert("plugins", QVariantList() << objectRef("DevicePlugin")); registerMethod("GetPlugins", description, params, returns); params.clear(); returns.clear(); @@ -467,18 +378,8 @@ JsonReply* DeviceHandler::GetSupportedVendors(const QVariantMap ¶ms) const QVariantList vendors; foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) { - - DevicePlugin *plugin = nullptr; - foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) { - if (p->supportedVendors().contains(vendor)) { - plugin = p; - } - } - QVariantMap variantMap; - variantMap.insert("id", vendor.id().toString()); - variantMap.insert("name", vendor.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale)); - vendors.append(variantMap); + Vendor translatedVendor = NymeaCore::instance()->deviceManager()->translateVendor(vendor, locale); + vendors.append(pack(translatedVendor)); } QVariantMap returns; @@ -492,8 +393,10 @@ JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap ¶ms) const VendorId vendorId = VendorId(params.value("vendorId").toString()); QVariantMap returns; QVariantList deviceClasses; - foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) - deviceClasses.append(packDeviceClass(deviceClass, locale)); + foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) { + DeviceClass translatedDeviceClass = NymeaCore::instance()->deviceManager()->translateDeviceClass(deviceClass, locale); + deviceClasses.append(pack(translatedDeviceClass)); + } returns.insert("deviceClasses", deviceClasses); return createReply(returns); @@ -511,14 +414,14 @@ JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap ¶ms) const JsonReply *reply = createAsyncReply("GetDiscoveredDevices"); DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(deviceClassId, discoveryParams); - connect(info, &DeviceDiscoveryInfo::finished, reply, [reply, info, locale](){ + connect(info, &DeviceDiscoveryInfo::finished, reply, [this, reply, info, locale](){ QVariantMap returns; returns.insert("deviceError", enumValueName(info->status())); if (info->status() == Device::DeviceErrorNoError) { QVariantList deviceDescriptorList; foreach (const DeviceDescriptor &deviceDescriptor, info->deviceDescriptors()) { - deviceDescriptorList.append(packDeviceDescriptor(deviceDescriptor)); + deviceDescriptorList.append(pack(deviceDescriptor)); } returns.insert("deviceDescriptors", deviceDescriptorList); } @@ -540,7 +443,9 @@ JsonReply* DeviceHandler::GetPlugins(const QVariantMap ¶ms) const QVariantList plugins; foreach (DevicePlugin* plugin, NymeaCore::instance()->deviceManager()->plugins()) { - plugins.append(packPlugin(plugin, locale)); + QVariantMap packedPlugin = pack(*plugin); + packedPlugin["displayName"] = NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale); + plugins.append(packedPlugin); } QVariantMap returns; @@ -560,7 +465,7 @@ JsonReply *DeviceHandler::GetPluginConfiguration(const QVariantMap ¶ms) cons QVariantList paramVariantList; foreach (const Param ¶m, plugin->configuration()) { - paramVariantList.append(packParam(param)); + paramVariantList.append(pack(param)); } returns.insert("configuration", paramVariantList); returns.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); @@ -820,12 +725,15 @@ JsonReply* DeviceHandler::GetActionTypes(const QVariantMap ¶ms) const JsonReply* DeviceHandler::GetStateTypes(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); + QVariantMap returns; QVariantList stateList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); - foreach (const StateType &stateType, deviceClass.stateTypes()) { - stateList.append(packStateType(stateType, deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())); + foreach (StateType stateType, deviceClass.stateTypes()) { + stateType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), stateType.displayName(), locale)); + stateList.append(pack(stateType)); } returns.insert("stateTypes", stateList); return createReply(returns); @@ -908,7 +816,7 @@ Param DeviceHandler::unpackParam(const QVariantMap ¶m) if (param.keys().count() == 0) return Param(); - ParamTypeId paramTypeId = param.value("paramTypeId").toString(); + ParamTypeId paramTypeId = param.value("paramTypeId").toUuid(); QVariant value = param.value("value"); return Param(paramTypeId, value); } @@ -992,56 +900,14 @@ QVariantMap DeviceHandler::packBrowserItem(const BrowserItem &item) return ret; } -QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) +QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) const { - QVariantMap variantMap; - variantMap.insert("id", paramType.id().toString()); - variantMap.insert("name", paramType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); - variantMap.insert("type", enumValueName(variantTypeToBasicType(paramType.type()))); - variantMap.insert("index", paramType.index()); - - // Optional values - if (paramType.defaultValue().isValid()) - variantMap.insert("defaultValue", paramType.defaultValue()); - - if (paramType.minValue().isValid()) - variantMap.insert("minValue", paramType.minValue()); - - if (paramType.maxValue().isValid()) - variantMap.insert("maxValue", paramType.maxValue()); - - if (!paramType.allowedValues().isEmpty()) - variantMap.insert("allowedValues", paramType.allowedValues()); - - if (paramType.inputType() != Types::InputTypeNone) - variantMap.insert("inputType", enumValueName(paramType.inputType())); - - if (paramType.unit() != Types::UnitNone) - variantMap.insert("unit", enumValueName(paramType.unit())); - - if (paramType.readOnly()) - variantMap.insert("readOnly", paramType.readOnly()); - - return variantMap; + ParamType translatedParamType = paramType; + translatedParamType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); + return pack(translatedParamType); } -QVariantMap DeviceHandler::packPlugin(DevicePlugin *plugin, const QLocale &locale) -{ - QVariantMap pluginMap; - pluginMap.insert("id", plugin->pluginId().toString()); - pluginMap.insert("name", plugin->pluginName()); - pluginMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale)); - - QVariantList params; - foreach (const ParamType ¶m, plugin->configurationDescription()) - params.append(packParamType(param, plugin->pluginId(), locale)); - - pluginMap.insert("paramTypes", params); - return pluginMap; -} - -QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) +QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const { QVariantMap variant; variant.insert("id", eventType.id().toString()); @@ -1057,23 +923,7 @@ QVariantMap DeviceHandler::packEventType(const EventType &eventType, const Plugi return variant; } -QVariantMap DeviceHandler::packVendor(const Vendor &vendor, const QLocale &locale) -{ - DevicePlugin *plugin = nullptr; - foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) { - if (p->supportedVendors().contains(vendor)) { - plugin = p; - } - } - QVariantMap variantMap; - variantMap.insert("id", vendor.id().toString()); - variantMap.insert("name", vendor.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale)); - return variantMap; - -} - -QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) +QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const { QVariantMap variantMap; variantMap.insert("id", actionType.id().toString()); @@ -1088,7 +938,7 @@ QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const Pl return variantMap; } -QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods) +QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods) const { QVariantList ret; if (createMethods.testFlag(DeviceClass::CreateMethodUser)) @@ -1103,96 +953,6 @@ QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createM return ret; } -QVariantMap DeviceHandler::packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) -{ - QVariantMap variant; - variant.insert("id", deviceClass.id().toString()); - variant.insert("name", deviceClass.name()); - variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), deviceClass.displayName(), locale)); - variant.insert("vendorId", deviceClass.vendorId().toString()); - variant.insert("pluginId", deviceClass.pluginId().toString()); - variant.insert("interfaces", deviceClass.interfaces()); - variant.insert("browsable", deviceClass.browsable()); - - QVariantList stateTypes; - foreach (const StateType &stateType, deviceClass.stateTypes()) - stateTypes.append(packStateType(stateType, deviceClass.pluginId(), locale)); - - QVariantList eventTypes; - foreach (const EventType &eventType, deviceClass.eventTypes()) - eventTypes.append(packEventType(eventType, deviceClass.pluginId(), locale)); - - QVariantList actionTypes; - foreach (const ActionType &actionType, deviceClass.actionTypes()) - actionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); - - QVariantList browserItemActionTypes; - foreach (const ActionType &actionType, deviceClass.browserItemActionTypes()) - browserItemActionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); - - QVariantList paramTypes; - foreach (const ParamType ¶mType, deviceClass.paramTypes()) - paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); - - QVariantList settingsTypes; - foreach (const ParamType &settingsType, deviceClass.settingsTypes()) - settingsTypes.append(packParamType(settingsType, deviceClass.pluginId(), locale)); - - QVariantList discoveryParamTypes; - foreach (const ParamType ¶mType, deviceClass.discoveryParamTypes()) - discoveryParamTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); - - variant.insert("paramTypes", paramTypes); - variant.insert("settingsTypes", settingsTypes); - variant.insert("discoveryParamTypes", discoveryParamTypes); - variant.insert("stateTypes", stateTypes); - variant.insert("eventTypes", eventTypes); - variant.insert("actionTypes", actionTypes); - variant.insert("browserItemActionTypes", browserItemActionTypes); - variant.insert("createMethods", packCreateMethods(deviceClass.createMethods())); - variant.insert("setupMethod", enumValueName(deviceClass.setupMethod())); - return variant; -} - -QVariantMap DeviceHandler::packDeviceDescriptor(const DeviceDescriptor &descriptor) -{ - QVariantMap variant; - variant.insert("id", descriptor.id().toString()); - variant.insert("deviceId", descriptor.deviceId().toString()); - variant.insert("title", descriptor.title()); - variant.insert("description", descriptor.description()); - QVariantList params; - foreach (const Param ¶m, descriptor.params()) { - params.append(packParam(param)); - } - variant.insert("deviceParams", params); - return variant; -} - -QVariantMap DeviceHandler::packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) -{ - QVariantMap variantMap; - variantMap.insert("id", stateType.id().toString()); - variantMap.insert("name", stateType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, stateType.displayName(), locale)); - variantMap.insert("index", stateType.index()); - variantMap.insert("type", enumValueName(variantTypeToBasicType(stateType.type()))); - variantMap.insert("defaultValue", stateType.defaultValue()); - - if (stateType.maxValue().isValid()) - variantMap.insert("maxValue", stateType.maxValue()); - - if (stateType.minValue().isValid()) - variantMap.insert("minValue", stateType.minValue()); - - if (!stateType.possibleValues().isEmpty()) - variantMap.insert("possibleValues", stateType.possibleValues()); - - if(stateType.unit() != Types::UnitNone) - variantMap.insert("unit", enumValueName(stateType.unit())); - - return variantMap; -} void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config) { diff --git a/libnymea-core/jsonrpc/devicehandler.h b/libnymea-core/jsonrpc/devicehandler.h index b96d37aa..07dbb6c4 100644 --- a/libnymea-core/jsonrpc/devicehandler.h +++ b/libnymea-core/jsonrpc/devicehandler.h @@ -60,15 +60,14 @@ public: Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap ¶ms) const; - static QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale); - static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale); - static QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale); - static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods); - static QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale); - static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor); + QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) const; +// QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale) const; + QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const; +// QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) const; + QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const; + QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods) const; +// QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) const; + QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor) const; static QVariantMap packParam(const Param ¶m); static QVariantList packParams(const ParamList ¶mList); diff --git a/libnymea-core/jsonrpc/eventhandler.cpp b/libnymea-core/jsonrpc/eventhandler.cpp index f48f140b..b33254f4 100644 --- a/libnymea-core/jsonrpc/eventhandler.cpp +++ b/libnymea-core/jsonrpc/eventhandler.cpp @@ -48,12 +48,12 @@ namespace nymeaserver { EventHandler::EventHandler(QObject *parent) : JsonHandler(parent) { + registerEnum(); + registerEnum(); // Objects - QVariantMap event; - event.insert("eventTypeId", enumValueName(Uuid)); - event.insert("deviceId", enumValueName(Uuid)); - event.insert("o:params", QVariantList() << objectRef("Param")); - registerObject("Event", event); + registerObject(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -80,30 +80,23 @@ QString EventHandler::name() const void EventHandler::eventTriggered(const Event &event) { QVariantMap params; - - QVariantMap variant; - variant.insert("eventTypeId", event.eventTypeId().toString()); - variant.insert("deviceId", event.deviceId().toString()); - QVariantList eventParams; - foreach (const Param ¶m, event.params()) { - eventParams.append(DeviceHandler::packParam(param)); - } - variant.insert("params", eventParams); - - params.insert("event", variant); + params.insert("event", pack(event)); emit EventTriggered(params); } JsonReply* EventHandler::GetEventType(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); qCDebug(dcJsonRpc) << "asked for event type" << params; EventTypeId eventTypeId(params.value("eventTypeId").toString()); foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const EventType &eventType, deviceClass.eventTypes()) { if (eventType.id() == eventTypeId) { + EventType translatedEventType = eventType; + translatedEventType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), eventType.displayName(), locale)); QVariantMap data; data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); - data.insert("eventType", DeviceHandler::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); + data.insert("eventType", pack(translatedEventType)); return createReply(data); } } diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp index 1f6c8bb4..5a4aaab0 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp @@ -80,12 +80,13 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration registerEnum(); // Objects - QVariantMap tokenInfo; - tokenInfo.insert("id", enumValueName(Uuid)); - tokenInfo.insert("userName", enumValueName(String)); - tokenInfo.insert("deviceName", enumValueName(String)); - tokenInfo.insert("creationTime", enumValueName(Uint)); - registerObject("TokenInfo", tokenInfo); +// QVariantMap tokenInfo; +// tokenInfo.insert("id", enumValueName(Uuid)); +// tokenInfo.insert("userName", enumValueName(String)); +// tokenInfo.insert("deviceName", enumValueName(String)); +// tokenInfo.insert("creationTime", enumValueName(Uint)); +// registerObject("TokenInfo", tokenInfo); + registerObject(); // Methods QString description; QVariantMap returns; QVariantMap params; @@ -355,14 +356,10 @@ JsonReply *JsonRPCServerImplementation::Tokens(const QVariantMap ¶ms) const QByteArray token = property("token").toByteArray(); QString username = NymeaCore::instance()->userManager()->userForToken(token); - if (username.isEmpty()) { - // There *really* should be a user for the token in the DB - Q_ASSERT(false); - } QList tokens = NymeaCore::instance()->userManager()->tokens(username); QVariantList retList; foreach (const TokenInfo &tokenInfo, tokens) { - retList << packTokenInfo(tokenInfo); + retList << pack(tokenInfo); } QVariantMap retMap; retMap.insert("tokenInfoList", retList); @@ -682,16 +679,6 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac } } -QVariantMap JsonRPCServerImplementation::packTokenInfo(const TokenInfo &tokenInfo) -{ - QVariantMap ret; - ret.insert("id", tokenInfo.id().toString()); - ret.insert("userName", tokenInfo.username()); - ret.insert("deviceName", tokenInfo.deviceName()); - ret.insert("creationTime", tokenInfo.creationTime().toTime_t()); - return ret; -} - void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms) { JsonHandler *handler = qobject_cast(sender()); @@ -793,39 +780,57 @@ void JsonRPCServerImplementation::onPushButtonAuthFinished(int transactionId, bo bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler) { // Sanity checks on API: - // * Make sure all $ref: entries are valid. A Handler can reference Types from previously loaded handlers or own ones. - // * A handler must not register a type name that is already registered by a previously loaded handler. - QVariantMap types = m_api.value("types").toMap(); + // * Make sure all $ref: entries are valid. + // * A handler must not register a type name that is already registered by a previously loaded handler with different content. QVariantMap methods = m_api.value("methods").toMap(); QVariantMap notifications = m_api.value("notifications").toMap(); + QVariantMap apiIncludingThis = m_api; // Verify enums name clash + QVariantMap enums = m_api.value("enums").toMap(); foreach (const QString &enumName, handler->jsonEnums().keys()) { QVariantList list = handler->jsonEnums().value(enumName).toList(); - if (types.contains(enumName)) { + if (enums.contains(enumName) && enums.value(enumName) != list) { qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name(); return false; } - types.insert(enumName, list); + enums.insert(enumName, list); } + apiIncludingThis["enums"] = enums; + + QVariantMap flags = m_api.value("flags").toMap(); + foreach (const QString &flagName, handler->jsonFlags().keys()) { + QVariant flagDescription = handler->jsonFlags().value(flagName); + if (enums.contains(flagName)) { + qCWarning(dcJsonRpc()) << "Enum with name" << flagName << "is already registered. Not registering handler" << handler->name(); + return false; + } + if (flags.contains(flagName) && flags.value(flagName) != handler->jsonFlags().value(flagName)) { + qCWarning(dcJsonRpc()) << "Flags with name" << flagName << "is already registered. Not registering handler" << handler->name(); + return false; + } + flags.insert(flagName, flagDescription); + } + apiIncludingThis["flags"] = flags; // Verify objects - QVariantMap typesIncludingThis = types; + QVariantMap existingTypes = m_api.value("types").toMap(); + QVariantMap typesIncludingThis = existingTypes; typesIncludingThis.unite(handler->jsonObjects()); + apiIncludingThis["types"] = typesIncludingThis; foreach (const QString &objectName, handler->jsonObjects().keys()) { QVariantMap object = handler->jsonObjects().value(objectName).toMap(); // Check for name clashes - if (types.contains(objectName)) { + if (existingTypes.contains(objectName) && existingTypes.value(objectName) != handler->jsonObjects().value(objectName)) { qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name(); return false; } // Check for invalid $ref: entries - if (!JsonValidator::checkRefs(object, typesIncludingThis)) { + if (!JsonValidator::checkRefs(object, apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name(); return false; } } - types = typesIncludingThis; // Verify methods QVariantMap newMethods; @@ -835,35 +840,35 @@ bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler) qCWarning(dcJsonRpc()).nospace().noquote() << "Invalid method \"" << methodName << "\". Method \"JsonReply* " + methodName + "(QVariantMap)\" does not exist. Not registering handler " << handler->name(); return false; } - if (!JsonValidator::checkRefs(method.value("params").toMap(), types)) { + if (!JsonValidator::checkRefs(method.value("params").toMap(), apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of method " << methodName << ". Not registering handler " << handler->name(); return false; } - if (!JsonValidator::checkRefs(method.value("returns").toMap(), types)) { + if (!JsonValidator::checkRefs(method.value("returns").toMap(), apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in return value of method " << methodName << ". Not registering handler " << handler->name(); return false; } newMethods.insert(handler->name() + '.' + methodName, method); } methods.unite(newMethods); + apiIncludingThis["methods"] = methods; // Verify notifications QVariantMap newNotifications; foreach (const QString ¬ificationName, handler->jsonNotifications().keys()) { QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap(); - if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) { + if (!JsonValidator::checkRefs(notification.value("params").toMap(), apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name(); return false; } newNotifications.insert(handler->name() + '.' + notificationName, notification); } notifications.unite(newNotifications); + apiIncludingThis["notifications"] = notifications; // Checks completed. Store new API qCDebug(dcJsonRpc()) << "Registering JSON RPC handler:" << handler->name(); - m_api["types"] = types; - m_api["methods"] = methods; - m_api["notifications"] = notifications; + m_api = apiIncludingThis; m_handlers.insert(handler->name(), handler); for (int i = 0; i < handler->metaObject()->methodCount(); ++i) { diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h index 4f5741bc..7d9f2598 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h @@ -84,9 +84,6 @@ private: void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data); - - static QVariantMap packTokenInfo(const TokenInfo &tokenInfo); - private slots: void setup(); diff --git a/libnymea-core/jsonrpc/jsonvalidator.cpp b/libnymea-core/jsonrpc/jsonvalidator.cpp index 56cb1c61..7b9e3dbc 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.cpp +++ b/libnymea-core/jsonrpc/jsonvalidator.cpp @@ -9,18 +9,23 @@ namespace nymeaserver { -bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types) +bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &api) { + QVariantMap enums = api.value("enums").toMap(); + QVariantMap flags = api.value("flags").toMap(); + QVariantMap types = api.value("types").toMap(); +// qWarning() << "checkrefs enums" << enums.keys(); foreach (const QString &key, map.keys()) { +// qWarning() << "checking prop" << key; if (map.value(key).toString().startsWith("$ref:")) { QString refName = map.value(key).toString().remove("$ref:"); - if (!types.contains(refName)) { + if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) { qCWarning(dcJsonRpc()) << "Invalid reference to" << refName; return false; } } if (map.value(key).type() == QVariant::Map) { - bool ret = checkRefs(map.value(key).toMap(), types); + bool ret = checkRefs(map.value(key).toMap(), api); if (!ret) { return false; } @@ -29,13 +34,13 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types) foreach (const QVariant &entry, map.value(key).toList()) { if (entry.toString().startsWith("$ref:")) { QString refName = entry.toString().remove("$ref:"); - if (!types.contains(refName)) { + if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) { qCWarning(dcJsonRpc()) << "Invalid reference to" << refName; return false; } } if (entry.type() == QVariant::Map) { - bool ret = checkRefs(map.value(key).toMap(), types); + bool ret = checkRefs(map.value(key).toMap(), api); if (!ret) { return false; } @@ -50,7 +55,7 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types) JsonValidator::Result JsonValidator::validateParams(const QVariantMap ¶ms, const QString &method, const QVariantMap &api) { QVariantMap paramDefinition = api.value("methods").toMap().value(method).toMap().value("params").toMap(); - m_result = validateMap(params, paramDefinition, api.value("types").toMap()); + m_result = validateMap(params, paramDefinition, api); m_result.setWhere(method + ", param " + m_result.where()); return m_result; } @@ -58,7 +63,7 @@ JsonValidator::Result JsonValidator::validateParams(const QVariantMap ¶ms, c JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api) { QVariantMap returnsDefinition = api.value("methods").toMap().value(method).toMap().value("returns").toMap(); - m_result = validateMap(returns, returnsDefinition, api.value("types").toMap()); + m_result = validateMap(returns, returnsDefinition, api); m_result.setWhere(method + ", returns " + m_result.where()); return m_result; } @@ -66,7 +71,7 @@ JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, JsonValidator::Result JsonValidator::validateNotificationParams(const QVariantMap ¶ms, const QString ¬ification, const QVariantMap &api) { QVariantMap paramDefinition = api.value("notifications").toMap().value(notification).toMap().value("params").toMap(); - m_result = validateMap(params, paramDefinition, api.value("types").toMap()); + m_result = validateMap(params, paramDefinition, api); m_result.setWhere(notification + ", param " + m_result.where()); return m_result; } @@ -76,7 +81,7 @@ JsonValidator::Result JsonValidator::result() const return m_result; } -JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types) +JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api) { // Make sure all required values are available foreach (const QString &key, definition.keys()) { @@ -102,7 +107,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q // Validate content QVariant value = map.value(key); - Result result = validateEntry(value, expectedValue, types); + Result result = validateEntry(value, expectedValue, api); if (!result.success()) { result.setWhere(key + '.' + result.where()); result.setErrorString(result.errorString()); @@ -114,8 +119,11 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q return Result(true); } -JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types) +JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api) { +// qWarning() << "validating" << definition; +// qWarning() << "** enums:" << api.value("enums").toMap().keys(); +// qWarning() << "** types:" << api.value("types").toMap().keys(); if (definition.type() == QVariant::String) { QString expectedTypeName = definition.toString(); @@ -123,20 +131,39 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QString refName = expectedTypeName; refName.remove("$ref:"); - QVariant refDefinition = types.value(refName); // Refs might be enums - if (refDefinition.type() == QVariant::List) { - if (value.type() != QVariant::String) { - return Result(false, "Expected enum " + refName + " but got " + value.toString()); - } + QVariantMap enums = api.value("enums").toMap(); + if (enums.contains(refName)) { + QVariant refDefinition = enums.value(refName); + QVariantList enumList = refDefinition.toList(); if (!enumList.contains(value.toString())) { - return Result(false, "Expected enum " + refName + " but got " + value.toString()); + return Result(false, "Expected enum " + refName + " but got " + value.toJsonDocument().toJson()); + } + return Result(true); + } + // Or flags + QVariantMap flags = api.value("flags").toMap(); + if (flags.contains(refName)) { + QVariant refDefinition = flags.value(refName); + qWarning() << "Flag:" << value.type(); + if (value.type() != QVariant::StringList) { + return Result(false, "Expected flags " + refName + " but got " + value.toString()); + } + QString flagEnum = refDefinition.toList().first().toString(); + qWarning() << "Flag enum:" << flagEnum; + foreach (const QVariant &flagsEntry, value.toList()) { + Result result = validateEntry(flagsEntry, flagEnum, api); + if (!result.success()) { + return result; + } } return Result(true); } - return validateEntry(value, refDefinition, types); + QVariantMap types = api.value("types").toMap(); + QVariant refDefinition = types.value(refName); + return validateEntry(value, refDefinition, api); } JsonHandler::BasicType expectedBasicType = JsonHandler::enumNameToValue(expectedTypeName); @@ -199,7 +226,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const if (value.type() != QVariant::Map) { return Result(false, "Invalud value. Expected a map bug received: " + value.toString()); } - return validateMap(value.toMap(), definition.toMap(), types); + return validateMap(value.toMap(), definition.toMap(), api); } if (definition.type() == QVariant::List) { @@ -209,7 +236,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const return Result(false, "Expected list of " + entryDefinition.toString() + " but got value of type " + value.typeName() + "\n" + QJsonDocument::fromVariant(value).toJson()); } foreach (const QVariant &entry, value.toList()) { - Result result = validateEntry(entry, entryDefinition, types); + Result result = validateEntry(entry, entryDefinition, api); if (!result.success()) { return result; } diff --git a/libnymea-core/jsonrpc/jsonvalidator.h b/libnymea-core/jsonrpc/jsonvalidator.h index 731da915..8d2d1130 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.h +++ b/libnymea-core/jsonrpc/jsonvalidator.h @@ -30,7 +30,7 @@ public: JsonValidator() {} - static bool checkRefs(const QVariantMap &map, const QVariantMap &types); + static bool checkRefs(const QVariantMap &map, const QVariantMap &api); Result validateParams(const QVariantMap ¶ms, const QString &method, const QVariantMap &api); Result validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api); @@ -38,8 +38,8 @@ public: Result result() const; private: - Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types); - Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types); + Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api); + Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api); Result m_result; }; diff --git a/libnymea-core/jsonrpc/logginghandler.cpp b/libnymea-core/jsonrpc/logginghandler.cpp index f3e3e0c0..5af2e1c7 100644 --- a/libnymea-core/jsonrpc/logginghandler.cpp +++ b/libnymea-core/jsonrpc/logginghandler.cpp @@ -62,18 +62,7 @@ LoggingHandler::LoggingHandler(QObject *parent) : registerEnum(); // Objects - QVariantMap logEntry; - logEntry.insert("timestamp", enumValueName(Int)); - logEntry.insert("loggingLevel", enumRef()); - logEntry.insert("source", enumRef()); - logEntry.insert("o:typeId", enumValueName(Uuid)); - logEntry.insert("o:deviceId", enumValueName(Uuid)); - logEntry.insert("o:itemId", enumValueName(String)); - logEntry.insert("o:value", enumValueName(String)); - logEntry.insert("o:active", enumValueName(Bool)); - logEntry.insert("o:eventType", enumRef()); - logEntry.insert("o:errorCode", enumValueName(String)); - registerObject("LogEntry", logEntry); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -198,8 +187,8 @@ QVariantMap LoggingHandler::packLogEntry(const LogEntry &logEntry) case Logging::LoggingSourceActions: case Logging::LoggingSourceEvents: case Logging::LoggingSourceStates: - logEntryMap.insert("typeId", logEntry.typeId().toString()); - logEntryMap.insert("deviceId", logEntry.deviceId().toString()); + logEntryMap.insert("typeId", logEntry.typeId()); + logEntryMap.insert("deviceId", logEntry.deviceId()); logEntryMap.insert("value", LogValueTool::convertVariantToString(logEntry.value())); break; case Logging::LoggingSourceSystem: diff --git a/libnymea-core/jsonrpc/ruleshandler.cpp b/libnymea-core/jsonrpc/ruleshandler.cpp index 0ddd8d1c..457f4ff1 100644 --- a/libnymea-core/jsonrpc/ruleshandler.cpp +++ b/libnymea-core/jsonrpc/ruleshandler.cpp @@ -116,12 +116,7 @@ RulesHandler::RulesHandler(QObject *parent) : repeatingOption.insert("o:monthDays", QVariantList() << enumValueName(Int)); registerObject("RepeatingOption", repeatingOption); - QVariantMap calendarItem; - calendarItem.insert("o:datetime", enumValueName(Uint)); - calendarItem.insert("o:startTime", enumValueName(Time)); - calendarItem.insert("duration", enumValueName(Uint)); - calendarItem.insert("o:repeating", objectRef("RepeatingOption")); - registerObject("CalendarItem", calendarItem); + registerObject(); QVariantMap timeEventItem; timeEventItem.insert("o:datetime", enumValueName(Uint)); diff --git a/libnymea-core/jsonrpc/statehandler.cpp b/libnymea-core/jsonrpc/statehandler.cpp index 2ede3ded..d260d322 100644 --- a/libnymea-core/jsonrpc/statehandler.cpp +++ b/libnymea-core/jsonrpc/statehandler.cpp @@ -73,7 +73,8 @@ JsonReply* StateHandler::GetStateType(const QVariantMap ¶ms) const if (stateType.id() == stateTypeId) { QVariantMap data; data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); - data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); + // FIXME TODO!!! +// data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); return createReply(data); } } diff --git a/libnymea-core/logging/logentry.h b/libnymea-core/logging/logentry.h index 5cd8fb84..abb973b0 100644 --- a/libnymea-core/logging/logentry.h +++ b/libnymea-core/logging/logentry.h @@ -34,6 +34,16 @@ namespace nymeaserver { class LogEntry { Q_GADGET + Q_PROPERTY(QDateTime timestamp READ timestamp) + Q_PROPERTY(Logging::LoggingLevel loggingLevel READ level) + Q_PROPERTY(Logging::LoggingSource source READ source) + Q_PROPERTY(QUuid typeId READ typeId USER true) + Q_PROPERTY(QUuid deviceId READ deviceId USER true) +// Q_PROPERTY(QString itemId READ itemId USER true) + Q_PROPERTY(QVariant value READ value USER true) + Q_PROPERTY(bool active READ active USER true) + Q_PROPERTY(Logging::LoggingEventType eventType READ eventType USER true) + Q_PROPERTY(QString errorCode READ errorCode USER true) public: LogEntry(QDateTime timestamp, Logging::LoggingLevel level, Logging::LoggingSource source, int errorCode = 0); diff --git a/libnymea-core/nymeaconfiguration.h b/libnymea-core/nymeaconfiguration.h index e6ada65b..aa24409b 100644 --- a/libnymea-core/nymeaconfiguration.h +++ b/libnymea-core/nymeaconfiguration.h @@ -30,9 +30,16 @@ namespace nymeaserver { class ServerConfiguration { + Q_GADGET + Q_PROPERTY(QString id MEMBER id) + Q_PROPERTY(QString address READ addressString) + Q_PROPERTY(uint port MEMBER port) + Q_PROPERTY(bool sslEnabled MEMBER sslEnabled) + Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled) public: QString id; QHostAddress address; + QString addressString() { return address.toString(); } uint port = 0; bool sslEnabled = true; bool authenticationEnabled = true; @@ -50,6 +57,8 @@ QDebug operator <<(QDebug debug, const ServerConfiguration &configuration); class WebServerConfiguration: public ServerConfiguration { + Q_GADGET + Q_PROPERTY(QString publicFolder MEMBER publicFolder) public: QString publicFolder; bool restServerEnabled = false; @@ -57,6 +66,13 @@ public: class MqttPolicy { + Q_GADGET + Q_PROPERTY(QString clientId MEMBER clientId) + Q_PROPERTY(QString username MEMBER username) + Q_PROPERTY(QString password MEMBER password) + Q_PROPERTY(QStringList allowedPublishTopicFilters MEMBER allowedPublishTopicFilters) + Q_PROPERTY(QStringList allowedSubscribeTopicFilters MEMBER allowedSubscribeTopicFilters) + public: QString clientId; QString username; diff --git a/libnymea-core/usermanager/tokeninfo.h b/libnymea-core/usermanager/tokeninfo.h index d65cf544..ed24200d 100644 --- a/libnymea-core/usermanager/tokeninfo.h +++ b/libnymea-core/usermanager/tokeninfo.h @@ -23,11 +23,18 @@ #include #include +#include namespace nymeaserver { class TokenInfo { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString username READ username) + Q_PROPERTY(QDateTime createionTime READ creationTime) + Q_PROPERTY(QString deviveName READ deviceName) + public: TokenInfo(const QUuid &id, const QString &username, const QDateTime &creationTime, const QString &deviceName); diff --git a/libnymea/devices/device.h b/libnymea/devices/device.h index acc937ab..7a012b01 100644 --- a/libnymea/devices/device.h +++ b/libnymea/devices/device.h @@ -41,9 +41,14 @@ class DevicePlugin; class LIBNYMEA_EXPORT Device: public QObject { Q_OBJECT - - friend class DeviceManager; - friend class DeviceManagerImplementation; + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QUuid deviceClassId READ deviceClassId) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(ParamList params READ params WRITE setParams) + Q_PROPERTY(ParamList settings READ settings WRITE setSettings) + Q_PROPERTY(States states READ states WRITE setStates) + Q_PROPERTY(bool setupComplete READ setupComplete WRITE setSetupComplete) + Q_PROPERTY(QUuid parentId READ parentId WRITE setParentId USER true) public: enum DeviceError { @@ -122,6 +127,8 @@ signals: void nameChanged(); private: + friend class DeviceManager; + friend class DeviceManagerImplementation; Device(DevicePlugin *plugin, const DeviceClass &deviceClass, const DeviceId &id, QObject *parent = nullptr); Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *parent = nullptr); diff --git a/libnymea/devices/devicedescriptor.h b/libnymea/devices/devicedescriptor.h index 6952cc65..15e84fc7 100644 --- a/libnymea/devices/devicedescriptor.h +++ b/libnymea/devices/devicedescriptor.h @@ -32,6 +32,13 @@ class LIBNYMEA_EXPORT DeviceDescriptor { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QUuid deviceId READ deviceId USER true) + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QString description READ description) + Q_PROPERTY(ParamList deviceParams READ params) + public: DeviceDescriptor(); DeviceDescriptor(const DeviceClassId &deviceClassId, const QString &title = QString(), const QString &description = QString(), const DeviceId &parentDeviceId = DeviceId()); diff --git a/libnymea/devices/devicemanager.h b/libnymea/devices/devicemanager.h index 2d55f80c..66bfd87a 100644 --- a/libnymea/devices/devicemanager.h +++ b/libnymea/devices/devicemanager.h @@ -125,7 +125,9 @@ public: virtual BrowserItemActionInfo* executeBrowserItemAction(const BrowserItemAction &browserItemAction) = 0; virtual QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0; - + virtual ParamType translateParamType(const PluginId &pluginId, const ParamType ¶mType, const QLocale &locale) = 0; + virtual DeviceClass translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) = 0; + virtual Vendor translateVendor(const Vendor &vendor, const QLocale &locale) = 0; signals: void pluginConfigChanged(const PluginId &id, const ParamList &config); void eventTriggered(const Event &event); diff --git a/libnymea/devices/deviceplugin.h b/libnymea/devices/deviceplugin.h index 034f06e6..0b6726c1 100644 --- a/libnymea/devices/deviceplugin.h +++ b/libnymea/devices/deviceplugin.h @@ -62,8 +62,10 @@ class LIBNYMEA_EXPORT DevicePlugin: public QObject { Q_OBJECT - friend class DeviceManager; - friend class DeviceManagerImplementation; + Q_PROPERTY(QUuid id READ pluginId) + Q_PROPERTY(QString name READ pluginName) + Q_PROPERTY(QString displayName READ pluginDisplayName) + Q_PROPERTY(ParamTypes paramTypes READ configurationDescription) public: DevicePlugin(QObject *parent = nullptr); @@ -115,6 +117,10 @@ protected: QSettings *pluginStorage() const; private: + friend class DeviceManager; + friend class DeviceManagerImplementation; + + void setMetaData(const PluginMetadata &metaData); void initPlugin(const PluginMetadata &metadata, DeviceManager *deviceManager, HardwareManager *hardwareManager); diff --git a/libnymea/devices/pluginmetadata.cpp b/libnymea/devices/pluginmetadata.cpp index e5830391..75aded84 100644 --- a/libnymea/devices/pluginmetadata.cpp +++ b/libnymea/devices/pluginmetadata.cpp @@ -103,7 +103,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) return; } - m_pluginId = jsonObject.value("id").toString(); + m_pluginId = PluginId(jsonObject.value("id").toString()); m_pluginName = jsonObject.value("name").toString(); m_pluginDisplayName = jsonObject.value("displayName").toString(); @@ -192,7 +192,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) continue; } - DeviceClassId deviceClassId = deviceClassObject.value("id").toString(); + DeviceClassId deviceClassId = DeviceClassId(deviceClassObject.value("id").toString()); QString deviceClassName = deviceClassObject.value("name").toString(); // Check if there are any unknown fields @@ -304,7 +304,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) continue; } - StateTypeId stateTypeId = st.value("id").toString(); + StateTypeId stateTypeId = StateTypeId(st.value("id").toString()); QString stateTypeName = st.value("name").toString(); // Check if there are any unknown fields diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 3b5e728e..4f5170e6 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -6,6 +6,7 @@ JsonHandler::JsonHandler(QObject *parent) : QObject(parent) { + registerEnum(); } QVariantMap JsonHandler::jsonEnums() const @@ -13,6 +14,11 @@ QVariantMap JsonHandler::jsonEnums() const return m_enums; } +QVariantMap JsonHandler::jsonFlags() const +{ + return m_flags; +} + QVariantMap JsonHandler::jsonObjects() const { return m_objects; @@ -62,6 +68,8 @@ JsonHandler::BasicType JsonHandler::variantTypeToBasicType(QVariant::Type varian return Time; case QVariant::Map: return Object; + case QVariant::DateTime: + return Uint; // DateTime is represented as time_t default: return Variant; } @@ -132,3 +140,73 @@ JsonReply *JsonHandler::createAsyncReply(const QString &method) const return JsonReply::createAsyncReply(const_cast(this), method); } +QVariantMap JsonHandler::pack(const QMetaObject &metaObject, const void *value) const +{ + QVariantMap ret; +// qWarning() << "+ Packing" << metaObject.className(); + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + if (metaProperty.name() == QStringLiteral("objectName")) { + continue; // Skip QObject's objectName property + } + + QVariant val = metaProperty.readOnGadget(value); +// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName(); +// qWarning() << "|-- All list types:" << m_listMetaObjects.keys(); + if (metaProperty.type() == QVariant::UserType) { + if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { + QMetaEnum metaEnum = QMetaEnum::fromType(); +// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt()); + ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); + } else if (m_listMetaObjects.contains(metaProperty.typeName())) { + QVariant listObject = metaProperty.readOnGadget(value); + QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName()); + QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count")); + int listCount = countProperty.readOnGadget(listObject.constData()).toInt(); +// qWarning() << "Packing list type" << listObject << "count is" << listCount; + QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)")); +// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)"); + + QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className())); + QVariantList list; + for (int i = 0; i < listCount; i++) { + QVariant entry; + metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); +// qWarning() << "|---Feckin hell" << entry; + + list.append(pack(entryMetaObject, entry.data())); + } + + ret.insert(metaProperty.name(), list); + + + } else { + Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); + } + } else if (metaProperty.isFlagType()) { + QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last()); +// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name())); + int flagValue = metaProperty.readOnGadget(value).toInt(); +// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type(); + QStringList flags; + for (int i = 0; i < metaFlag.keyCount(); i++) { +// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i); + if ((metaFlag.value(i) & flagValue) > 0) { + flags.append(metaFlag.key(i)); + } + } + ret.insert(metaProperty.name(), flags); + } else if (metaProperty.isEnumType()) { + QString enumName = QString(metaProperty.typeName()).split("::").last(); + Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); + QMetaEnum metaEnum = m_metaEnums.value(enumName); +// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys(); + ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); + } else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { +// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value); + ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); + } + } + return ret; +} + diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index 09b509c5..87423f64 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "jsonreply.h" @@ -32,6 +34,7 @@ public: virtual QString name() const = 0; QVariantMap jsonEnums() const; + QVariantMap jsonFlags() const; QVariantMap jsonObjects() const; QVariantMap jsonMethods() const; QVariantMap jsonNotifications() const; @@ -46,8 +49,13 @@ public: static BasicType variantTypeToBasicType(QVariant::Type variantType); static QVariant::Type basicTypeToVariantType(BasicType basicType); + template QVariantMap pack(const T &value) const; + protected: - template void registerEnum(); + template void registerEnum(); + template void registerEnum(); + template void registerObject(); + template void registerObject(); void registerObject(const QString &name, const QVariantMap &object); void registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool deprecated = false); void registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool deprecated = false); @@ -55,13 +63,23 @@ protected: JsonReply *createReply(const QVariantMap &data) const; JsonReply *createAsyncReply(const QString &method) const; +private: + QVariantMap pack(const QMetaObject &metaObject, const void *gadget) const; private: QVariantMap m_enums; + QHash m_metaEnums; + QVariantMap m_flags; + QHash m_metaFlags; + QHash m_flagsEnums; QVariantMap m_objects; + QHash m_metaObjects; + QHash m_listMetaObjects; + QHash m_listEntryTypes; QVariantMap m_methods; QVariantMap m_notifications; }; +Q_DECLARE_METATYPE(QVariant::Type) template void JsonHandler::registerEnum() @@ -72,9 +90,83 @@ void JsonHandler::registerEnum() values << metaEnum.key(i); } m_enums.insert(metaEnum.name(), values); - + m_metaEnums.insert(metaEnum.name(), metaEnum); } +template +void JsonHandler::registerEnum() +{ + registerEnum(); + QMetaEnum metaEnum = QMetaEnum::fromType(); + QMetaEnum metaFlags = QMetaEnum::fromType(); + m_metaFlags.insert(metaFlags.name(), metaFlags); + m_flagsEnums.insert(metaFlags.name(), metaEnum.name()); + m_flags.insert(metaFlags.name(), QVariantList() << QString("$ref:%1").arg(metaEnum.name())); +} + +template +void JsonHandler::registerObject() +{ + qRegisterMetaType(); + QMetaObject metaObject = ObjectType::staticMetaObject; + QString className = QString(metaObject.className()).split("::").last(); + QVariantMap description; + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + QString name = metaProperty.name(); + if (name == "objectName") { + continue; // Skip QObject's objectName property + } + if (metaProperty.isUser()) { + name.prepend("o:"); + } + QVariant typeName; +// qWarning() << ".-.-.-.-.-" << metaProperty.name() << metaProperty.type() << metaProperty.typeName(); + if (metaProperty.type() == QVariant::UserType) { + if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { + typeName = QString("$ref:BasicType"); + } else if (QString(metaProperty.typeName()).startsWith("QList")) { + typeName = QVariantList() << "$ref:" + QString(metaProperty.typeName()).remove("QList<").remove(">"); + } else { + typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); + } + } else if (metaProperty.isEnumType()) { + typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); + } else if (metaProperty.isFlagType()) { + typeName = QVariantList() << "$ref:" + m_flagsEnums.value(metaProperty.name()); + } else if (metaProperty.type() == QVariant::List) { + typeName = QVariantList() << enumValueName(Variant); + } else { + typeName = enumValueName(variantTypeToBasicType(metaProperty.type())); + } + description.insert(name, typeName); + } + m_objects.insert(className, description); + m_metaObjects.insert(className, metaObject); +} + +template +void JsonHandler::registerObject() +{ + registerObject(); + QMetaObject metaObject = ObjectType::staticMetaObject; + QMetaObject listMetaObject = ListType::staticMetaObject; + m_objects.insert(listMetaObject.className(), QVariantList() << QVariant(QString("$ref:%1").arg(metaObject.className()))); + m_metaObjects.insert(listMetaObject.className(), listMetaObject); + m_listMetaObjects.insert(listMetaObject.className(), listMetaObject); + m_listEntryTypes.insert(listMetaObject.className(), metaObject.className()); + Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", "List type does not implement \"count\" property!"); + Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", "List type does not implement \"Q_INVOKABLE QVariant get(int index)\" method!"); +} + +//template +//void JsonHandler::registerList() +//{ +// QMetaObject metaObject = T::staticMetaObject; +// m_lists.insert(metaObject.className(), metaObject); +// m_objects.insert(metaObject.classInfo(), QVariantList() << ) +//} + template QString JsonHandler::enumRef() { @@ -96,4 +188,12 @@ T JsonHandler::enumNameToValue(const QString &name) return static_cast(metaEnum.keyToValue(name.toUtf8())); } +template +QVariantMap JsonHandler::pack(const T &value) const +{ + QMetaObject metaObject = T::staticMetaObject; + return pack(metaObject, static_cast(&value)); +} + + #endif // JSONHANDLER_H diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index b00b7833..0fc19205 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -26,8 +26,7 @@ HEADERS += \ devices/browseresult.h \ jsonrpc/jsonhandler.h \ jsonrpc/jsonreply.h \ - experiences/experienceplugin.h \ - jsonrpc/jsonrpcserver.h \ + jsonrpc/jsonrpcserver.h \ libnymea.h \ platform/package.h \ platform/repository.h \ @@ -109,8 +108,7 @@ SOURCES += \ devices/browseresult.cpp \ jsonrpc/jsonhandler.cpp \ jsonrpc/jsonreply.cpp \ - experiences/experienceplugin.cpp \ - jsonrpc/jsonrpcserver.cpp \ + jsonrpc/jsonrpcserver.cpp \ loggingcategories.cpp \ nymeasettings.cpp \ platform/package.cpp \ diff --git a/libnymea/time/calendaritem.cpp b/libnymea/time/calendaritem.cpp index b3a07e5d..edee90bb 100644 --- a/libnymea/time/calendaritem.cpp +++ b/libnymea/time/calendaritem.cpp @@ -19,8 +19,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! - \class nymeaserver::CalendarItem - \brief Describes a clendar item for a time based \l{nymeaserver::Rule}{Rule}. + \class CalendarItem + \brief Describes a clendar item. \ingroup rules \inmodule core @@ -33,8 +33,6 @@ #include -namespace nymeaserver { - /*! Construct a invalid \l{CalendarItem}. */ CalendarItem::CalendarItem(): m_duration(0) @@ -275,5 +273,4 @@ QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem) return dbg; } -} diff --git a/libnymea/time/calendaritem.h b/libnymea/time/calendaritem.h index c99798b4..56eb6341 100644 --- a/libnymea/time/calendaritem.h +++ b/libnymea/time/calendaritem.h @@ -25,10 +25,13 @@ #include "repeatingoption.h" -namespace nymeaserver { - class CalendarItem { + Q_GADGET + Q_PROPERTY(uint duration READ duration WRITE setDuration) + Q_PROPERTY(QDateTime datetime READ dateTime WRITE setDateTime USER true) + Q_PROPERTY(QTime startTime READ startTime WRITE setStartTime USER true) + Q_PROPERTY(RepeatingOption repeating READ repeatingOption WRITE setRepeatingOption USER true) public: CalendarItem(); @@ -64,6 +67,5 @@ private: }; QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem); -} #endif // CALENDARITEM_H diff --git a/libnymea/time/repeatingoption.cpp b/libnymea/time/repeatingoption.cpp index 3a25fd26..58807d9f 100644 --- a/libnymea/time/repeatingoption.cpp +++ b/libnymea/time/repeatingoption.cpp @@ -83,8 +83,6 @@ #include -namespace nymeaserver { - /*! Constructs an empty \l{RepeatingOption}. */ RepeatingOption::RepeatingOption() : m_mode(RepeatingModeNone) @@ -197,5 +195,3 @@ QDebug operator<<(QDebug dbg, const RepeatingOption &repeatingOption) dbg.nospace() << "RepeatingOption(Mode:" << repeatingOption.mode() << ", Monthdays:" << repeatingOption.monthDays() << "Weekdays:" << repeatingOption.weekDays() << ")"; return dbg; } - -} diff --git a/libnymea/time/repeatingoption.h b/libnymea/time/repeatingoption.h index 28055546..85390a11 100644 --- a/libnymea/time/repeatingoption.h +++ b/libnymea/time/repeatingoption.h @@ -26,8 +26,6 @@ class QDateTime; -namespace nymeaserver { - class RepeatingOption { Q_GADGET @@ -66,6 +64,5 @@ private: }; QDebug operator<<(QDebug dbg, const RepeatingOption &RepeatingOption); -} #endif // REPEATINGOPTION_H diff --git a/libnymea/time/timedescriptor.cpp b/libnymea/time/timedescriptor.cpp index eb00bd46..dda50d2a 100644 --- a/libnymea/time/timedescriptor.cpp +++ b/libnymea/time/timedescriptor.cpp @@ -36,8 +36,6 @@ #include -namespace nymeaserver { - /*! Constructs an invalid \l{TimeDescriptor}.*/ TimeDescriptor::TimeDescriptor() { @@ -119,5 +117,3 @@ QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor) } return dbg; } - -} diff --git a/libnymea/time/timedescriptor.h b/libnymea/time/timedescriptor.h index 94efcc7c..0da0c0a7 100644 --- a/libnymea/time/timedescriptor.h +++ b/libnymea/time/timedescriptor.h @@ -24,8 +24,6 @@ #include "timeeventitem.h" #include "calendaritem.h" -namespace nymeaserver { - class TimeDescriptor { public: @@ -54,6 +52,5 @@ private: QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor); -} #endif // TIMEDESCRIPTOR_H diff --git a/libnymea/time/timeeventitem.cpp b/libnymea/time/timeeventitem.cpp index b4fa53f8..408b79a8 100644 --- a/libnymea/time/timeeventitem.cpp +++ b/libnymea/time/timeeventitem.cpp @@ -33,8 +33,6 @@ #include -namespace nymeaserver { - /*! Constructs an invalid \l{TimeEventItem}. */ TimeEventItem::TimeEventItem() { @@ -141,4 +139,3 @@ QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem) return dbg; } -} diff --git a/libnymea/time/timeeventitem.h b/libnymea/time/timeeventitem.h index 60a2a82a..90b8819e 100644 --- a/libnymea/time/timeeventitem.h +++ b/libnymea/time/timeeventitem.h @@ -25,8 +25,6 @@ #include "repeatingoption.h" -namespace nymeaserver { - class TimeEventItem { public: @@ -56,6 +54,5 @@ private: QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem); -} #endif // TIMEEVENTITEM_H diff --git a/libnymea/types/action.cpp b/libnymea/types/action.cpp index a38597c1..95f9c589 100644 --- a/libnymea/types/action.cpp +++ b/libnymea/types/action.cpp @@ -73,12 +73,22 @@ ActionTypeId Action::actionTypeId() const return m_actionTypeId; } +void Action::setActionTypeId(const ActionTypeId &actionTypeId) +{ + m_actionTypeId = actionTypeId; +} + /*! Returns the deviceId this Action is associated with. */ DeviceId Action::deviceId() const { return m_deviceId; } +void Action::setDeviceId(const DeviceId &deviceId) +{ + m_deviceId = deviceId; +} + /*! Returns the parameters for this Action. */ ParamList Action::params() const { diff --git a/libnymea/types/action.h b/libnymea/types/action.h index 85e9c005..bfeda7fd 100644 --- a/libnymea/types/action.h +++ b/libnymea/types/action.h @@ -32,6 +32,11 @@ class LIBNYMEA_EXPORT Action { + Q_GADGET + Q_PROPERTY(QUuid actionTypeId READ actionTypeId WRITE setActionTypeId) + Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId) + Q_PROPERTY(ParamList params READ params WRITE setParams USER true) + public: explicit Action(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId()); Action(const Action &other); @@ -41,7 +46,9 @@ public: bool isValid() const; ActionTypeId actionTypeId() const; + void setActionTypeId(const ActionTypeId &actionTypeId); DeviceId deviceId() const; + void setDeviceId(const DeviceId &deviceId); ParamList params() const; void setParams(const ParamList ¶ms); diff --git a/libnymea/types/actiontype.cpp b/libnymea/types/actiontype.cpp index 959183bd..94e35701 100644 --- a/libnymea/types/actiontype.cpp +++ b/libnymea/types/actiontype.cpp @@ -123,6 +123,11 @@ ActionTypes::ActionTypes(const QList &other) } } +QVariant ActionTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + ActionType ActionTypes::findByName(const QString &name) { foreach (const ActionType &actionType, *this) { diff --git a/libnymea/types/actiontype.h b/libnymea/types/actiontype.h index d809ab4e..6b03e6b9 100644 --- a/libnymea/types/actiontype.h +++ b/libnymea/types/actiontype.h @@ -32,6 +32,13 @@ class LIBNYMEA_EXPORT ActionType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(int index READ index WRITE setIndex) + Q_PROPERTY(ParamTypes paramTypes READ paramTypes WRITE setParamTypes) + public: ActionType(const ActionTypeId &id = ActionTypeId()); @@ -59,16 +66,21 @@ private: int m_index; ParamTypes m_paramTypes; }; +Q_DECLARE_METATYPE(ActionType) QDebug operator<<(QDebug dbg, const ActionType &actionType); class ActionTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: ActionTypes() = default; ActionTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); ActionType findByName(const QString &name); ActionType findById(const ActionTypeId &id); }; +Q_DECLARE_METATYPE(ActionTypes) #endif // ACTIONTYPE_H diff --git a/libnymea/types/browseritem.h b/libnymea/types/browseritem.h index 466f725e..c32bcaea 100644 --- a/libnymea/types/browseritem.h +++ b/libnymea/types/browseritem.h @@ -33,6 +33,16 @@ class LIBNYMEA_EXPORT BrowserItem { Q_GADGET + Q_PROPERTY(QString id READ id) + Q_PROPERTY(QString displayName READ displayName) + Q_PROPERTY(QString description READ description) + Q_PROPERTY(BrowserIcon icon READ icon) + Q_PROPERTY(QString thumbnail READ thumbnail) + Q_PROPERTY(bool executable READ executable) + Q_PROPERTY(bool browsable READ browsable) + Q_PROPERTY(bool disabled READ disabled) + Q_PROPERTY(QList actionTypeIds READ actionTypeIds) + public: enum BrowserIcon { BrowserIconNone, diff --git a/libnymea/types/deviceclass.h b/libnymea/types/deviceclass.h index abf1644e..e03c494c 100644 --- a/libnymea/types/deviceclass.h +++ b/libnymea/types/deviceclass.h @@ -38,6 +38,22 @@ class LIBNYMEA_EXPORT DeviceClass { Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QUuid vendorId READ vendorId) + Q_PROPERTY(QUuid pluginId READ pluginId) + Q_PROPERTY(QString name READ name) + Q_PROPERTY(QString displayName READ displayName) + Q_PROPERTY(QStringList interfaces READ interfaces) + Q_PROPERTY(bool browsable READ browsable) + Q_PROPERTY(SetupMethod setupMethod READ setupMethod) + Q_PROPERTY(CreateMethods createMethods READ createMethods) + Q_PROPERTY(StateTypes stateTypes READ stateTypes) + Q_PROPERTY(EventTypes eventTypes READ eventTypes) + Q_PROPERTY(ActionTypes actionTypes READ actionTypes) + Q_PROPERTY(ActionTypes browserItemActionTypes READ browserItemActionTypes) + Q_PROPERTY(ParamTypes paramTypes READ paramTypes) + Q_PROPERTY(ParamTypes settingsTypes READ settingsTypes) + Q_PROPERTY(ParamTypes discoveryParamTypes READ discoveryParamTypes) public: enum CreateMethod { @@ -47,6 +63,7 @@ public: }; Q_ENUM(CreateMethod) Q_DECLARE_FLAGS(CreateMethods, CreateMethod) + Q_FLAG(CreateMethods) enum SetupMethod { SetupMethodJustAdd, diff --git a/libnymea/types/event.cpp b/libnymea/types/event.cpp index 9703c68d..82a50eb4 100644 --- a/libnymea/types/event.cpp +++ b/libnymea/types/event.cpp @@ -108,7 +108,7 @@ Param Event::param(const ParamTypeId ¶mTypeId) const return param; } } - return Param(QString()); + return Param(paramTypeId); } /*! Returns true if this event is autogenerated by a state change. */ diff --git a/libnymea/types/event.h b/libnymea/types/event.h index e88867ab..de2bd947 100644 --- a/libnymea/types/event.h +++ b/libnymea/types/event.h @@ -34,6 +34,10 @@ class LIBNYMEA_EXPORT Event { + Q_GADGET + Q_PROPERTY(QUuid eventTypeId READ eventTypeId) + Q_PROPERTY(QUuid deviceId READ deviceId) + Q_PROPERTY(ParamList params READ params) public: Event(); Event(const EventTypeId &eventTypeId, const DeviceId &deviceId, const ParamList ¶ms = ParamList(), bool isStateChangeEvent = false); diff --git a/libnymea/types/eventtype.cpp b/libnymea/types/eventtype.cpp index b7a10fa1..9b563736 100644 --- a/libnymea/types/eventtype.cpp +++ b/libnymea/types/eventtype.cpp @@ -33,6 +33,11 @@ #include "eventtype.h" +EventType::EventType() +{ + +} + /*! Constructs a EventType object with the given \a id. */ EventType::EventType(const EventTypeId &id): m_id(id), @@ -123,6 +128,11 @@ EventTypes::EventTypes(const QList &other) } } +QVariant EventTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + EventType EventTypes::findByName(const QString &name) { foreach (const EventType &eventType, *this) { diff --git a/libnymea/types/eventtype.h b/libnymea/types/eventtype.h index c50ec651..fbdb4628 100644 --- a/libnymea/types/eventtype.h +++ b/libnymea/types/eventtype.h @@ -32,7 +32,15 @@ class LIBNYMEA_EXPORT EventType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(int index READ index) + Q_PROPERTY(ParamTypes paramTypes READ paramTypes WRITE setParamTypes) + public: + EventType(); EventType(const EventTypeId &id); EventTypeId id() const; @@ -61,14 +69,19 @@ private: int m_index; QList m_paramTypes; }; +Q_DECLARE_METATYPE(EventType) class EventTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: EventTypes() = default; EventTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); EventType findByName(const QString &name); EventType findById(const EventTypeId &id); }; +Q_DECLARE_METATYPE(EventTypes) #endif // TRIGGERTYPE_H diff --git a/libnymea/types/mediabrowseritem.h b/libnymea/types/mediabrowseritem.h index 64df18b2..03ad702e 100644 --- a/libnymea/types/mediabrowseritem.h +++ b/libnymea/types/mediabrowseritem.h @@ -28,6 +28,8 @@ class MediaBrowserItem: public BrowserItem { Q_GADGET + Q_PROPERTY(MediaBrowserIcon mediaIcon READ mediaIcon) + public: enum MediaBrowserIcon { MediaBrowserIconNone = 1, diff --git a/libnymea/types/param.cpp b/libnymea/types/param.cpp index f49f39f6..0d3b81aa 100644 --- a/libnymea/types/param.cpp +++ b/libnymea/types/param.cpp @@ -109,6 +109,11 @@ ParamList::ParamList(const QList &other): QList(other) } +QVariant ParamList::get(int index) +{ + return QVariant::fromValue(at(index)); +} + /*! Returns true if this ParamList contains a Param with the given \a paramTypeId. */ bool ParamList::hasParam(const ParamTypeId ¶mTypeId) const { diff --git a/libnymea/types/param.h b/libnymea/types/param.h index 04c14fe5..9b180054 100644 --- a/libnymea/types/param.h +++ b/libnymea/types/param.h @@ -32,6 +32,9 @@ class LIBNYMEA_EXPORT Param { + Q_GADGET + Q_PROPERTY(QUuid paramTypeId READ paramTypeId) + Q_PROPERTY(QVariant value READ value WRITE setValue) public: Param(const ParamTypeId ¶mTypeId = ParamTypeId(), const QVariant &value = QVariant()); @@ -52,9 +55,12 @@ QDebug operator<<(QDebug dbg, const Param ¶m); class LIBNYMEA_EXPORT ParamList: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: ParamList(); ParamList(const QList &other); + Q_INVOKABLE QVariant get(int index); bool hasParam(const ParamTypeId ¶mTypeId) const; QVariant paramValue(const ParamTypeId ¶mTypeId) const; bool setParamValue(const ParamTypeId ¶mTypeId, const QVariant &value); @@ -64,7 +70,7 @@ private: QList m_ids; }; - +Q_DECLARE_METATYPE(ParamList) QDebug operator<<(QDebug dbg, const ParamList ¶ms); #endif // PARAM_H diff --git a/libnymea/types/paramtype.cpp b/libnymea/types/paramtype.cpp index 246d4a8e..cb69b88f 100644 --- a/libnymea/types/paramtype.cpp +++ b/libnymea/types/paramtype.cpp @@ -255,6 +255,11 @@ ParamTypes::ParamTypes(const QList &other): QList(other) { } +QVariant ParamTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + ParamType ParamTypes::findByName(const QString &name) { foreach (const ParamType ¶mType, *this) { diff --git a/libnymea/types/paramtype.h b/libnymea/types/paramtype.h index ea80fc00..217e4185 100644 --- a/libnymea/types/paramtype.h +++ b/libnymea/types/paramtype.h @@ -32,6 +32,20 @@ class LIBNYMEA_EXPORT ParamType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(QVariant::Type type READ type WRITE setType) + Q_PROPERTY(int index READ index WRITE setIndex) + Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue USER true) + Q_PROPERTY(QVariant minValue READ minValue WRITE setMinValue USER true) + Q_PROPERTY(QVariant maxValue READ maxValue WRITE setMaxValue USER true) + Q_PROPERTY(QVariantList allowedValues READ allowedValues WRITE setAllowedValues USER true) + Q_PROPERTY(Types::InputType inputType READ inputType WRITE setInputType USER true) + Q_PROPERTY(Types::Unit unit READ unit WRITE setUnit USER true) + Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly USER true) + public: ParamType() = default; ParamType(const ParamTypeId &id, const QString &name, const QVariant::Type type, const QVariant &defaultValue = QVariant()); @@ -96,12 +110,17 @@ private: class ParamTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: ParamTypes() = default; ParamTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); ParamType findByName(const QString &name); ParamType findById(const ParamTypeId &id); }; +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(ParamTypes) QDebug operator<<(QDebug dbg, const ParamType ¶mType); QDebug operator<<(QDebug dbg, const QList ¶mTypes); diff --git a/libnymea/types/state.cpp b/libnymea/types/state.cpp index 272d670c..e1c3185e 100644 --- a/libnymea/types/state.cpp +++ b/libnymea/types/state.cpp @@ -36,6 +36,11 @@ #include "state.h" +State::State() +{ + +} + /*! Constructs a State reflecting the \l{StateType} given by \a stateTypeId * and associated with the \l{Device} given by \a deviceId */ State::State(const StateTypeId &stateTypeId, const DeviceId &deviceId): @@ -92,3 +97,18 @@ QDebug operator<<(QDebug dbg, const QList &states) return dbg.space(); } + +States::States() +{ + +} + +States::States(const QList &other): QList(other) +{ + +} + +QVariant States::get(int index) +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/types/state.h b/libnymea/types/state.h index 471115ca..969323af 100644 --- a/libnymea/types/state.h +++ b/libnymea/types/state.h @@ -32,7 +32,12 @@ class LIBNYMEA_EXPORT State { + Q_GADGET + Q_PROPERTY(QUuid stateTypeId READ stateTypeId) + Q_PROPERTY(QVariant value READ value) + public: + State(); State(const StateTypeId &stateTypeId, const DeviceId &deviceId); StateId id() const; @@ -49,6 +54,18 @@ private: DeviceId m_deviceId; QVariant m_value; }; +Q_DECLARE_METATYPE(State) + +class States: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + States(); + States(const QList &other); + Q_INVOKABLE QVariant get(int index); +}; +Q_DECLARE_METATYPE(States) QDebug operator<<(QDebug dbg, const State &event); QDebug operator<<(QDebug dbg, const QList &events); diff --git a/libnymea/types/statetype.cpp b/libnymea/types/statetype.cpp index acbd55c9..6953f6e1 100644 --- a/libnymea/types/statetype.cpp +++ b/libnymea/types/statetype.cpp @@ -34,6 +34,11 @@ #include "statetype.h" +StateType::StateType() +{ + +} + /*! Constructs a StateType with the given \a id. * When creating a \l{DevicePlugin} generate a new uuid for each StateType you define and * hardcode it into the plugin json file. */ @@ -193,6 +198,11 @@ StateTypes::StateTypes(const QList &other) } } +QVariant StateTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + StateType StateTypes::findByName(const QString &name) { foreach (const StateType &stateType, *this) { diff --git a/libnymea/types/statetype.h b/libnymea/types/statetype.h index 88d65a16..7a3a0905 100644 --- a/libnymea/types/statetype.h +++ b/libnymea/types/statetype.h @@ -32,7 +32,20 @@ class LIBNYMEA_EXPORT StateType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(QVariant::Type type READ type WRITE setType) + Q_PROPERTY(int index READ index WRITE setIndex) + Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue) + Q_PROPERTY(Types::Unit unit READ unit WRITE setUnit USER true) + Q_PROPERTY(QVariant minValue READ minValue WRITE setMinValue USER true) + Q_PROPERTY(QVariant maxValue READ maxValue WRITE setMaxValue USER true) + Q_PROPERTY(QVariantList possibleValues READ possibleValues WRITE setPossibleValues USER true) + public: + StateType(); StateType(const StateTypeId &id); StateTypeId id() const; @@ -83,14 +96,19 @@ private: Types::Unit m_unit = Types::UnitNone; bool m_cached = true; }; +Q_DECLARE_METATYPE(StateType) class StateTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: StateTypes() = default; StateTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); StateType findByName(const QString &name); StateType findById(const StateTypeId &id); }; +Q_DECLARE_METATYPE(StateTypes) #endif // STATETYPE_H diff --git a/libnymea/types/vendor.h b/libnymea/types/vendor.h index cdbb32ae..27010619 100644 --- a/libnymea/types/vendor.h +++ b/libnymea/types/vendor.h @@ -32,6 +32,11 @@ class LIBNYMEA_EXPORT Vendor { + Q_GADGET + Q_PROPERTY(QUuid id READ id WRITE setId) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + public: Vendor(const VendorId &id, const QString &name = QString()); diff --git a/libnymea/typeutils.h b/libnymea/typeutils.h index d211d9ff..a8439a69 100644 --- a/libnymea/typeutils.h +++ b/libnymea/typeutils.h @@ -32,7 +32,7 @@ #define DECLARE_TYPE_ID(type) class type##Id: public QUuid \ { \ public: \ - type##Id(const QString &uuid): QUuid(uuid) {} \ + type##Id(const QUuid &uuid): QUuid(uuid) {} \ type##Id(): QUuid() {} \ static type##Id create##type##Id() { return type##Id(QUuid::createUuid().toString()); } \ static type##Id fromUuid(const QUuid &uuid) { return type##Id(uuid.toString()); } \ diff --git a/tests/scripts/getactiontype.sh b/tests/scripts/getactiontype.sh index 94f8d2be..38f5447f 100755 --- a/tests/scripts/getactiontype.sh +++ b/tests/scripts/getactiontype.sh @@ -2,6 +2,10 @@ if [ -z $2 ]; then echo "usage: $0 host actionTypeId" -else - (echo '{"id":1, "method":"Actions.GetActionType", "params":{"actionTypeId":"'$2'"}}'; sleep 1) | nc $1 2222 + exit 1; fi + +cat << EOD | nc $1 2222 +{"id":0, "method":"JSONRPC.Hello"} +{"id":1, "method":"Actions.GetActionType", "params":{"actionTypeId":"$2"}} +EOD diff --git a/tests/scripts/getactiontypes.sh b/tests/scripts/getactiontypes.sh index 0557d377..fb03af88 100755 --- a/tests/scripts/getactiontypes.sh +++ b/tests/scripts/getactiontypes.sh @@ -2,6 +2,11 @@ if [ -z $2 ]; then echo "usage: $0 host deviceClassId" -else - (echo '{"id":1, "method":"Devices.GetActionTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 2222 + exit 1 fi + + +cat <" + exit 1 fi + +if [ -z $2 ]; then +cat < Date: Mon, 28 Oct 2019 12:32:04 +0100 Subject: [PATCH 08/22] implement stubs for AddDelivery and GetDeliveries --- libnymea-core/jsonrpc/devicehandler.cpp | 4 +- libnymea/devices/device.cpp | 11 ++ libnymea/devices/device.h | 1 + libnymea/jsonrpc/jsonhandler.cpp | 199 +++++++++++++++++------- libnymea/jsonrpc/jsonhandler.h | 31 +++- libnymea/time/calendaritem.cpp | 15 ++ libnymea/time/calendaritem.h | 12 ++ 7 files changed, 213 insertions(+), 60 deletions(-) diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 37429bee..69e749b1 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -443,7 +443,7 @@ JsonReply* DeviceHandler::GetPlugins(const QVariantMap ¶ms) const QVariantList plugins; foreach (DevicePlugin* plugin, NymeaCore::instance()->deviceManager()->plugins()) { - QVariantMap packedPlugin = pack(*plugin); + QVariantMap packedPlugin = pack(*plugin).toMap(); packedPlugin["displayName"] = NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale); plugins.append(packedPlugin); } @@ -904,7 +904,7 @@ QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const Plugi { ParamType translatedParamType = paramType; translatedParamType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); - return pack(translatedParamType); + return pack(translatedParamType).toMap(); } QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const diff --git a/libnymea/devices/device.cpp b/libnymea/devices/device.cpp index 5ed27594..f138181a 100644 --- a/libnymea/devices/device.cpp +++ b/libnymea/devices/device.cpp @@ -460,3 +460,14 @@ Devices Devices::filterByParentDeviceId(const DeviceId &deviceId) } return ret; } + +Devices Devices::filterByInterface(const QString &interface) +{ + Devices ret; + foreach (Device *device, *this) { + if (device->deviceClass().interfaces().indexOf(interface) >= 0) { + ret.append(device); + } + } + return ret; +} diff --git a/libnymea/devices/device.h b/libnymea/devices/device.h index 7a012b01..ac24b82b 100644 --- a/libnymea/devices/device.h +++ b/libnymea/devices/device.h @@ -161,6 +161,7 @@ public: Devices filterByParam(const ParamTypeId ¶mTypeId, const QVariant &value = QVariant()); Devices filterByDeviceClassId(const DeviceClassId &deviceClassId); Devices filterByParentDeviceId(const DeviceId &deviceId); + Devices filterByInterface(const QString &interface); }; Q_DECLARE_METATYPE(Device::DeviceError) diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 4f5170e6..656d9e6f 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -140,73 +140,162 @@ JsonReply *JsonHandler::createAsyncReply(const QString &method) const return JsonReply::createAsyncReply(const_cast(this), method); } -QVariantMap JsonHandler::pack(const QMetaObject &metaObject, const void *value) const +QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) const { - QVariantMap ret; -// qWarning() << "+ Packing" << metaObject.className(); - for (int i = 0; i < metaObject.propertyCount(); i++) { - QMetaProperty metaProperty = metaObject.property(i); - if (metaProperty.name() == QStringLiteral("objectName")) { - continue; // Skip QObject's objectName property + QString className = QString(metaObject.className()).split("::").last(); + if (m_listMetaObjects.contains(className)) { + QVariantList ret; + QMetaProperty countProperty = metaObject.property(metaObject.indexOfProperty("count")); + QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(metaObject.className())); + int count = countProperty.readOnGadget(value).toInt(); + QMetaMethod getMethod = metaObject.method(metaObject.indexOfMethod("get(int)")); + for (int i = 0; i < count; i++) { + QVariant entry; + getMethod.invokeOnGadget(const_cast(value), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); + ret.append(pack(entryMetaObject, entry.data())); } + return ret; + } - QVariant val = metaProperty.readOnGadget(value); -// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName(); -// qWarning() << "|-- All list types:" << m_listMetaObjects.keys(); - if (metaProperty.type() == QVariant::UserType) { + if (m_metaObjects.contains(className)) { + QVariantMap ret; + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + + // Skip QObject's objectName property + if (metaProperty.name() == QStringLiteral("objectName")) { + continue; + } + + // Pack flags + if (metaProperty.isFlagType()) { + QString flagName = QString(metaProperty.typeName()).split("::").last(); + Q_ASSERT_X(m_metaFlags.contains(flagName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(className).arg(flagName).toUtf8()); + QMetaEnum metaFlag = m_metaFlags.value(flagName); + int flagValue = metaProperty.readOnGadget(value).toInt(); + QStringList flags; + for (int i = 0; i < metaFlag.keyCount(); i++) { + if ((metaFlag.value(i) & flagValue) > 0) { + flags.append(metaFlag.key(i)); + } + } + ret.insert(metaProperty.name(), flags); + continue; + } + + // Pack enums + if (metaProperty.isEnumType()) { + QString enumName = QString(metaProperty.typeName()).split("::").last(); + Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(className).arg(metaProperty.typeName()).toUtf8()); + QMetaEnum metaEnum = m_metaEnums.value(enumName); + ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); + continue; + } + + // Basic type/Variant type if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { QMetaEnum metaEnum = QMetaEnum::fromType(); -// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt()); ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); - } else if (m_listMetaObjects.contains(metaProperty.typeName())) { - QVariant listObject = metaProperty.readOnGadget(value); - QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName()); - QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count")); - int listCount = countProperty.readOnGadget(listObject.constData()).toInt(); -// qWarning() << "Packing list type" << listObject << "count is" << listCount; - QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)")); -// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)"); + continue; + } - QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className())); - QVariantList list; - for (int i = 0; i < listCount; i++) { - QVariant entry; - metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); -// qWarning() << "|---Feckin hell" << entry; - - list.append(pack(entryMetaObject, entry.data())); + // Our own objects + if (metaProperty.type() == QVariant::UserType) { + if (m_listMetaObjects.contains(metaProperty.typeName())) { + QMetaObject entryMetaObject = m_listMetaObjects.value(metaProperty.typeName()); + ret.insert(metaProperty.name(), pack(entryMetaObject, metaProperty.readOnGadget(value).data())); + continue; } - ret.insert(metaProperty.name(), list); - - - } else { - Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); - } - } else if (metaProperty.isFlagType()) { - QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last()); -// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name())); - int flagValue = metaProperty.readOnGadget(value).toInt(); -// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type(); - QStringList flags; - for (int i = 0; i < metaFlag.keyCount(); i++) { -// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i); - if ((metaFlag.value(i) & flagValue) > 0) { - flags.append(metaFlag.key(i)); + if (m_metaObjects.contains(metaProperty.typeName())) { + QMetaObject entryMetaObject = m_metaObjects.value(metaProperty.typeName()); + ret.insert(metaProperty.name(), pack(entryMetaObject, metaProperty.readOnGadget(value).data())); + continue; } + + Q_ASSERT_X(false, this->metaObject()->className(), QString("Unregistered property type: %1").arg(metaProperty.typeName()).toUtf8()); + qCWarning(dcJsonRpc()) << "Cannot pack property of unregistered object type" << metaProperty.typeName(); + continue; } - ret.insert(metaProperty.name(), flags); - } else if (metaProperty.isEnumType()) { - QString enumName = QString(metaProperty.typeName()).split("::").last(); - Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); - QMetaEnum metaEnum = m_metaEnums.value(enumName); -// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys(); - ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); - } else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { -// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value); - ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); + + // Standard properties, QString, int etc... If it's not optional, or if it's not empty, pack it up + if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { + ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); + } + } + return ret; } - return ret; + + Q_ASSERT_X(false, this->metaObject()->className(), QString("Unregistered object type: %1").arg(className).toUtf8()); + qCWarning(dcJsonRpc()) << "Cannot pack object of unregistered type" << className; + return QVariant(); +// QVariantMap ret; +//// qWarning() << "+ Packing" << metaObject.className(); +// for (int i = 0; i < metaObject.propertyCount(); i++) { +// QMetaProperty metaProperty = metaObject.property(i); +// if (metaProperty.name() == QStringLiteral("objectName")) { +// continue; // Skip QObject's objectName property +// } + +// QVariant val = metaProperty.readOnGadget(value); +//// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName(); +//// qWarning() << "|-- All list types:" << m_listMetaObjects.keys(); +// if (metaProperty.type() == QVariant::UserType) { +// if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { +// QMetaEnum metaEnum = QMetaEnum::fromType(); +//// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt()); +// ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); +// } else if (m_listMetaObjects.contains(metaProperty.typeName())) { +// QVariant listObject = metaProperty.readOnGadget(value); +// QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName()); +// QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count")); +// int listCount = countProperty.readOnGadget(listObject.constData()).toInt(); +//// qWarning() << "Packing list type" << listObject << "count is" << listCount; +// QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)")); +//// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)"); + +// QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className())); +// QVariantList list; +// for (int i = 0; i < listCount; i++) { +// QVariant entry; +// metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); +//// qWarning() << "|---Feckin hell" << entry; + +// list.append(pack(entryMetaObject, entry.data())); +// } + +// ret.insert(metaProperty.name(), list); + + +// } else { +// Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); +// } +// } else if (metaProperty.isFlagType()) { +// QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last()); +//// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name())); +// int flagValue = metaProperty.readOnGadget(value).toInt(); +//// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type(); +// QStringList flags; +// for (int i = 0; i < metaFlag.keyCount(); i++) { +//// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i); +// if ((metaFlag.value(i) & flagValue) > 0) { +// flags.append(metaFlag.key(i)); +// } +// } +// ret.insert(metaProperty.name(), flags); +// } else if (metaProperty.isEnumType()) { +// QString enumName = QString(metaProperty.typeName()).split("::").last(); +// Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); +// QMetaEnum metaEnum = m_metaEnums.value(enumName); +//// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys(); +// ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); +// } else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { +//// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value); +// ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); +// } +// } +// return ret; + } diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index 87423f64..289df8a7 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -49,7 +49,8 @@ public: static BasicType variantTypeToBasicType(QVariant::Type variantType); static QVariant::Type basicTypeToVariantType(BasicType basicType); - template QVariantMap pack(const T &value) const; + template QVariant pack(const T &value) const; + template T unpack(const QVariantMap &map) const; protected: template void registerEnum(); @@ -64,7 +65,7 @@ protected: JsonReply *createAsyncReply(const QString &method) const; private: - QVariantMap pack(const QMetaObject &metaObject, const void *gadget) const; + QVariant pack(const QMetaObject &metaObject, const void *gadget) const; private: QVariantMap m_enums; @@ -189,11 +190,35 @@ T JsonHandler::enumNameToValue(const QString &name) } template -QVariantMap JsonHandler::pack(const T &value) const +QVariant JsonHandler::pack(const T &value) const { QMetaObject metaObject = T::staticMetaObject; return pack(metaObject, static_cast(&value)); } +template +T JsonHandler::unpack(const QVariantMap &map) const +{ + T ret; + QMetaObject metaObject = T::staticMetaObject; + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + if (metaProperty.name() == QStringLiteral("objectName")) { + continue; + } + if (!metaProperty.isWritable()) { + continue; + } + if (!metaProperty.isUser()) { + Q_ASSERT_X(map.contains(metaProperty.name()), this->metaObject()->className(), QString("Missing property %1 in map.").arg(metaProperty.name()).toUtf8()); + } + if (map.contains(metaProperty.name())) { + metaProperty.writeOnGadget(&ret, map.value(metaProperty.name())); + } + } + return ret; +} + + #endif // JSONHANDLER_H diff --git a/libnymea/time/calendaritem.cpp b/libnymea/time/calendaritem.cpp index edee90bb..ee39e1ee 100644 --- a/libnymea/time/calendaritem.cpp +++ b/libnymea/time/calendaritem.cpp @@ -274,3 +274,18 @@ QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem) } + +CalendarItems::CalendarItems() +{ + +} + +CalendarItems::CalendarItems(const QList &other): QList(other) +{ + +} + +QVariant CalendarItems::get(int index) +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/time/calendaritem.h b/libnymea/time/calendaritem.h index 56eb6341..4d2b5534 100644 --- a/libnymea/time/calendaritem.h +++ b/libnymea/time/calendaritem.h @@ -24,6 +24,7 @@ #include #include "repeatingoption.h" +#include class CalendarItem { @@ -66,6 +67,17 @@ private: }; +class CalendarItems: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + CalendarItems(); + CalendarItems(const QList &other); + Q_INVOKABLE QVariant get(int index); +}; +Q_DECLARE_METATYPE(CalendarItems) + QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem); #endif // CALENDARITEM_H From baaa719b6a554962660617d644ba3c138608bd3a Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 29 Oct 2019 23:20:09 +0100 Subject: [PATCH 09/22] Restructuring json done --- .../jsonrpc/configurationhandler.cpp | 47 +-------- libnymea-core/jsonrpc/configurationhandler.h | 5 - libnymea-core/jsonrpc/eventhandler.cpp | 5 +- .../jsonrpc/jsonrpcserverimplementation.cpp | 32 ++++-- .../jsonrpc/jsonrpcserverimplementation.h | 4 +- libnymea-core/jsonrpc/jsonvalidator.cpp | 14 +-- libnymea-core/jsonrpc/logginghandler.cpp | 15 +-- libnymea-core/jsonrpc/ruleshandler.cpp | 99 +++---------------- libnymea-core/jsonrpc/ruleshandler.h | 2 +- libnymea-core/jsonrpc/statehandler.cpp | 16 +-- libnymea-core/jsonrpc/systemhandler.cpp | 59 ++--------- libnymea-core/jsonrpc/systemhandler.h | 4 - libnymea-core/jsonrpc/tagshandler.cpp | 49 ++------- libnymea-core/jsonrpc/tagshandler.h | 3 - libnymea-core/logging/logentry.cpp | 20 ++++ libnymea-core/logging/logentry.h | 14 ++- libnymea-core/nymeaconfiguration.h | 3 +- libnymea-core/nymeacore.cpp | 2 +- libnymea-core/ruleengine/rule.cpp | 15 +++ libnymea-core/ruleengine/rule.h | 23 +++++ libnymea-core/ruleengine/ruleaction.cpp | 48 ++++++++- libnymea-core/ruleengine/ruleaction.h | 40 ++++++-- libnymea-core/ruleengine/ruleactionparam.cpp | 27 +++-- libnymea-core/ruleengine/ruleactionparam.h | 21 +++- libnymea-core/ruleengine/ruleengine.cpp | 4 +- libnymea-core/ruleengine/stateevaluator.cpp | 20 ++++ libnymea-core/ruleengine/stateevaluator.h | 16 +++ libnymea-core/tagging/tag.cpp | 40 ++++++++ libnymea-core/tagging/tag.h | 28 ++++++ libnymea-core/usermanager/tokeninfo.h | 2 +- libnymea/jsonrpc/jsonhandler.cpp | 15 ++- libnymea/jsonrpc/jsonhandler.h | 42 +++++--- libnymea/jsonrpc/jsonrpcserver.h | 2 +- libnymea/platform/package.cpp | 15 +++ libnymea/platform/package.h | 26 +++++ libnymea/platform/repository.cpp | 15 +++ libnymea/platform/repository.h | 16 +++ libnymea/time/repeatingoption.cpp | 15 +++ libnymea/time/repeatingoption.h | 8 +- libnymea/time/timedescriptor.h | 3 + libnymea/time/timeeventitem.cpp | 19 +++- libnymea/time/timeeventitem.h | 19 +++- libnymea/types/eventdescriptor.cpp | 35 +++++++ libnymea/types/eventdescriptor.h | 25 +++++ libnymea/types/param.h | 2 +- libnymea/types/paramdescriptor.cpp | 21 ++++ libnymea/types/paramdescriptor.h | 18 ++++ libnymea/types/statedescriptor.cpp | 30 ++++++ libnymea/types/statedescriptor.h | 16 +++ nymea.pri | 6 +- tests/auto/devices/testdevices.cpp | 31 +++--- tests/auto/jsonrpc/testjsonrpc.cpp | 15 ++- tests/auto/logging/testlogging.cpp | 12 +-- tests/auto/rules/testrules.cpp | 20 ++-- tests/auto/tags/testtags.cpp | 10 +- tests/auto/timemanager/testtimemanager.cpp | 35 ++++++- tests/testlib/nymeatestbase.cpp | 1 + 57 files changed, 785 insertions(+), 364 deletions(-) diff --git a/libnymea-core/jsonrpc/configurationhandler.cpp b/libnymea-core/jsonrpc/configurationhandler.cpp index 4a3f4f64..92b3b0eb 100644 --- a/libnymea-core/jsonrpc/configurationhandler.cpp +++ b/libnymea-core/jsonrpc/configurationhandler.cpp @@ -391,7 +391,7 @@ JsonReply *ConfigurationHandler::SetLanguage(const QVariantMap ¶ms) const JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap ¶ms) const { - ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap()); + ServerConfiguration config = unpack(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); } @@ -421,7 +421,7 @@ JsonReply *ConfigurationHandler::DeleteTcpServerConfiguration(const QVariantMap JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap ¶ms) const { - WebServerConfiguration config = unpackWebServerConfiguration(params.value("configuration").toMap()); + WebServerConfiguration config = unpack(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); @@ -452,7 +452,7 @@ JsonReply *ConfigurationHandler::DeleteWebServerConfiguration(const QVariantMap JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantMap ¶ms) const { - ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap()); + ServerConfiguration config = unpack(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); } @@ -495,7 +495,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap & JsonReply *ConfigurationHandler::SetMqttServerConfiguration(const QVariantMap ¶ms) const { - ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap()); + ServerConfiguration config = unpack(params.value("configuration").toMap()); if (config.id.isEmpty()) { return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); } @@ -538,7 +538,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap ¶ms) cons JsonReply *ConfigurationHandler::SetMqttPolicy(const QVariantMap ¶ms) const { - MqttPolicy policy = unpackMqttPolicy(params.value("policy").toMap()); + MqttPolicy policy = unpack(params.value("policy").toMap()); NymeaCore::instance()->configuration()->updateMqttPolicy(policy); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError)); } @@ -664,43 +664,6 @@ QVariantMap ConfigurationHandler::packBasicConfiguration() return basicConfiguration; } - -MqttPolicy ConfigurationHandler::unpackMqttPolicy(const QVariantMap &mqttPolicyMap) -{ - MqttPolicy policy; - policy.clientId = mqttPolicyMap.value("clientId").toString(); - policy.username = mqttPolicyMap.value("username").toString(); - policy.password = mqttPolicyMap.value("password").toString(); - policy.allowedPublishTopicFilters = mqttPolicyMap.value("allowedPublishTopicFilters").toStringList(); - policy.allowedSubscribeTopicFilters = mqttPolicyMap.value("allowedSubscribeTopicFilters").toStringList(); - return policy; -} - -ServerConfiguration ConfigurationHandler::unpackServerConfiguration(const QVariantMap &serverConfigurationMap) -{ - ServerConfiguration serverConfiguration; - serverConfiguration.id = serverConfigurationMap.value("id").toString(); - serverConfiguration.address = QHostAddress(serverConfigurationMap.value("address").toString()); - serverConfiguration.port = serverConfigurationMap.value("port").toUInt(); - serverConfiguration.sslEnabled = serverConfigurationMap.value("sslEnabled", true).toBool(); - serverConfiguration.authenticationEnabled = serverConfigurationMap.value("authenticationEnabled", true).toBool(); - return serverConfiguration; -} - -WebServerConfiguration ConfigurationHandler::unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap) -{ - ServerConfiguration tmp = unpackServerConfiguration(webServerConfigurationMap); - WebServerConfiguration webServerConfiguration; - webServerConfiguration.id = tmp.id; - webServerConfiguration.address = tmp.address; - webServerConfiguration.port = tmp.port; - webServerConfiguration.sslEnabled = tmp.sslEnabled; - webServerConfiguration.authenticationEnabled = tmp.authenticationEnabled; - webServerConfiguration.publicFolder = webServerConfigurationMap.value("publicFolder").toString(); - qWarning() << "Unpacking web server config:" << webServerConfigurationMap; - return webServerConfiguration; -} - QVariantMap ConfigurationHandler::statusToReply(NymeaConfiguration::ConfigurationError status) const { QVariantMap returns; diff --git a/libnymea-core/jsonrpc/configurationhandler.h b/libnymea-core/jsonrpc/configurationhandler.h index 578debdb..d2fc4667 100644 --- a/libnymea-core/jsonrpc/configurationhandler.h +++ b/libnymea-core/jsonrpc/configurationhandler.h @@ -92,11 +92,6 @@ private slots: private: static QVariantMap packBasicConfiguration(); - - static ServerConfiguration unpackServerConfiguration(const QVariantMap &serverConfigurationMap); - static WebServerConfiguration unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap); - static MqttPolicy unpackMqttPolicy(const QVariantMap &mqttPolicyMap); - QVariantMap statusToReply(NymeaConfiguration::ConfigurationError status) const; }; diff --git a/libnymea-core/jsonrpc/eventhandler.cpp b/libnymea-core/jsonrpc/eventhandler.cpp index b33254f4..7d8fcbfc 100644 --- a/libnymea-core/jsonrpc/eventhandler.cpp +++ b/libnymea-core/jsonrpc/eventhandler.cpp @@ -54,19 +54,20 @@ EventHandler::EventHandler(QObject *parent) : registerObject(); registerObject(); registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; description = "Get the EventType for the given eventTypeId."; params.insert("eventTypeId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); - returns.insert("o:eventType", objectRef("EventType")); + returns.insert("o:eventType", objectRef()); registerMethod("GetEventType", description, params, returns); // Notifications params.clear(); returns.clear(); description = "Emitted whenever an Event is triggered."; - params.insert("event", objectRef("Event")); + params.insert("event", objectRef()); registerNotification("EventTriggered", description, params); connect(NymeaCore::instance(), &NymeaCore::eventTriggered, this, &EventHandler::eventTriggered); } diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp index 5a4aaab0..a66b28c0 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp @@ -80,14 +80,13 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration registerEnum(); // Objects -// QVariantMap tokenInfo; -// tokenInfo.insert("id", enumValueName(Uuid)); -// tokenInfo.insert("userName", enumValueName(String)); -// tokenInfo.insert("deviceName", enumValueName(String)); -// tokenInfo.insert("creationTime", enumValueName(Uint)); -// registerObject("TokenInfo", tokenInfo); registerObject(); + QVariantMap experiece; + experiece.insert("name", enumValueName(String)); + experiece.insert("version", enumValueName(String)); + registerObject("Experience", experiece); + // Methods QString description; QVariantMap returns; QVariantMap params; description = "Initiates a connection. Use this method to perform an initial handshake of the " @@ -110,6 +109,7 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration returns.insert("initialSetupRequired", enumValueName(Bool)); returns.insert("authenticationRequired", enumValueName(Bool)); returns.insert("pushButtonAuthAvailable", enumValueName(Bool)); + returns.insert("o:experiences", QVariantList() << objectRef("Experience")); registerMethod("Hello", description, params, returns); params.clear(); returns.clear(); @@ -455,6 +455,15 @@ void JsonRPCServerImplementation::unregisterTransportInterface(TransportInterfac m_interfaces.take(interface); } +bool JsonRPCServerImplementation::registerExperienceHandler(JsonHandler *handler, int majorVersion, int minorVersion) +{ + bool ret = registerHandler(handler); + if (ret) { + m_experiences.insert(handler, QString("%1.%2").arg(majorVersion).arg(minorVersion)); + } + return ret; +} + /*! Send a JSON success response to the client with the given \a clientId, * \a commandId and \a params to the inerted \l{TransportInterface}. */ @@ -511,6 +520,16 @@ QVariantMap JsonRPCServerImplementation::createWelcomeMessage(TransportInterface handshake.insert("initialSetupRequired", (interface->configuration().authenticationEnabled ? NymeaCore::instance()->userManager()->initRequired() : false)); handshake.insert("authenticationRequired", interface->configuration().authenticationEnabled); handshake.insert("pushButtonAuthAvailable", NymeaCore::instance()->userManager()->pushButtonAuthAvailable()); + if (!m_experiences.isEmpty()) { + QVariantList experiences; + foreach (JsonHandler* handler, m_experiences.keys()) { + QVariantMap experience; + experience.insert("name", handler->name()); + experience.insert("version", m_experiences.value(handler)); + experiences.append(experience); + } + handshake.insert("experiences", experiences); + } return handshake; } @@ -634,6 +653,7 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac if (!validationResult.success()) { qCWarning(dcJsonRpc()) << "JSON RPC parameter verification failed for method" << targetNamespace + '.' + method; qCWarning(dcJsonRpc()) << validationResult.errorString() << "in" << validationResult.where(); + qCWarning(dcJsonRpc()) << "Call params:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson()); sendErrorResponse(interface, clientId, commandId, "Invalid params: " + validationResult.errorString() + " in " + validationResult.where()); return; } diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h index 7d9f2598..59bcea8e 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h @@ -72,9 +72,10 @@ public: void registerTransportInterface(TransportInterface *interface, bool authenticationRequired); void unregisterTransportInterface(TransportInterface *interface); - bool registerHandler(JsonHandler *handler) override; + bool registerExperienceHandler(JsonHandler *handler, int majorVersion, int minorVersion) override; private: + bool registerHandler(JsonHandler *handler); QHash handlers() const; void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms = QVariantMap()); @@ -102,6 +103,7 @@ private slots: private: QVariantMap m_api; + QHash m_experiences; QMap m_interfaces; // Interface, authenticationRequired QHash m_handlers; QHash m_asyncReplies; diff --git a/libnymea-core/jsonrpc/jsonvalidator.cpp b/libnymea-core/jsonrpc/jsonvalidator.cpp index 7b9e3dbc..d5557bb0 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.cpp +++ b/libnymea-core/jsonrpc/jsonvalidator.cpp @@ -16,7 +16,7 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &api) QVariantMap types = api.value("types").toMap(); // qWarning() << "checkrefs enums" << enums.keys(); foreach (const QString &key, map.keys()) { -// qWarning() << "checking prop" << key; +// qWarning() << "checking prop" << key << types.keys(); if (map.value(key).toString().startsWith("$ref:")) { QString refName = map.value(key).toString().remove("$ref:"); if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) { @@ -121,9 +121,6 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api) { -// qWarning() << "validating" << definition; -// qWarning() << "** enums:" << api.value("enums").toMap().keys(); -// qWarning() << "** types:" << api.value("types").toMap().keys(); if (definition.type() == QVariant::String) { QString expectedTypeName = definition.toString(); @@ -146,12 +143,10 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariantMap flags = api.value("flags").toMap(); if (flags.contains(refName)) { QVariant refDefinition = flags.value(refName); - qWarning() << "Flag:" << value.type(); if (value.type() != QVariant::StringList) { return Result(false, "Expected flags " + refName + " but got " + value.toString()); } QString flagEnum = refDefinition.toList().first().toString(); - qWarning() << "Flag enum:" << flagEnum; foreach (const QVariant &flagsEntry, value.toList()) { Result result = validateEntry(flagsEntry, flagEnum, api); if (!result.success()) { @@ -211,9 +206,8 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const } // Time if (expectedBasicType == JsonHandler::Time) { - bool ok; - QDateTime time = QDateTime::fromTime_t(value.toUInt(&ok)); - if (!ok || !time.isValid()) { + QTime time = QTime::fromString(value.toString(), "hh:mm"); + if (!time.isValid()) { return Result(false, "Invalid Time: " + value.toString()); } } @@ -224,7 +218,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const if (definition.type() == QVariant::Map) { if (value.type() != QVariant::Map) { - return Result(false, "Invalud value. Expected a map bug received: " + value.toString()); + return Result(false, "Invalid value. Expected a map bug received: " + value.toString()); } return validateMap(value.toMap(), definition.toMap(), api); } diff --git a/libnymea-core/jsonrpc/logginghandler.cpp b/libnymea-core/jsonrpc/logginghandler.cpp index 5af2e1c7..c5b047bf 100644 --- a/libnymea-core/jsonrpc/logginghandler.cpp +++ b/libnymea-core/jsonrpc/logginghandler.cpp @@ -45,6 +45,7 @@ #include "logginghandler.h" #include "logging/logengine.h" #include "logging/logfilter.h" +#include "logging/logentry.h" #include "logging/logvaluetool.h" #include "loggingcategories.h" #include "nymeacore.h" @@ -62,7 +63,7 @@ LoggingHandler::LoggingHandler(QObject *parent) : registerEnum(); // Objects - registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -94,7 +95,7 @@ LoggingHandler::LoggingHandler(QObject *parent) : params.insert("o:limit", enumValueName(Int)); params.insert("o:offset", enumValueName(Int)); returns.insert("loggingError", enumRef()); - returns.insert("o:logEntries", QVariantList() << objectRef("LogEntry")); + returns.insert("o:logEntries", objectRef()); returns.insert("count", enumValueName(Int)); returns.insert("offset", enumValueName(Int)); registerMethod("GetLogEntries", description, params, returns); @@ -102,7 +103,7 @@ LoggingHandler::LoggingHandler(QObject *parent) : // Notifications params.clear(); description = "Emitted whenever an entry is appended to the logging system. "; - params.insert("logEntry", objectRef("LogEntry")); + params.insert("logEntry", objectRef()); registerNotification("LogEntryAdded", description, params); params.clear(); @@ -187,7 +188,10 @@ QVariantMap LoggingHandler::packLogEntry(const LogEntry &logEntry) case Logging::LoggingSourceActions: case Logging::LoggingSourceEvents: case Logging::LoggingSourceStates: - logEntryMap.insert("typeId", logEntry.typeId()); + case Logging::LoggingSourceBrowserActions: + if (!logEntry.typeId().isNull()) { + logEntryMap.insert("typeId", logEntry.typeId()); + } logEntryMap.insert("deviceId", logEntry.deviceId()); logEntryMap.insert("value", LogValueTool::convertVariantToString(logEntry.value())); break; @@ -197,9 +201,6 @@ QVariantMap LoggingHandler::packLogEntry(const LogEntry &logEntry) case Logging::LoggingSourceRules: logEntryMap.insert("typeId", logEntry.typeId().toString()); break; - case Logging::LoggingSourceBrowserActions: - logEntryMap.insert("itemId", logEntry.value()); - break; } return logEntryMap; diff --git a/libnymea-core/jsonrpc/ruleshandler.cpp b/libnymea-core/jsonrpc/ruleshandler.cpp index 457f4ff1..cd9075c8 100644 --- a/libnymea-core/jsonrpc/ruleshandler.cpp +++ b/libnymea-core/jsonrpc/ruleshandler.cpp @@ -80,86 +80,17 @@ RulesHandler::RulesHandler(QObject *parent) : ruleDescription.insert("executable", enumValueName(Bool)); registerObject("RuleDescription", ruleDescription); - QVariantMap paramDescriptor; - paramDescriptor.insert("o:paramTypeId", enumValueName(Uuid)); - paramDescriptor.insert("o:paramName", enumValueName(Uuid)); - paramDescriptor.insert("value", enumValueName(Variant)); - paramDescriptor.insert("operator", enumRef()); - registerObject("ParamDescriptor", paramDescriptor); - - QVariantMap eventDescriptor; - eventDescriptor.insert("o:eventTypeId", enumValueName(Uuid)); - eventDescriptor.insert("o:deviceId", enumValueName(Uuid)); - eventDescriptor.insert("o:interface", enumValueName(String)); - eventDescriptor.insert("o:interfaceEvent", enumValueName(String)); - eventDescriptor.insert("o:paramDescriptors", QVariantList() << objectRef("ParamDescriptor")); - registerObject("EventDescriptor", eventDescriptor); - - QVariantMap stateDescriptor; - stateDescriptor.insert("o:stateTypeId", enumValueName(Uuid)); - stateDescriptor.insert("o:deviceId", enumValueName(Uuid)); - stateDescriptor.insert("o:interface", enumValueName(String)); - stateDescriptor.insert("o:interfaceState", enumValueName(String)); - stateDescriptor.insert("value", enumValueName(Variant)); - stateDescriptor.insert("operator", enumRef()); - registerObject("StateDescriptor", stateDescriptor); - - QVariantMap stateEvaluator; - stateEvaluator.insert("o:stateDescriptor", objectRef("StateDescriptor")); - stateEvaluator.insert("o:childEvaluators", QVariantList() << objectRef("StateEvaluator")); - stateEvaluator.insert("o:operator", enumRef()); - registerObject("StateEvaluator", stateEvaluator); - - QVariantMap repeatingOption; - repeatingOption.insert("mode", enumRef()); - repeatingOption.insert("o:weekDays", QVariantList() << enumValueName(Int)); - repeatingOption.insert("o:monthDays", QVariantList() << enumValueName(Int)); - registerObject("RepeatingOption", repeatingOption); - - registerObject(); - - QVariantMap timeEventItem; - timeEventItem.insert("o:datetime", enumValueName(Uint)); - timeEventItem.insert("o:time", enumValueName(Time)); - timeEventItem.insert("o:repeating", objectRef("RepeatingOption")); - registerObject("TimeEventItem", timeEventItem); - - QVariantMap timeDescriptor; - timeDescriptor.insert("o:calendarItems", QVariantList() << objectRef("CalendarItem")); - timeDescriptor.insert("o:timeEventItems", QVariantList() << objectRef("TimeEventItem")); - registerObject("TimeDescriptor", timeDescriptor); - - QVariantMap ruleActionParam; - ruleActionParam.insert("o:paramTypeId", enumValueName(Uuid)); - ruleActionParam.insert("o:paramName", enumValueName(String)); - ruleActionParam.insert("o:value", enumValueName(Variant)); - ruleActionParam.insert("o:eventTypeId", enumValueName(Uuid)); - ruleActionParam.insert("o:eventParamTypeId", enumValueName(Uuid)); - ruleActionParam.insert("o:stateDeviceId", enumValueName(Uuid)); - ruleActionParam.insert("o:stateTypeId", enumValueName(Uuid)); - registerObject("RuleActionParam", ruleActionParam); - - QVariantMap ruleAction; - ruleAction.insert("o:deviceId", enumValueName(Uuid)); - ruleAction.insert("o:actionTypeId", enumValueName(Uuid)); - ruleAction.insert("o:interface", enumValueName(String)); - ruleAction.insert("o:interfaceAction", enumValueName(String)); - ruleAction.insert("o:browserItemId", enumValueName(String)); - ruleAction.insert("o:ruleActionParams", QVariantList() << objectRef("RuleActionParam")); - registerObject("RuleAction", ruleAction); - - QVariantMap rule; - rule.insert("id", enumValueName(Uuid)); - rule.insert("name", enumValueName(String)); - rule.insert("enabled", enumValueName(Bool)); - rule.insert("executable", enumValueName(Bool)); - rule.insert("active", enumValueName(Bool)); - rule.insert("eventDescriptors", QVariantList() << objectRef("EventDescriptor")); - rule.insert("actions", QVariantList() << objectRef("RuleAction")); - rule.insert("exitActions", QVariantList() << objectRef("RuleAction")); - rule.insert("stateEvaluator", objectRef("StateEvaluator")); - rule.insert("timeDescriptor", objectRef("TimeDescriptor")); - registerObject("Rule", rule); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -765,7 +696,7 @@ TimeEventItem RulesHandler::unpackTimeEventItem(const QVariantMap &timeEventItem TimeEventItem timeEventItem; if (timeEventItemMap.contains("datetime")) - timeEventItem.setDateTime(timeEventItemMap.value("datetime").toUInt()); + timeEventItem.setDateTime(QDateTime::fromTime_t(timeEventItemMap.value("datetime").toUInt())); if (timeEventItemMap.contains("time")) timeEventItem.setTime(timeEventItemMap.value("time").toTime()); @@ -831,9 +762,9 @@ RuleActionParam RulesHandler::unpackRuleActionParam(const QVariantMap &ruleActio return param; } -RuleActionParamList RulesHandler::unpackRuleActionParams(const QVariantList &ruleActionParamList) +RuleActionParams RulesHandler::unpackRuleActionParams(const QVariantList &ruleActionParamList) { - RuleActionParamList ruleActionParams; + RuleActionParams ruleActionParams; foreach (const QVariant ¶mVariant, ruleActionParamList) ruleActionParams.append(unpackRuleActionParam(paramVariant.toMap())); @@ -847,7 +778,7 @@ RuleAction RulesHandler::unpackRuleAction(const QVariantMap &ruleActionMap) QString interface = ruleActionMap.value("interface").toString(); QString interfaceAction = ruleActionMap.value("interfaceAction").toString(); QString browserItemId = ruleActionMap.value("browserItemId").toString(); - RuleActionParamList actionParamList = unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList()); + RuleActionParams actionParamList = unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList()); if (!actionDeviceId.isNull() && !actionTypeId.isNull()) { return RuleAction(actionTypeId, actionDeviceId, actionParamList); diff --git a/libnymea-core/jsonrpc/ruleshandler.h b/libnymea-core/jsonrpc/ruleshandler.h index c6a65595..56b25a41 100644 --- a/libnymea-core/jsonrpc/ruleshandler.h +++ b/libnymea-core/jsonrpc/ruleshandler.h @@ -87,7 +87,7 @@ private: static StateDescriptor unpackStateDescriptor(const QVariantMap &stateDescriptorMap); static StateEvaluator unpackStateEvaluator(const QVariantMap &stateEvaluatorMap); static RuleActionParam unpackRuleActionParam(const QVariantMap &ruleActionParamMap); - static RuleActionParamList unpackRuleActionParams(const QVariantList &ruleActionParamList); + static RuleActionParams unpackRuleActionParams(const QVariantList &ruleActionParamList); static RuleAction unpackRuleAction(const QVariantMap &ruleActionMap); static Rule unpackRule(const QVariantMap &ruleMap); diff --git a/libnymea-core/jsonrpc/statehandler.cpp b/libnymea-core/jsonrpc/statehandler.cpp index d260d322..ed103716 100644 --- a/libnymea-core/jsonrpc/statehandler.cpp +++ b/libnymea-core/jsonrpc/statehandler.cpp @@ -43,18 +43,16 @@ namespace nymeaserver { StateHandler::StateHandler(QObject *parent) : JsonHandler(parent) { - QVariantMap state; - state.insert("stateTypeId", enumValueName(Uuid)); - state.insert("deviceId", enumValueName(Uuid)); - state.insert("value", enumValueName(Variant)); - registerObject("State", state); + registerEnum(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; description = "Get the StateType for the given stateTypeId."; params.insert("stateTypeId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); - returns.insert("o:stateType", objectRef("StateType")); + returns.insert("o:stateType", objectRef()); registerMethod("GetStateType", description, params, returns, true); } @@ -66,6 +64,7 @@ QString StateHandler::name() const JsonReply* StateHandler::GetStateType(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); qCDebug(dcJsonRpc) << "asked for state type" << params; StateTypeId stateTypeId(params.value("stateTypeId").toString()); foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { @@ -73,8 +72,9 @@ JsonReply* StateHandler::GetStateType(const QVariantMap ¶ms) const if (stateType.id() == stateTypeId) { QVariantMap data; data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); - // FIXME TODO!!! -// data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); + StateType translatedStateType = stateType; + translatedStateType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), stateType.displayName(), locale)); + data.insert("stateType", pack(translatedStateType)); return createReply(data); } } diff --git a/libnymea-core/jsonrpc/systemhandler.cpp b/libnymea-core/jsonrpc/systemhandler.cpp index d1c3e367..c433f97b 100644 --- a/libnymea-core/jsonrpc/systemhandler.cpp +++ b/libnymea-core/jsonrpc/systemhandler.cpp @@ -33,23 +33,8 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): m_platform(platform) { // Objects - QVariantMap package; - package.insert("id", enumValueName(String)); - package.insert("displayName", enumValueName(String)); - package.insert("summary", enumValueName(String)); - package.insert("installedVersion", enumValueName(String)); - package.insert("candidateVersion", enumValueName(String)); - package.insert("changelog", enumValueName(String)); - package.insert("updateAvailable", enumValueName(Bool)); - package.insert("rollbackAvailable", enumValueName(Bool)); - package.insert("canRemove", enumValueName(Bool)); - registerObject("Package", package); - - QVariantMap repository; - repository.insert("id", enumValueName(String)); - repository.insert("displayName", enumValueName(String)); - repository.insert("enabled", enumValueName(Bool)); - registerObject("Repository", repository); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -93,7 +78,7 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): params.clear(); returns.clear(); description = "Get the list of packages currently available to the system. This might include installed available but " "not installed packages. Installed packages will have the installedVersion set to a non-empty value."; - returns.insert("packages", QVariantList() << objectRef("Package")); + returns.insert("packages", objectRef("Packages")); registerMethod("GetPackages", description, params, returns); params.clear(); returns.clear(); @@ -121,7 +106,7 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): params.clear(); returns.clear(); description = "Get the list of repositories currently available to the system."; - returns.insert("repositories", QVariantList() << objectRef("Repository")); + returns.insert("repositories",objectRef("Repositories")); registerMethod("GetRepositories", description, params, returns); params.clear(); returns.clear(); @@ -192,12 +177,12 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): }); connect(m_platform->updateController(), &PlatformUpdateController::packageAdded, this, [this](const Package &package){ QVariantMap params; - params.insert("package", packPackage(package)); + params.insert("package", pack(package)); emit PackageAdded(params); }); connect(m_platform->updateController(), &PlatformUpdateController::packageChanged, this, [this](const Package &package){ QVariantMap params; - params.insert("package", packPackage(package)); + params.insert("package", pack(package)); emit PackageChanged(params); }); connect(m_platform->updateController(), &PlatformUpdateController::packageRemoved, this, [this](const QString &packageId){ @@ -207,12 +192,12 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent): }); connect(m_platform->updateController(), &PlatformUpdateController::repositoryAdded, this, [this](const Repository &repository){ QVariantMap params; - params.insert("repository", packRepository(repository)); + params.insert("repository", pack(repository)); emit RepositoryAdded(params); }); connect(m_platform->updateController(), &PlatformUpdateController::repositoryChanged, this, [this](const Repository &repository){ QVariantMap params; - params.insert("repository", packRepository(repository)); + params.insert("repository", pack(repository)); emit RepositoryChanged(params); }); connect(m_platform->updateController(), &PlatformUpdateController::repositoryRemoved, this, [this](const QString &repositoryId){ @@ -277,7 +262,7 @@ JsonReply *SystemHandler::GetPackages(const QVariantMap ¶ms) const Q_UNUSED(params) QVariantList packagelist; foreach (const Package &package, m_platform->updateController()->packages()) { - packagelist.append(packPackage(package)); + packagelist.append(pack(package)); } QVariantMap returns; returns.insert("packages", packagelist); @@ -313,7 +298,7 @@ JsonReply *SystemHandler::GetRepositories(const QVariantMap ¶ms) const Q_UNUSED(params) QVariantList repos; foreach (const Repository &repository, m_platform->updateController()->repositories()) { - repos.append(packRepository(repository)); + repos.append(pack(repository)); } QVariantMap returns; returns.insert("repositories", repos); @@ -337,28 +322,4 @@ void SystemHandler::onCapabilitiesChanged() emit CapabilitiesChanged(caps); } -QVariantMap SystemHandler::packPackage(const Package &package) -{ - QVariantMap ret; - ret.insert("id", package.packageId()); - ret.insert("displayName", package.displayName()); - ret.insert("summary", package.summary()); - ret.insert("installedVersion", package.installedVersion()); - ret.insert("candidateVersion", package.candidateVersion()); - ret.insert("changelog", package.changelog()); - ret.insert("updateAvailable", package.updateAvailable()); - ret.insert("rollbackAvailable", package.rollbackAvailable()); - ret.insert("canRemove", package.canRemove()); - return ret; -} - -QVariantMap SystemHandler::packRepository(const Repository &repository) -{ - QVariantMap ret; - ret.insert("id", repository.id()); - ret.insert("displayName", repository.displayName()); - ret.insert("enabled", repository.enabled()); - return ret; -} - } diff --git a/libnymea-core/jsonrpc/systemhandler.h b/libnymea-core/jsonrpc/systemhandler.h index 3a73bd6b..4c43a4e8 100644 --- a/libnymea-core/jsonrpc/systemhandler.h +++ b/libnymea-core/jsonrpc/systemhandler.h @@ -66,10 +66,6 @@ signals: private slots: void onCapabilitiesChanged(); -private: - static QVariantMap packPackage(const Package &package); - static QVariantMap packRepository(const Repository &repository); - private: Platform *m_platform = nullptr; }; diff --git a/libnymea-core/jsonrpc/tagshandler.cpp b/libnymea-core/jsonrpc/tagshandler.cpp index 913ca9a5..e9b842f8 100644 --- a/libnymea-core/jsonrpc/tagshandler.cpp +++ b/libnymea-core/jsonrpc/tagshandler.cpp @@ -31,13 +31,7 @@ TagsHandler::TagsHandler(QObject *parent) : JsonHandler(parent) registerEnum(); // Objects - QVariantMap tag; - tag.insert("o:deviceId", enumValueName(Uuid)); - tag.insert("o:ruleId", enumValueName(Uuid)); - tag.insert("appId", enumValueName(String)); - tag.insert("tagId", enumValueName(String)); - tag.insert("o:value", enumValueName(String)); - registerObject("Tag", tag); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -47,7 +41,7 @@ TagsHandler::TagsHandler(QObject *parent) : JsonHandler(parent) params.insert("o:appId", enumValueName(String)); params.insert("o:tagId", enumValueName(String)); returns.insert("tagError", enumRef()); - returns.insert("o:tags", QVariantList() << objectRef("Tag")); + returns.insert("o:tags", objectRef("Tags")); registerMethod("GetTags", description, params, returns); params.clear(); returns.clear(); @@ -103,7 +97,7 @@ JsonReply *TagsHandler::GetTags(const QVariantMap ¶ms) const if (params.contains("tagId") && params.value("tagId").toString() != tag.tagId()) { continue; } - ret.append(packTag(tag)); + ret.append(pack(tag)); } QVariantMap returns = statusToReply(TagsStorage::TagErrorNoError); returns.insert("tags", ret); @@ -113,7 +107,7 @@ JsonReply *TagsHandler::GetTags(const QVariantMap ¶ms) const JsonReply *TagsHandler::AddTag(const QVariantMap ¶ms) const { - Tag tag = unpackTag(params.value("tag").toMap()); + Tag tag = unpack(params.value("tag").toMap()); TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->addTag(tag); QVariantMap returns = statusToReply(error); return createReply(returns); @@ -121,7 +115,7 @@ JsonReply *TagsHandler::AddTag(const QVariantMap ¶ms) const JsonReply *TagsHandler::RemoveTag(const QVariantMap ¶ms) const { - Tag tag = unpackTag(params.value("tag").toMap()); + Tag tag = unpack(params.value("tag").toMap()); TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->removeTag(tag); QVariantMap returns = statusToReply(error); return createReply(returns); @@ -131,7 +125,7 @@ void TagsHandler::onTagAdded(const Tag &tag) { qCDebug(dcJsonRpc) << "Notify \"Tags.TagAdded\""; QVariantMap params; - params.insert("tag", packTag(tag)); + params.insert("tag", pack(tag)); emit TagAdded(params); } @@ -139,7 +133,7 @@ void TagsHandler::onTagRemoved(const Tag &tag) { qCDebug(dcJsonRpc) << "Notify \"Tags.TagRemoved\""; QVariantMap params; - params.insert("tag", packTag(tag)); + params.insert("tag", pack(tag)); emit TagRemoved(params); } @@ -147,37 +141,10 @@ void TagsHandler::onTagValueChanged(const Tag &tag) { qCDebug(dcJsonRpc) << "Notify \"Tags.TagValueChanged\""; QVariantMap params; - params.insert("tag", packTag(tag)); + params.insert("tag", pack(tag)); emit TagValueChanged(params); } -QVariantMap TagsHandler::packTag(const Tag &tag) -{ - QVariantMap ret; - if (!tag.deviceId().isNull()){ - ret.insert("deviceId", tag.deviceId().toString()); - } else { - ret.insert("ruleId", tag.ruleId().toString()); - } - ret.insert("appId", tag.appId()); - ret.insert("tagId", tag.tagId()); - ret.insert("value", tag.value()); - return ret; -} - -Tag TagsHandler::unpackTag(const QVariantMap &tagMap) -{ - DeviceId deviceId = DeviceId(tagMap.value("deviceId").toString()); - RuleId ruleId = RuleId(tagMap.value("ruleId").toString()); - QString appId = tagMap.value("appId").toString(); - QString tagId = tagMap.value("tagId").toString(); - QString value = tagMap.value("value").toString(); - if (!deviceId.isNull()) { - return Tag(deviceId, appId, tagId, value); - } - return Tag(ruleId, appId, tagId, value); -} - QVariantMap TagsHandler::statusToReply(TagsStorage::TagError status) const { QVariantMap returns; diff --git a/libnymea-core/jsonrpc/tagshandler.h b/libnymea-core/jsonrpc/tagshandler.h index c8af320d..8d3c907c 100644 --- a/libnymea-core/jsonrpc/tagshandler.h +++ b/libnymea-core/jsonrpc/tagshandler.h @@ -50,9 +50,6 @@ private slots: void onTagValueChanged(const Tag &tag); private: - static QVariantMap packTag(const Tag &tag); - static Tag unpackTag(const QVariantMap &tagMap); - QVariantMap statusToReply(TagsStorage::TagError status) const; }; diff --git a/libnymea-core/logging/logentry.cpp b/libnymea-core/logging/logentry.cpp index c22eb2b9..290952ab 100644 --- a/libnymea-core/logging/logentry.cpp +++ b/libnymea-core/logging/logentry.cpp @@ -44,6 +44,11 @@ namespace nymeaserver { +LogEntry::LogEntry() +{ + +} + /*! Constructs a \l{LogEntry} with the given \a timestamp, \a level, \a source and \a errorCode.*/ LogEntry::LogEntry(QDateTime timestamp, Logging::LoggingLevel level, Logging::LoggingSource source, int errorCode): m_timestamp(timestamp), @@ -173,4 +178,19 @@ QDebug operator<<(QDebug dbg, const LogEntry &entry) return dbg.space(); } +LogEntries::LogEntries() +{ + +} + +LogEntries::LogEntries(const QList &other): QList(other) +{ + +} + +QVariant LogEntries::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + } diff --git a/libnymea-core/logging/logentry.h b/libnymea-core/logging/logentry.h index abb973b0..4561aa2c 100644 --- a/libnymea-core/logging/logentry.h +++ b/libnymea-core/logging/logentry.h @@ -39,13 +39,13 @@ class LogEntry Q_PROPERTY(Logging::LoggingSource source READ source) Q_PROPERTY(QUuid typeId READ typeId USER true) Q_PROPERTY(QUuid deviceId READ deviceId USER true) -// Q_PROPERTY(QString itemId READ itemId USER true) Q_PROPERTY(QVariant value READ value USER true) Q_PROPERTY(bool active READ active USER true) Q_PROPERTY(Logging::LoggingEventType eventType READ eventType USER true) Q_PROPERTY(QString errorCode READ errorCode USER true) public: + LogEntry(); LogEntry(QDateTime timestamp, Logging::LoggingLevel level, Logging::LoggingSource source, int errorCode = 0); LogEntry(Logging::LoggingLevel level, Logging::LoggingSource source, int errorCode = 0); LogEntry(Logging::LoggingSource source); @@ -92,8 +92,20 @@ private: int m_errorCode; }; +class LogEntries: QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + LogEntries(); + LogEntries(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; + QDebug operator<<(QDebug dbg, const LogEntry &entry); } +Q_DECLARE_METATYPE(nymeaserver::LogEntry) +Q_DECLARE_METATYPE(nymeaserver::LogEntries) #endif diff --git a/libnymea-core/nymeaconfiguration.h b/libnymea-core/nymeaconfiguration.h index aa24409b..eba54c09 100644 --- a/libnymea-core/nymeaconfiguration.h +++ b/libnymea-core/nymeaconfiguration.h @@ -32,7 +32,7 @@ namespace nymeaserver { class ServerConfiguration { Q_GADGET Q_PROPERTY(QString id MEMBER id) - Q_PROPERTY(QString address READ addressString) + Q_PROPERTY(QString address READ addressString WRITE setAddress) Q_PROPERTY(uint port MEMBER port) Q_PROPERTY(bool sslEnabled MEMBER sslEnabled) Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled) @@ -40,6 +40,7 @@ public: QString id; QHostAddress address; QString addressString() { return address.toString(); } + void setAddress(const QString &addressString) {address = QHostAddress(addressString); } uint port = 0; bool sslEnabled = true; bool authenticationEnabled = true; diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index eb382c48..7397cd74 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -799,7 +799,7 @@ void NymeaCore::gotEvent(const Event &event) // Set action params, depending on the event value foreach (RuleAction ruleAction, eventBasedActions) { - RuleActionParamList newParams; + RuleActionParams newParams; foreach (RuleActionParam ruleActionParam, ruleAction.ruleActionParams()) { // if this event param should be taken over in this action if (event.eventTypeId() == ruleActionParam.eventTypeId()) { diff --git a/libnymea-core/ruleengine/rule.cpp b/libnymea-core/ruleengine/rule.cpp index f025cb15..2e0259a7 100644 --- a/libnymea-core/ruleengine/rule.cpp +++ b/libnymea-core/ruleengine/rule.cpp @@ -250,4 +250,19 @@ QDebug operator<<(QDebug dbg, const Rule &rule) return dbg.space(); } +Rules::Rules() +{ + +} + +Rules::Rules(const QList &other): QList(other) +{ + +} + +QVariant Rules::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + } diff --git a/libnymea-core/ruleengine/rule.h b/libnymea-core/ruleengine/rule.h index dacf9559..cb3fbfd4 100644 --- a/libnymea-core/ruleengine/rule.h +++ b/libnymea-core/ruleengine/rule.h @@ -34,6 +34,18 @@ namespace nymeaserver { class Rule { + Q_GADGET + Q_PROPERTY(QUuid id READ id WRITE setId) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(bool active READ active) + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) + Q_PROPERTY(bool executable READ executable WRITE setExecutable) + Q_PROPERTY(EventDescriptors eventDescriptors READ eventDescriptors WRITE setEventDescriptors) + Q_PROPERTY(RuleActions actions READ actions WRITE setActions) + Q_PROPERTY(RuleActions exitActions READ exitActions WRITE setExitActions) + Q_PROPERTY(StateEvaluator stateEvaluator READ stateEvaluator WRITE setStateEvaluator) + Q_PROPERTY(TimeDescriptor timeDescriptor READ timeDescriptor WRITE setTimeDescriptor) + public: Rule(); @@ -94,8 +106,19 @@ private: bool m_executable; }; +class Rules: QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + Rules(); + Rules(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; + QDebug operator<<(QDebug dbg, const Rule &rule); } +Q_DECLARE_METATYPE(nymeaserver::Rules) #endif // RULE_H diff --git a/libnymea-core/ruleengine/ruleaction.cpp b/libnymea-core/ruleengine/ruleaction.cpp index 10b31d11..5995ed07 100644 --- a/libnymea-core/ruleengine/ruleaction.cpp +++ b/libnymea-core/ruleengine/ruleaction.cpp @@ -49,7 +49,7 @@ /*! Constructs a RuleAction with the given by \a actionTypeId, \a deviceId and \a params. * Use this to create a RuleAction for regular actions, that is, identifying the Action by deviceId and actionTypeId. */ -RuleAction::RuleAction(const ActionTypeId &actionTypeId, const DeviceId &deviceId, const RuleActionParamList ¶ms): +RuleAction::RuleAction(const ActionTypeId &actionTypeId, const DeviceId &deviceId, const RuleActionParams ¶ms): m_id(ActionId::createActionId()), m_deviceId(deviceId), m_actionTypeId(actionTypeId), @@ -61,7 +61,7 @@ RuleAction::RuleAction(const ActionTypeId &actionTypeId, const DeviceId &deviceI /*! Constructs a RuleAction with the given by \a interface and \a interfaceAction. * This will create an interface based RuleAction. Meaning, the Action is idenfified by an interface and and interfaceAction. */ -RuleAction::RuleAction(const QString &interface, const QString &interfaceAction, const RuleActionParamList ¶ms) : +RuleAction::RuleAction(const QString &interface, const QString &interfaceAction, const RuleActionParams ¶ms) : m_interface(interface), m_interfaceAction(interfaceAction), m_ruleActionParams(params) @@ -169,40 +169,65 @@ ActionTypeId RuleAction::actionTypeId() const return m_actionTypeId; } +void RuleAction::setActionTypeId(const ActionTypeId &actionTypeId) +{ + m_actionTypeId = actionTypeId; +} + /*! Returns the browserItemId of this RuleAction. */ QString RuleAction::browserItemId() const { return m_browserItemId; } +void RuleAction::setBrowserItemId(const QString &browserItemId) +{ + m_browserItemId = browserItemId; +} + /*! Returns the deviceId of this RuleAction. */ DeviceId RuleAction::deviceId() const { return m_deviceId; } +void RuleAction::setDeviceId(const DeviceId &deviceId) +{ + m_deviceId = deviceId; +} + /*! Returns the name of the interface associated with this RuleAction. */ QString RuleAction::interface() const { return m_interface; } +void RuleAction::setInterface(const QString &interface) +{ + m_interface = interface; +} + /*! Returns the name of the action of the associated interface. */ QString RuleAction::interfaceAction() const { return m_interfaceAction; } +void RuleAction::setInterfaceAction(const QString &interfaceAction) +{ + m_interfaceAction = interfaceAction; +} + /*! Returns the \l{RuleActionParamList} of this RuleAction. * \sa RuleActionParam, */ -RuleActionParamList RuleAction::ruleActionParams() const +RuleActionParams RuleAction::ruleActionParams() const { return m_ruleActionParams; } /*! Set the \l{RuleActionParamList} of this RuleAction to the given \a ruleActionParams. * \sa RuleActionParam, */ -void RuleAction::setRuleActionParams(const RuleActionParamList &ruleActionParams) +void RuleAction::setRuleActionParams(const RuleActionParams &ruleActionParams) { m_ruleActionParams = ruleActionParams; } @@ -260,3 +285,18 @@ QDebug operator<<(QDebug dbg, const QList &ruleActionList) } return dbg; } + +RuleActions::RuleActions() +{ + +} + +RuleActions::RuleActions(const QList &other): QList(other) +{ + +} + +QVariant RuleActions::get(int index) const +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea-core/ruleengine/ruleaction.h b/libnymea-core/ruleengine/ruleaction.h index d71b318a..f94fe2e8 100644 --- a/libnymea-core/ruleengine/ruleaction.h +++ b/libnymea-core/ruleengine/ruleaction.h @@ -31,14 +31,22 @@ class LIBNYMEA_EXPORT RuleAction { + Q_GADGET + Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId USER true) + Q_PROPERTY(QUuid actionTypeId READ actionTypeId WRITE setActionTypeId USER true) + Q_PROPERTY(QString interface READ interface WRITE setInterface USER true) + Q_PROPERTY(QString interfaceAction READ interfaceAction WRITE setInterfaceAction USER true) + Q_PROPERTY(QString browserItemId READ browserItemId WRITE setBrowserItemId USER true) + Q_PROPERTY(RuleActionParams ruleActionParams READ ruleActionParams WRITE setRuleActionParams USER true) + public: enum Type { TypeDevice, TypeInterface, TypeBrowser }; - explicit RuleAction(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId(), const RuleActionParamList ¶ms = RuleActionParamList()); - explicit RuleAction(const QString &interface, const QString &interfaceAction, const RuleActionParamList ¶ms = RuleActionParamList()); + explicit RuleAction(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId(), const RuleActionParams ¶ms = RuleActionParams()); + explicit RuleAction(const QString &interface, const QString &interfaceAction, const RuleActionParams ¶ms = RuleActionParams()); explicit RuleAction(const DeviceId &deviceId, const QString &browserItemId); RuleAction(const RuleAction &other); @@ -54,14 +62,22 @@ public: BrowserItemAction toBrowserItemAction() const; DeviceId deviceId() const; + void setDeviceId(const DeviceId &deviceId); + ActionTypeId actionTypeId() const; + void setActionTypeId(const ActionTypeId &actionTypeId); + QString browserItemId() const; + void setBrowserItemId(const QString &browserItemId); QString interface() const; - QString interfaceAction() const; + void setInterface(const QString &interface); - RuleActionParamList ruleActionParams() const; - void setRuleActionParams(const RuleActionParamList &ruleActionParams); + QString interfaceAction() const; + void setInterfaceAction(const QString &interfaceAction); + + RuleActionParams ruleActionParams() const; + void setRuleActionParams(const RuleActionParams &ruleActionParams); RuleActionParam ruleActionParam(const ParamTypeId &ruleActionParamTypeId) const; RuleActionParam ruleActionParam(const QString &ruleActionParamName) const; @@ -74,8 +90,20 @@ private: QString m_browserItemId; QString m_interface; QString m_interfaceAction; - RuleActionParamList m_ruleActionParams; + RuleActionParams m_ruleActionParams; }; +Q_DECLARE_METATYPE(RuleAction) + +class RuleActions: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + RuleActions(); + RuleActions(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; +Q_DECLARE_METATYPE(RuleActions) QDebug operator<<(QDebug dbg, const RuleAction &ruleAction); QDebug operator<<(QDebug dbg, const QList &ruleActionList); diff --git a/libnymea-core/ruleengine/ruleactionparam.cpp b/libnymea-core/ruleengine/ruleactionparam.cpp index 31c92b50..10728861 100644 --- a/libnymea-core/ruleengine/ruleactionparam.cpp +++ b/libnymea-core/ruleengine/ruleactionparam.cpp @@ -124,12 +124,22 @@ ParamTypeId RuleActionParam::paramTypeId() const return m_paramTypeId; } +void RuleActionParam::setParamTypeId(const ParamTypeId ¶mTypeId) +{ + m_paramTypeId = paramTypeId; +} + /*! Returns the name of this RuleActionParam. */ QString RuleActionParam::paramName() const { return m_paramName; } +void RuleActionParam::setParamName(const QString ¶mName) +{ + m_paramName = paramName; +} + /*! Returns the value of this RuleActionParam. */ QVariant RuleActionParam::value() const { @@ -238,13 +248,13 @@ QDebug operator<<(QDebug dbg, const RuleActionParam &ruleActionParam) */ /*! Returns true if this \l{RuleActionParamList} contains a \l{RuleActionParam} with the given \a ruleActionParamTypeId. */ -bool RuleActionParamList::hasParam(const ParamTypeId &ruleActionParamTypeId) const +bool RuleActionParams::hasParam(const ParamTypeId &ruleActionParamTypeId) const { return m_ids.contains(ruleActionParamTypeId); } /*! Returns true if this \l{RuleActionParamList} contains a \l{RuleActionParam} with the given \a ruleActionParamName. */ -bool RuleActionParamList::hasParam(const QString &ruleActionParamName) const +bool RuleActionParams::hasParam(const QString &ruleActionParamName) const { foreach (const RuleActionParam ¶m, *this) { if (param.paramName() == ruleActionParamName) { @@ -255,7 +265,7 @@ bool RuleActionParamList::hasParam(const QString &ruleActionParamName) const } /*! Returns the value of the \l{RuleActionParam} with the given \a ruleActionParamTypeId. */ -QVariant RuleActionParamList::paramValue(const ParamTypeId &ruleActionParamTypeId) const +QVariant RuleActionParams::paramValue(const ParamTypeId &ruleActionParamTypeId) const { foreach (const RuleActionParam ¶m, *this) { if (param.paramTypeId() == ruleActionParamTypeId) { @@ -267,7 +277,7 @@ QVariant RuleActionParamList::paramValue(const ParamTypeId &ruleActionParamTypeI } /*! Returns true if the \a value of the \l{RuleActionParam} with the given \a ruleActionParamTypeId could be set successfully. */ -bool RuleActionParamList::setParamValue(const ParamTypeId &ruleActionParamTypeId, const QVariant &value) +bool RuleActionParams::setParamValue(const ParamTypeId &ruleActionParamTypeId, const QVariant &value) { for (int i = 0; i < count(); i++) { if (this->operator [](i).paramTypeId() == ruleActionParamTypeId) { @@ -280,7 +290,7 @@ bool RuleActionParamList::setParamValue(const ParamTypeId &ruleActionParamTypeId } /*! Appends the given \a ruleActionParam to a RuleActionParamList. */ -RuleActionParamList RuleActionParamList::operator<<(const RuleActionParam &ruleActionParam) +RuleActionParams RuleActionParams::operator<<(const RuleActionParam &ruleActionParam) { this->append(ruleActionParam); m_ids.append(ruleActionParam.paramTypeId()); @@ -288,7 +298,7 @@ RuleActionParamList RuleActionParamList::operator<<(const RuleActionParam &ruleA } /*! Writes the ruleActionParam of the given \a ruleActionParams to \a dbg. */ -QDebug operator<<(QDebug dbg, const RuleActionParamList &ruleActionParams) +QDebug operator<<(QDebug dbg, const RuleActionParams &ruleActionParams) { dbg.nospace() << "RuleActionParamList (count:" << ruleActionParams.count() << ")" << endl; for (int i = 0; i < ruleActionParams.count(); i++ ) { @@ -297,3 +307,8 @@ QDebug operator<<(QDebug dbg, const RuleActionParamList &ruleActionParams) return dbg.space(); } + +QVariant RuleActionParams::get(int index) const +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea-core/ruleengine/ruleactionparam.h b/libnymea-core/ruleengine/ruleactionparam.h index 5608844c..5ed19acd 100644 --- a/libnymea-core/ruleengine/ruleactionparam.h +++ b/libnymea-core/ruleengine/ruleactionparam.h @@ -34,6 +34,15 @@ class LIBNYMEA_EXPORT RuleActionParam { + Q_GADGET + Q_PROPERTY(QUuid paramTypeId READ paramTypeId WRITE setParamTypeId USER true) + Q_PROPERTY(QString paramName READ paramName WRITE setParamName USER true) + Q_PROPERTY(QVariant value READ value WRITE setValue USER true) + Q_PROPERTY(QUuid eventTypeId READ eventTypeId WRITE setEventTypeId USER true) + Q_PROPERTY(QUuid eventParamTypeId READ eventParamTypeId WRITE setEventParamTypeId USER true) + Q_PROPERTY(QUuid stateDeviceId READ stateDeviceId WRITE setStateDeviceId USER true) + Q_PROPERTY(QUuid stateTypeId READ stateTypeId WRITE setStateTypeId USER true) + public: RuleActionParam(const Param ¶m = Param()); RuleActionParam(const ParamTypeId ¶mTypeId, const QVariant &value = QVariant()); @@ -44,7 +53,10 @@ public: RuleActionParam(const QString ¶mName, const DeviceId &stateDeviceId, const StateTypeId &stateTypeId); ParamTypeId paramTypeId() const; + void setParamTypeId(const ParamTypeId ¶mTypeId); + QString paramName() const; + void setParamName(const QString ¶mName); bool isValid() const; bool isValueBased() const; @@ -81,19 +93,22 @@ private: Q_DECLARE_METATYPE(RuleActionParam) QDebug operator<<(QDebug dbg, const RuleActionParam &ruleActionParam); -class LIBNYMEA_EXPORT RuleActionParamList: public QList +class LIBNYMEA_EXPORT RuleActionParams: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: bool hasParam(const ParamTypeId &ruleActionParamTypeId) const; bool hasParam(const QString &ruleActionParamName) const; + Q_INVOKABLE QVariant get(int index) const; QVariant paramValue(const ParamTypeId &ruleActionParamName) const; bool setParamValue(const ParamTypeId &ruleActionParamTypeId, const QVariant &value); - RuleActionParamList operator<<(const RuleActionParam &ruleActionParam); + RuleActionParams operator<<(const RuleActionParam &ruleActionParam); private: QList m_ids; }; -QDebug operator<<(QDebug dbg, const RuleActionParamList &ruleActionParams); +QDebug operator<<(QDebug dbg, const RuleActionParams &ruleActionParams); #endif // RULEACTIONPARAM_H diff --git a/libnymea-core/ruleengine/ruleengine.cpp b/libnymea-core/ruleengine/ruleengine.cpp index 72f98733..564e7fea 100644 --- a/libnymea-core/ruleengine/ruleengine.cpp +++ b/libnymea-core/ruleengine/ruleengine.cpp @@ -1264,7 +1264,7 @@ QList RuleEngine::loadRuleActions(NymeaSettings *settings) foreach (const QString &actionNumber, settings->childGroups()) { settings->beginGroup(actionNumber); - RuleActionParamList params; + RuleActionParams params; foreach (QString paramTypeIdString, settings->childGroups()) { if (paramTypeIdString.startsWith("RuleActionParam-")) { settings->beginGroup(paramTypeIdString); @@ -1384,7 +1384,7 @@ void RuleEngine::init() settings.beginGroup(childGroup); TimeEventItem timeEventItem; - timeEventItem.setDateTime(settings.value("dateTime", 0).toUInt()); + timeEventItem.setDateTime(QDateTime::fromTime_t(settings.value("dateTime", 0).toUInt())); timeEventItem.setTime(QTime::fromString(settings.value("time").toString())); QList weekDays; diff --git a/libnymea-core/ruleengine/stateevaluator.cpp b/libnymea-core/ruleengine/stateevaluator.cpp index 4a9a7d90..c6a7f623 100644 --- a/libnymea-core/ruleengine/stateevaluator.cpp +++ b/libnymea-core/ruleengine/stateevaluator.cpp @@ -63,6 +63,11 @@ StateDescriptor StateEvaluator::stateDescriptor() const return m_stateDescriptor; } +void StateEvaluator::setStateDescriptor(const StateDescriptor &stateDescriptor) +{ + m_stateDescriptor = stateDescriptor; +} + /*! Returns the list of child \l {StateEvaluator}{StateEvaluators} of this \l StateEvaluator. */ QList StateEvaluator::childEvaluators() const { @@ -372,4 +377,19 @@ QDebug operator<<(QDebug dbg, const StateEvaluator &stateEvaluator) return dbg; } +StateEvaluators::StateEvaluators() +{ + +} + +StateEvaluators::StateEvaluators(const QList &other): QList(other) +{ + +} + +QVariant StateEvaluators::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + } diff --git a/libnymea-core/ruleengine/stateevaluator.h b/libnymea-core/ruleengine/stateevaluator.h index 273b98b9..434a22a3 100644 --- a/libnymea-core/ruleengine/stateevaluator.h +++ b/libnymea-core/ruleengine/stateevaluator.h @@ -33,11 +33,16 @@ namespace nymeaserver { class StateEvaluator { + Q_GADGET + Q_PROPERTY(StateDescriptor stateDescriptor READ stateDescriptor WRITE setStateDescriptor USER true) + Q_PROPERTY(StateEvaluators childEvaluators READ childEvaluators WRITE setChildEvaluators USER true) + Q_PROPERTY(Types::StateOperator operator READ operatorType WRITE setOperatorType USER true) public: StateEvaluator(const StateDescriptor &stateDescriptor); StateEvaluator(QList childEvaluators = QList(), Types::StateOperator stateOperator = Types::StateOperatorAnd); StateDescriptor stateDescriptor() const; + void setStateDescriptor(const StateDescriptor &stateDescriptor); QList childEvaluators() const; void setChildEvaluators(const QList &childEvaluators); @@ -65,8 +70,19 @@ private: Types::StateOperator m_operatorType; }; +class StateEvaluators: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + StateEvaluators(); + StateEvaluators(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; + QDebug operator<<(QDebug dbg, const StateEvaluator &stateEvaluator); } +Q_DECLARE_METATYPE(nymeaserver::StateEvaluators) #endif // STATEEVALUATOR_H diff --git a/libnymea-core/tagging/tag.cpp b/libnymea-core/tagging/tag.cpp index a900ab92..68945958 100644 --- a/libnymea-core/tagging/tag.cpp +++ b/libnymea-core/tagging/tag.cpp @@ -24,6 +24,11 @@ namespace nymeaserver { +Tag::Tag() +{ + +} + Tag::Tag(const DeviceId &deviceId, const QString &appId, const QString &tagId, const QString &value): m_deviceId(deviceId), m_appId(appId), @@ -48,21 +53,41 @@ DeviceId Tag::deviceId() const return m_deviceId; } +void Tag::setDeviceId(const DeviceId &deviceId) +{ + m_deviceId = deviceId; +} + RuleId Tag::ruleId() const { return m_ruleId; } +void Tag::setRuleId(const RuleId &ruleId) +{ + m_ruleId = ruleId; +} + QString Tag::appId() const { return m_appId; } +void Tag::setAppId(const QString &appId) +{ + m_appId = appId; +} + QString Tag::tagId() const { return m_tagId; } +void Tag::setTagId(const QString &tagId) +{ + m_tagId = tagId; +} + QString Tag::value() const { return m_value; @@ -92,4 +117,19 @@ QDebug operator<<(QDebug dbg, const Tag &tag) return dbg; } +Tags::Tags() +{ + +} + +Tags::Tags(const QList &other): QList(other) +{ + +} + +QVariant Tags::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + } diff --git a/libnymea-core/tagging/tag.h b/libnymea-core/tagging/tag.h index 78e95b51..a58ed1fb 100644 --- a/libnymea-core/tagging/tag.h +++ b/libnymea-core/tagging/tag.h @@ -24,19 +24,34 @@ #include "typeutils.h" #include +#include namespace nymeaserver { class Tag { + Q_GADGET + Q_PROPERTY(QString appId READ appId WRITE setAppId) + Q_PROPERTY(QString tagId READ tagId WRITE setTagId) + Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId USER true) + Q_PROPERTY(QUuid ruleId READ ruleId WRITE setRuleId USER true) + Q_PROPERTY(QString value READ value WRITE setValue USER true) public: + Tag(); Tag(const DeviceId &deviceId, const QString &appId, const QString &tagId, const QString &value); Tag(const RuleId &ruleId, const QString &appId, const QString &tagId, const QString &value); DeviceId deviceId() const; + void setDeviceId(const DeviceId &deviceId); + RuleId ruleId() const; + void setRuleId(const RuleId &ruleId); + QString appId() const; + void setAppId(const QString &appId); + QString tagId() const; + void setTagId(const QString &tagId); QString value() const; void setValue(const QString &value); @@ -51,7 +66,20 @@ private: QString m_value; }; +class Tags: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + Tags(); + Tags(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; + QDebug operator<<(QDebug dbg, const Tag &tag); } +Q_DECLARE_METATYPE(nymeaserver::Tag) +Q_DECLARE_METATYPE(nymeaserver::Tags) + #endif // TAG_H diff --git a/libnymea-core/usermanager/tokeninfo.h b/libnymea-core/usermanager/tokeninfo.h index ed24200d..ccc2b7c6 100644 --- a/libnymea-core/usermanager/tokeninfo.h +++ b/libnymea-core/usermanager/tokeninfo.h @@ -32,7 +32,7 @@ class TokenInfo Q_GADGET Q_PROPERTY(QUuid id READ id) Q_PROPERTY(QString username READ username) - Q_PROPERTY(QDateTime createionTime READ creationTime) + Q_PROPERTY(QDateTime creationTime READ creationTime) Q_PROPERTY(QString deviveName READ deviceName) public: diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 656d9e6f..0450e7cf 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -3,6 +3,7 @@ #include "loggingcategories.h" #include +#include JsonHandler::JsonHandler(QObject *parent) : QObject(parent) { @@ -34,12 +35,6 @@ QVariantMap JsonHandler::jsonNotifications() const return m_notifications; } -//QString JsonHandler::basicTypeName(JsonHandler::BasicType type) -//{ -// QMetaEnum metaEnum = QMetaEnum::fromType(); -// return metaEnum.valueToKey(type); -//} - QString JsonHandler::objectRef(const QString &objectName) { return "$ref:" + objectName; @@ -220,9 +215,13 @@ QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) con // Standard properties, QString, int etc... If it's not optional, or if it's not empty, pack it up if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { - ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); + QVariant variant = metaProperty.readOnGadget(value); + // Special treatment for QDateTime (converting to time_t) + if (metaProperty.type() == QVariant::DateTime) { + variant = variant.toDateTime().toTime_t(); + } + ret.insert(metaProperty.name(), variant); } - } return ret; } diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index 289df8a7..12398611 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "jsonreply.h" @@ -41,6 +42,7 @@ public: template static QString enumRef(); + template static QString objectRef(); static QString objectRef(const QString &objectName); template static QString enumValueName(T value); @@ -127,7 +129,9 @@ void JsonHandler::registerObject() if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { typeName = QString("$ref:BasicType"); } else if (QString(metaProperty.typeName()).startsWith("QList")) { - typeName = QVariantList() << "$ref:" + QString(metaProperty.typeName()).remove("QList<").remove(">"); + QString elementType = QString(metaProperty.typeName()).remove("QList<").remove(">"); + QVariant::Type variantType = QVariant::nameToType(elementType.toUtf8()); + typeName = QVariantList() << enumValueName(variantTypeToBasicType(variantType)); } else { typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); } @@ -152,22 +156,16 @@ void JsonHandler::registerObject() registerObject(); QMetaObject metaObject = ObjectType::staticMetaObject; QMetaObject listMetaObject = ListType::staticMetaObject; - m_objects.insert(listMetaObject.className(), QVariantList() << QVariant(QString("$ref:%1").arg(metaObject.className()))); - m_metaObjects.insert(listMetaObject.className(), listMetaObject); - m_listMetaObjects.insert(listMetaObject.className(), listMetaObject); - m_listEntryTypes.insert(listMetaObject.className(), metaObject.className()); - Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", "List type does not implement \"count\" property!"); - Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", "List type does not implement \"Q_INVOKABLE QVariant get(int index)\" method!"); + QString listTypeName = QString(listMetaObject.className()).split("::").last(); + QString objectTypeName = QString(metaObject.className()).split("::").last(); + m_objects.insert(listTypeName, QVariantList() << QVariant(QString("$ref:%1").arg(objectTypeName))); + m_metaObjects.insert(listTypeName, listMetaObject); + m_listMetaObjects.insert(listTypeName, listMetaObject); + m_listEntryTypes.insert(listTypeName, objectTypeName); + Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", QString("List type %1 does not implement \"count\" property!").arg(listTypeName).toUtf8()); + Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE QVariant get(int index)\" method!").arg(listTypeName).toUtf8()); } -//template -//void JsonHandler::registerList() -//{ -// QMetaObject metaObject = T::staticMetaObject; -// m_lists.insert(metaObject.className(), metaObject); -// m_objects.insert(metaObject.classInfo(), QVariantList() << ) -//} - template QString JsonHandler::enumRef() { @@ -175,6 +173,13 @@ QString JsonHandler::enumRef() return QString("$ref:%1").arg(metaEnum.name()); } +template +QString JsonHandler::objectRef() +{ + QMetaObject metaObject = T::staticMetaObject; + return QString("$ref:%1").arg(QString(metaObject.className()).split("::").last()); +} + template QString JsonHandler::enumValueName(T value) { @@ -213,7 +218,12 @@ T JsonHandler::unpack(const QVariantMap &map) const Q_ASSERT_X(map.contains(metaProperty.name()), this->metaObject()->className(), QString("Missing property %1 in map.").arg(metaProperty.name()).toUtf8()); } if (map.contains(metaProperty.name())) { - metaProperty.writeOnGadget(&ret, map.value(metaProperty.name())); + // Special treatment for QDateTime (convert from time_t) + QVariant variant = map.value(metaProperty.name()); + if (metaProperty.type() == QVariant::DateTime) { + variant = QDateTime::fromTime_t(variant.toUInt()); + } + metaProperty.writeOnGadget(&ret, variant); } } return ret; diff --git a/libnymea/jsonrpc/jsonrpcserver.h b/libnymea/jsonrpc/jsonrpcserver.h index b83c3a47..aeeddc4e 100644 --- a/libnymea/jsonrpc/jsonrpcserver.h +++ b/libnymea/jsonrpc/jsonrpcserver.h @@ -9,7 +9,7 @@ public: explicit JsonRPCServer() = default; virtual ~JsonRPCServer() = default; - virtual bool registerHandler(JsonHandler *handler) = 0; + virtual bool registerExperienceHandler(JsonHandler *handler, int majorVersion, int minorVersion) = 0; }; diff --git a/libnymea/platform/package.cpp b/libnymea/platform/package.cpp index 195205ec..fff64f53 100644 --- a/libnymea/platform/package.cpp +++ b/libnymea/platform/package.cpp @@ -129,3 +129,18 @@ bool Package::operator!=(const Package &other) const { return !operator==(other); } + +Packages::Packages() +{ + +} + +Packages::Packages(const QList &other): QList(other) +{ + +} + +QVariant Packages::get(int index) const +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/platform/package.h b/libnymea/platform/package.h index a0c90ab1..9e891008 100644 --- a/libnymea/platform/package.h +++ b/libnymea/platform/package.h @@ -24,9 +24,23 @@ #define PACKAGE_H #include +#include +#include +#include class Package { + Q_GADGET + Q_PROPERTY(QString id READ packageId) + Q_PROPERTY(QString displayName READ displayName) + Q_PROPERTY(QString summary READ summary) + Q_PROPERTY(QString installedVersion READ installedVersion) + Q_PROPERTY(QString candidateVersion READ candidateVersion) + Q_PROPERTY(QString changelog READ changelog) + Q_PROPERTY(bool updateAvailable READ updateAvailable) + Q_PROPERTY(bool rollbackAvailable READ rollbackAvailable) + Q_PROPERTY(bool canRemove READ canRemove) + public: explicit Package(const QString &packageId = QString(), const QString &displayName = QString(), const QString &installedVersion = QString(), const QString &candidateVersion = QString(), const QString &changelog = QString()); @@ -69,5 +83,17 @@ private: bool m_rollbackAvailable = false; bool m_canRemove = false; }; +Q_DECLARE_METATYPE(Package) + +class Packages: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + Packages(); + Packages(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; +Q_DECLARE_METATYPE(Packages) #endif // PACKAGE_H diff --git a/libnymea/platform/repository.cpp b/libnymea/platform/repository.cpp index c3eeac53..d3b1fc5f 100644 --- a/libnymea/platform/repository.cpp +++ b/libnymea/platform/repository.cpp @@ -54,3 +54,18 @@ void Repository::setEnabled(bool enabled) { m_enabled = enabled; } + +Repositories::Repositories() +{ + +} + +Repositories::Repositories(const QList &other): QList(other) +{ + +} + +QVariant Repositories::get(int index) const +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/platform/repository.h b/libnymea/platform/repository.h index 5ec2b86b..798331b5 100644 --- a/libnymea/platform/repository.h +++ b/libnymea/platform/repository.h @@ -24,9 +24,14 @@ #define REPOSITORY_H #include +#include class Repository { + Q_GADGET + Q_PROPERTY(QString id READ id) + Q_PROPERTY(QString displayName READ displayName) + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) public: Repository(); Repository(const QString &id, const QString &displayName, bool enabled); @@ -42,5 +47,16 @@ private: QString m_displayName; bool m_enabled = false; }; +Q_DECLARE_METATYPE(Repository) + +class Repositories: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + Repositories(); + Repositories(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; #endif // REPOSITORY_H diff --git a/libnymea/time/repeatingoption.cpp b/libnymea/time/repeatingoption.cpp index 58807d9f..6dea237f 100644 --- a/libnymea/time/repeatingoption.cpp +++ b/libnymea/time/repeatingoption.cpp @@ -105,18 +105,33 @@ RepeatingOption::RepeatingMode RepeatingOption::mode() const return m_mode; } +void RepeatingOption::setMode(RepeatingOption::RepeatingMode mode) +{ + m_mode = mode; +} + /*! Returns the list of week days on which this \l{RepeatingOption} should be valid. */ QList RepeatingOption::weekDays() const { return m_weekDays; } +void RepeatingOption::setWeekDays(const QList &weekDays) +{ + m_weekDays = weekDays; +} + /*! Returns the list of month days on which this \l{RepeatingOption} should be valid. */ QList RepeatingOption::monthDays() const { return m_monthDays; } +void RepeatingOption::setMonthDays(const QList &monthDays) +{ + m_monthDays = monthDays; +} + /*! Returns true if this \l{RepeatingOption} is empty. */ bool RepeatingOption::isEmtpy() const { diff --git a/libnymea/time/repeatingoption.h b/libnymea/time/repeatingoption.h index 85390a11..3af9b6c1 100644 --- a/libnymea/time/repeatingoption.h +++ b/libnymea/time/repeatingoption.h @@ -29,7 +29,9 @@ class QDateTime; class RepeatingOption { Q_GADGET - + Q_PROPERTY(RepeatingMode mode READ mode WRITE setMode) + Q_PROPERTY(QList weekDays READ weekDays WRITE setWeekDays USER true) + Q_PROPERTY(QList monthDays READ monthDays WRITE setMonthDays USER true) public: enum RepeatingMode { RepeatingModeNone, @@ -45,9 +47,13 @@ public: RepeatingOption(const RepeatingMode &mode, const QList &weekDays = QList(), const QList &monthDays = QList()); RepeatingMode mode() const; + void setMode(RepeatingMode mode); QList weekDays() const; + void setWeekDays(const QList &weekDays); + QList monthDays() const; + void setMonthDays(const QList &monthDays); bool isEmtpy() const; bool isValid() const; diff --git a/libnymea/time/timedescriptor.h b/libnymea/time/timedescriptor.h index 0da0c0a7..c7e0b898 100644 --- a/libnymea/time/timedescriptor.h +++ b/libnymea/time/timedescriptor.h @@ -26,6 +26,9 @@ class TimeDescriptor { + Q_GADGET + Q_PROPERTY(TimeEventItems timeEventItems READ timeEventItems WRITE setTimeEventItems USER true) + Q_PROPERTY(CalendarItems calendarItems READ calendarItems WRITE setCalendarItems USER true) public: explicit TimeDescriptor(); diff --git a/libnymea/time/timeeventitem.cpp b/libnymea/time/timeeventitem.cpp index 408b79a8..93c793c9 100644 --- a/libnymea/time/timeeventitem.cpp +++ b/libnymea/time/timeeventitem.cpp @@ -46,9 +46,9 @@ QDateTime TimeEventItem::dateTime() const } /*! Sets the dateTime of this \l{TimeEventItem} to the given \a timeStamp. */ -void TimeEventItem::setDateTime(const uint &timeStamp) +void TimeEventItem::setDateTime(const QDateTime &dateTime) { - m_dateTime = QDateTime::fromTime_t(timeStamp); + m_dateTime = dateTime; } /*! Returns the time of this \l{TimeEventItem}. */ @@ -139,3 +139,18 @@ QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem) return dbg; } + +TimeEventItems::TimeEventItems() +{ + +} + +TimeEventItems::TimeEventItems(const QList &other): QList(other) +{ + +} + +QVariant TimeEventItems::get(int index) const +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/time/timeeventitem.h b/libnymea/time/timeeventitem.h index 90b8819e..94d31515 100644 --- a/libnymea/time/timeeventitem.h +++ b/libnymea/time/timeeventitem.h @@ -22,16 +22,21 @@ #define TIMEEVENTITEM_H #include +#include #include "repeatingoption.h" class TimeEventItem { + Q_GADGET + Q_PROPERTY(QDateTime datetime READ dateTime WRITE setDateTime USER true) + Q_PROPERTY(QTime time READ time WRITE setTime USER true) + Q_PROPERTY(RepeatingOption repeating READ repeatingOption WRITE setRepeatingOption USER true) public: TimeEventItem(); QDateTime dateTime() const; - void setDateTime(const uint &timeStamp); + void setDateTime(const QDateTime &dateTime); QTime time() const; void setTime(const QTime &time); @@ -51,6 +56,18 @@ private: RepeatingOption m_repeatingOption; }; +Q_DECLARE_METATYPE(TimeEventItem) + +class TimeEventItems: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + TimeEventItems(); + TimeEventItems(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; +Q_DECLARE_METATYPE(TimeEventItems) QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem); diff --git a/libnymea/types/eventdescriptor.cpp b/libnymea/types/eventdescriptor.cpp index f0a2b117..69cbc35d 100644 --- a/libnymea/types/eventdescriptor.cpp +++ b/libnymea/types/eventdescriptor.cpp @@ -89,24 +89,44 @@ EventTypeId EventDescriptor::eventTypeId() const return m_eventTypeId; } +void EventDescriptor::setEventTypeId(const EventTypeId &eventTypeId) +{ + m_eventTypeId = eventTypeId; +} + /*! Returns the id of the \l{Device} associated with this Event. */ DeviceId EventDescriptor::deviceId() const { return m_deviceId; } +void EventDescriptor::setDeviceId(const DeviceId &deviceId) +{ + m_deviceId = deviceId; +} + /*! Returns the interface associated with this EventDescriptor. */ QString EventDescriptor::interface() const { return m_interface; } +void EventDescriptor::setInterface(const QString &interface) +{ + m_interface = interface; +} + /*! Returns the interface's event name associated with this EventDescriptor.*/ QString EventDescriptor::interfaceEvent() const { return m_interfaceEvent; } +void EventDescriptor::setInterfaceEvent(const QString &interfaceEvent) +{ + m_interfaceEvent = interfaceEvent; +} + /*! Returns the parameters of this Event. */ QList EventDescriptor::paramDescriptors() const { @@ -169,3 +189,18 @@ QDebug operator<<(QDebug dbg, const QList &eventDescriptors) return dbg; } + +EventDescriptors::EventDescriptors() +{ + +} + +EventDescriptors::EventDescriptors(const QList &other): QList(other) +{ + +} + +QVariant EventDescriptors::get(int index) const +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/types/eventdescriptor.h b/libnymea/types/eventdescriptor.h index 97e98f79..5d032f39 100644 --- a/libnymea/types/eventdescriptor.h +++ b/libnymea/types/eventdescriptor.h @@ -35,6 +35,12 @@ class LIBNYMEA_EXPORT EventDescriptor { + Q_GADGET + Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId USER true) + Q_PROPERTY(QUuid eventTypeId READ eventTypeId WRITE setEventTypeId USER true) + Q_PROPERTY(QString interface READ interface WRITE setInterface USER true) + Q_PROPERTY(QString interfaceEvent READ interfaceEvent WRITE setInterfaceEvent USER true) + Q_PROPERTY(ParamDescriptors paramDescriptors READ paramDescriptors WRITE setParamDescriptors USER true) public: enum Type { TypeDevice, @@ -49,10 +55,16 @@ public: bool isValid() const; EventTypeId eventTypeId() const; + void setEventTypeId(const EventTypeId &eventTypeId); + DeviceId deviceId() const; + void setDeviceId(const DeviceId &deviceId); QString interface() const; + void setInterface(const QString &interface); + QString interfaceEvent() const; + void setInterfaceEvent(const QString &interfaceEvent); QList paramDescriptors() const; void setParamDescriptors(const QList ¶mDescriptors); @@ -67,6 +79,19 @@ private: QString m_interfaceEvent; QList m_paramDescriptors; }; +Q_DECLARE_METATYPE(EventDescriptor) + +class EventDescriptors: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + EventDescriptors(); + EventDescriptors(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; +Q_DECLARE_METATYPE(EventDescriptors) + QDebug operator<<(QDebug dbg, const EventDescriptor &eventDescriptor); QDebug operator<<(QDebug dbg, const QList &eventDescriptors); diff --git a/libnymea/types/param.h b/libnymea/types/param.h index 9b180054..036b1fd2 100644 --- a/libnymea/types/param.h +++ b/libnymea/types/param.h @@ -33,7 +33,7 @@ class LIBNYMEA_EXPORT Param { Q_GADGET - Q_PROPERTY(QUuid paramTypeId READ paramTypeId) + Q_PROPERTY(QUuid paramTypeId READ paramTypeId USER true) Q_PROPERTY(QVariant value READ value WRITE setValue) public: Param(const ParamTypeId ¶mTypeId = ParamTypeId(), const QVariant &value = QVariant()); diff --git a/libnymea/types/paramdescriptor.cpp b/libnymea/types/paramdescriptor.cpp index 86a569c0..69679ab4 100644 --- a/libnymea/types/paramdescriptor.cpp +++ b/libnymea/types/paramdescriptor.cpp @@ -62,6 +62,12 @@ QString ParamDescriptor::paramName() const return m_paramName; } +/*! Sets the param name of this ParamDescriptor. */ +void ParamDescriptor::setParamName(const QString ¶mName) +{ + m_paramName = paramName; +} + /*! Returns the ValueOperator of this ParamDescriptor. */ Types::ValueOperator ParamDescriptor::operatorType() const { @@ -80,3 +86,18 @@ QDebug operator<<(QDebug dbg, const ParamDescriptor ¶mDescriptor) dbg.nospace() << "ParamDescriptor(ParamTypeId: " << paramDescriptor.paramTypeId().toString() << ", Name:" << paramDescriptor.paramName() << ", Value:" << paramDescriptor.value() << ")" << endl; return dbg; } + +ParamDescriptors::ParamDescriptors() +{ + +} + +ParamDescriptors::ParamDescriptors(const QList &other): QList(other) +{ + +} + +QVariant ParamDescriptors::get(int index) const +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/types/paramdescriptor.h b/libnymea/types/paramdescriptor.h index 0c038069..ecfcb564 100644 --- a/libnymea/types/paramdescriptor.h +++ b/libnymea/types/paramdescriptor.h @@ -31,11 +31,17 @@ class LIBNYMEA_EXPORT ParamDescriptor : public Param { + Q_GADGET + Q_PROPERTY(QString paramName READ paramName WRITE setParamName USER true) + Q_PROPERTY(Types::ValueOperator operator READ operatorType WRITE setOperatorType) public: + ParamDescriptor() = default; ParamDescriptor(const ParamTypeId ¶mTypeId, const QVariant &value = QVariant()); ParamDescriptor(const QString ¶mName, const QVariant &value = QVariant()); QString paramName() const; + void setParamName(const QString ¶mName); + Types::ValueOperator operatorType() const; void setOperatorType(Types::ValueOperator operatorType); @@ -43,6 +49,18 @@ private: QString m_paramName; Types::ValueOperator m_operatorType; }; +Q_DECLARE_METATYPE(ParamDescriptor) + +class LIBNYMEA_EXPORT ParamDescriptors: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + ParamDescriptors(); + ParamDescriptors(const QList &other); + Q_INVOKABLE QVariant get(int index) const; +}; +Q_DECLARE_METATYPE(ParamDescriptors) QDebug operator<<(QDebug dbg, const ParamDescriptor ¶mDescriptor); diff --git a/libnymea/types/statedescriptor.cpp b/libnymea/types/statedescriptor.cpp index 29b70aac..ece565d4 100644 --- a/libnymea/types/statedescriptor.cpp +++ b/libnymea/types/statedescriptor.cpp @@ -85,36 +85,66 @@ StateTypeId StateDescriptor::stateTypeId() const return m_stateTypeId; } +void StateDescriptor::setStateTypeId(const StateTypeId &stateTypeId) +{ + m_stateTypeId = stateTypeId; +} + /*! Returns the DeviceId of this \l{State}.*/ DeviceId StateDescriptor::deviceId() const { return m_deviceId; } +void StateDescriptor::setDeviceId(const DeviceId &deviceId) +{ + m_deviceId = deviceId; +} + /*! Returns the interface for this \{StateDescriptor}.*/ QString StateDescriptor::interface() const { return m_interface; } +void StateDescriptor::setInterface(const QString &interface) +{ + m_interface = interface; +} + /*! Returns the interface state's name for this \{StateDescriptor}.*/ QString StateDescriptor::interfaceState() const { return m_interfaceState; } +void StateDescriptor::setInterfaceState(const QString &interfaceState) +{ + m_interfaceState = interfaceState; +} + /*! Returns the Value of this \l{State}.*/ QVariant StateDescriptor::stateValue() const { return m_stateValue; } +void StateDescriptor::setStateValue(const QVariant &value) +{ + m_stateValue = value; +} + /*! Returns the ValueOperator of this \l{State}.*/ Types::ValueOperator StateDescriptor::operatorType() const { return m_operatorType; } +void StateDescriptor::setOperatorType(Types::ValueOperator opertatorType) +{ + m_operatorType = opertatorType; +} + /*! Compare this StateDescriptor to \a other. * StateDescriptors are equal (returns true) if stateTypeId, stateValue and operatorType match. */ bool StateDescriptor::operator ==(const StateDescriptor &other) const diff --git a/libnymea/types/statedescriptor.h b/libnymea/types/statedescriptor.h index e53034dd..83f00250 100644 --- a/libnymea/types/statedescriptor.h +++ b/libnymea/types/statedescriptor.h @@ -36,6 +36,13 @@ class LIBNYMEA_EXPORT StateDescriptor { + Q_GADGET + Q_PROPERTY(QUuid stateTypeId READ stateTypeId WRITE setStateTypeId USER true) + Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId USER true) + Q_PROPERTY(QString interface READ interface WRITE setInterface USER true) + Q_PROPERTY(QString interfaceState READ interfaceState WRITE setInterfaceState USER true) + Q_PROPERTY(QVariant value READ stateValue WRITE setStateValue) + Q_PROPERTY(Types::ValueOperator operator READ operatorType WRITE setOperatorType) public: enum Type { TypeDevice, @@ -49,13 +56,22 @@ public: Type type() const; StateTypeId stateTypeId() const; + void setStateTypeId(const StateTypeId &stateTypeId); + DeviceId deviceId() const; + void setDeviceId(const DeviceId &deviceId); QString interface() const; + void setInterface(const QString &interface); + QString interfaceState() const; + void setInterfaceState(const QString &interfaceState); QVariant stateValue() const; + void setStateValue(const QVariant &value); + Types::ValueOperator operatorType() const; + void setOperatorType(Types::ValueOperator opertatorType); bool isValid() const; diff --git a/nymea.pri b/nymea.pri index 54a66bca..094a6ce7 100644 --- a/nymea.pri +++ b/nymea.pri @@ -2,9 +2,9 @@ NYMEA_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"') # define protocol versions -JSON_PROTOCOL_VERSION_MAJOR=3 -JSON_PROTOCOL_VERSION_MINOR=2 -LIBNYMEA_API_VERSION_MAJOR=3 +JSON_PROTOCOL_VERSION_MAJOR=4 +JSON_PROTOCOL_VERSION_MINOR=0 +LIBNYMEA_API_VERSION_MAJOR=4 LIBNYMEA_API_VERSION_MINOR=0 LIBNYMEA_API_VERSION_PATCH=0 diff --git a/tests/auto/devices/testdevices.cpp b/tests/auto/devices/testdevices.cpp index bfca2cea..caf121a9 100644 --- a/tests/auto/devices/testdevices.cpp +++ b/tests/auto/devices/testdevices.cpp @@ -291,7 +291,7 @@ void TestDevices::verifyInterfaces() QVariantMap mockDevice; foreach (const QVariant &deviceClass, supportedDevices) { - if (deviceClass.toMap().value("id") == mockDeviceClassId) { + if (deviceClass.toMap().value("id").toUuid() == mockDeviceClassId) { mockDevice = deviceClass.toMap(); } } @@ -312,6 +312,7 @@ void TestDevices::addConfiguredDevice_data() { QTest::addColumn("deviceClassId"); QTest::addColumn("deviceParams"); + QTest::addColumn("jsonValidation"); QTest::addColumn("deviceError"); QVariantMap httpportParam; @@ -327,29 +328,29 @@ void TestDevices::addConfiguredDevice_data() QVariantList deviceParams; deviceParams.clear(); deviceParams << httpportParam; - QTest::newRow("User, JustAdd") << mockDeviceClassId << deviceParams << Device::DeviceErrorNoError; + QTest::newRow("User, JustAdd") << mockDeviceClassId << deviceParams << true << Device::DeviceErrorNoError; deviceParams.clear(); deviceParams << httpportParam << asyncParam; - QTest::newRow("User, JustAdd, Async") << mockDeviceClassId << deviceParams << Device::DeviceErrorNoError; - QTest::newRow("Invalid DeviceClassId") << DeviceClassId::createDeviceClassId() << deviceParams << Device::DeviceErrorDeviceClassNotFound; + QTest::newRow("User, JustAdd, Async") << mockDeviceClassId << deviceParams << true << Device::DeviceErrorNoError; + QTest::newRow("Invalid DeviceClassId") << DeviceClassId::createDeviceClassId() << deviceParams << true << Device::DeviceErrorDeviceClassNotFound; deviceParams.clear(); deviceParams << httpportParam << brokenParam; - QTest::newRow("Setup failure") << mockDeviceClassId << deviceParams << Device::DeviceErrorSetupFailed; + QTest::newRow("Setup failure") << mockDeviceClassId << deviceParams << true << Device::DeviceErrorSetupFailed; deviceParams.clear(); deviceParams << httpportParam << asyncParam << brokenParam; - QTest::newRow("Setup failure, Async") << mockDeviceClassId << deviceParams << Device::DeviceErrorSetupFailed; + QTest::newRow("Setup failure, Async") << mockDeviceClassId << deviceParams << true << Device::DeviceErrorSetupFailed; QVariantList invalidDeviceParams; - QTest::newRow("User, JustAdd, missing params") << mockDeviceClassId << invalidDeviceParams << Device::DeviceErrorMissingParameter; + QTest::newRow("User, JustAdd, missing params") << mockDeviceClassId << invalidDeviceParams << true << Device::DeviceErrorMissingParameter; QVariantMap fakeparam; fakeparam.insert("paramTypeId", ParamTypeId::createParamTypeId()); invalidDeviceParams.append(fakeparam); - QTest::newRow("User, JustAdd, invalid param") << mockDeviceClassId << invalidDeviceParams << Device::DeviceErrorMissingParameter; + QTest::newRow("User, JustAdd, invalid param") << mockDeviceClassId << invalidDeviceParams << false << Device::DeviceErrorMissingParameter; QVariantMap fakeparam2; fakeparam2.insert("paramTypeId", mockDeviceHttpportParamTypeId.toString()); fakeparam2.insert("value", "blabla"); invalidDeviceParams.clear(); invalidDeviceParams.append(fakeparam2); - QTest::newRow("User, JustAdd, wrong param") << mockDeviceClassId << invalidDeviceParams << Device::DeviceErrorInvalidParameter; + QTest::newRow("User, JustAdd, wrong param") << mockDeviceClassId << invalidDeviceParams << true << Device::DeviceErrorInvalidParameter; deviceParams.clear(); deviceParams << httpportParam << fakeparam; QTest::newRow("USer, JustAdd, additional invalid param") << mockDeviceClassId << deviceParams << Device::DeviceErrorNoError; @@ -360,6 +361,7 @@ void TestDevices::addConfiguredDevice() { QFETCH(DeviceClassId, deviceClassId); QFETCH(QVariantList, deviceParams); + QFETCH(bool, jsonValidation); QFETCH(Device::DeviceError, deviceError); QVariantMap params; @@ -367,8 +369,11 @@ void TestDevices::addConfiguredDevice() params.insert("name", "Test Add Device"); params.insert("deviceParams", deviceParams); QVariant response = injectAndWait("Devices.AddConfiguredDevice", params); - qDebug() << "response is" << response; + if (!jsonValidation) { + QCOMPARE(response.toMap().value("status").toString(), "error"); + return; + } verifyDeviceError(response, deviceError); if (deviceError == Device::DeviceErrorNoError) { @@ -779,7 +784,7 @@ void TestDevices::getStateTypes() QVariantList stateTypes = response.toMap().value("params").toMap().value("stateTypes").toList(); QCOMPARE(stateTypes.count(), resultCount); if (resultCount > 0) { - QCOMPARE(stateTypes.first().toMap().value("id").toString(), mockIntStateTypeId.toString()); + QCOMPARE(stateTypes.first().toMap().value("id").toUuid(), mockIntStateTypeId); } } @@ -808,10 +813,8 @@ void TestDevices::getStateType() QVariantMap stateType = response.toMap().value("params").toMap().value("stateType").toMap(); - qDebug() << QJsonDocument::fromVariant(stateType).toJson(); - QVERIFY2(!stateType.isEmpty(), "Got no stateType"); - QCOMPARE(stateType.value("id").toString(), stateTypeId.toString()); + QCOMPARE(stateType.value("id").toUuid(), stateTypeId); } void TestDevices::getStateValue_data() diff --git a/tests/auto/jsonrpc/testjsonrpc.cpp b/tests/auto/jsonrpc/testjsonrpc.cpp index e875b661..cfd83ddf 100644 --- a/tests/auto/jsonrpc/testjsonrpc.cpp +++ b/tests/auto/jsonrpc/testjsonrpc.cpp @@ -612,6 +612,8 @@ void TestJSONRPC::introspect() QVariant response = injectAndWait("JSONRPC.Introspect"); QVariantMap methods = response.toMap().value("params").toMap().value("methods").toMap(); QVariantMap notifications = response.toMap().value("params").toMap().value("notifications").toMap(); + QVariantMap enums = response.toMap().value("params").toMap().value("enums").toMap(); + QVariantMap flags = response.toMap().value("params").toMap().value("flags").toMap(); QVariantMap types = response.toMap().value("params").toMap().value("types").toMap(); QVERIFY2(methods.count() > 0, "No methods in Introspect response!"); @@ -624,8 +626,11 @@ void TestJSONRPC::introspect() foreach (const QString &ref, extractRefs(item)) { QString typeId = ref; typeId.remove("$ref:"); - QVERIFY2(types.contains(typeId), QString("Undefined ref: %1. Did you forget to add it to JsonTypes::allTypes()?").arg(ref).toLatin1().data()); - QVERIFY2(!types.value(typeId).toString().startsWith("$ref:"), QString("Definition for %1 must not be a reference itself").arg(ref).toLatin1().data()); + QVERIFY2(enums.contains(typeId) || types.contains(typeId) || flags.contains(typeId), + QString("Undefined ref: %1. Did you forget to add it to JsonTypes::allTypes()?").arg(ref).toLatin1().data()); + QVERIFY2(!types.value(typeId).toString().startsWith("$ref:") + && !flags.value(typeId).toString().startsWith("$ref:") + && !enums.value(typeId).toString().startsWith("$ref:"), QString("Definition for %1 must not be a reference itself").arg(ref).toLatin1().data()); } } } @@ -836,7 +841,7 @@ void TestJSONRPC::ruleActiveChangedNotifications() notificationVariant = checkNotification(clientSpy, "Rules.RuleActiveChanged"); verifyRuleError(response); - QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toString(), ruleId.toString()); + QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid(), ruleId); QCOMPARE(notificationVariant.toMap().value("params").toMap().value("active").toBool(), true); spy.clear(); clientSpy.clear(); @@ -854,7 +859,7 @@ void TestJSONRPC::ruleActiveChangedNotifications() notificationVariant = checkNotification(clientSpy, "Rules.RuleActiveChanged"); verifyRuleError(response); - QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toString(), ruleId.toString()); + QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid(), ruleId); QCOMPARE(notificationVariant.toMap().value("params").toMap().value("active").toBool(), false); // now remove the rule and check the RuleRemoved notification @@ -867,7 +872,7 @@ void TestJSONRPC::ruleActiveChangedNotifications() checkNotification(clientSpy, "Logging.LogDatabaseUpdated"); verifyRuleError(response); - QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toString(), ruleId.toString()); + QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid(), ruleId); } void TestJSONRPC::deviceChangedNotifications() diff --git a/tests/auto/logging/testlogging.cpp b/tests/auto/logging/testlogging.cpp index 79ce347b..34aa2c85 100644 --- a/tests/auto/logging/testlogging.cpp +++ b/tests/auto/logging/testlogging.cpp @@ -250,10 +250,10 @@ void TestLogging::eventLogs() qDebug() << "got" << loggEntryAddedVariants.count() << "Logging.LogEntryAdded"; foreach (const QVariant &loggEntryAddedVariant, loggEntryAddedVariants) { QVariantMap logEntry = loggEntryAddedVariant.toMap().value("params").toMap().value("logEntry").toMap(); - if (logEntry.value("deviceId").toString() == device->id().toString()) { + if (logEntry.value("deviceId").toUuid() == device->id()) { found = true; // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toString(), mockEvent1EventTypeId.toString()); + QCOMPARE(logEntry.value("typeId").toUuid(), mockEvent1EventTypeId); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceEvents)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); @@ -320,10 +320,10 @@ void TestLogging::actionLog() qDebug() << "got" << loggEntryAddedVariants.count() << "Logging.LogEntryAdded"; foreach (const QVariant &loggEntryAddedVariant, loggEntryAddedVariants) { QVariantMap logEntry = loggEntryAddedVariant.toMap().value("params").toMap().value("logEntry").toMap(); - if (logEntry.value("deviceId").toString() == m_mockDeviceId.toString()) { + if (logEntry.value("deviceId").toUuid() == m_mockDeviceId) { found = true; // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toString(), mockWithParamsActionTypeId.toString()); + QCOMPARE(logEntry.value("typeId").toUuid(), mockWithParamsActionTypeId); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); @@ -379,10 +379,10 @@ void TestLogging::actionLog() qDebug() << "got" << loggEntryAddedVariants.count() << "Logging.LogEntryAdded"; foreach (const QVariant &loggEntryAddedVariant, loggEntryAddedVariants) { QVariantMap logEntry = loggEntryAddedVariant.toMap().value("params").toMap().value("logEntry").toMap(); - if (logEntry.value("deviceId").toString() == m_mockDeviceId.toString()) { + if (logEntry.value("deviceId").toUuid() == m_mockDeviceId) { found = true; // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toString(), mockFailingActionTypeId.toString()); + QCOMPARE(logEntry.value("typeId").toUuid(), mockFailingActionTypeId); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelAlert)); diff --git a/tests/auto/rules/testrules.cpp b/tests/auto/rules/testrules.cpp index 2487482c..43ec378b 100644 --- a/tests/auto/rules/testrules.cpp +++ b/tests/auto/rules/testrules.cpp @@ -400,6 +400,7 @@ void TestRules::initTestCase() "Tests.debug=true\n" "RuleEngine.debug=true\n" // "RuleEngineDebug.debug=true\n" + "JsonRpc.debug=true\n" "MockDevice.*=true"); } @@ -412,7 +413,7 @@ void TestRules::addRemoveRules_data() validActionNoParams.insert("ruleActionParams", QVariantList()); QVariantMap invalidAction; - invalidAction.insert("actionTypeId", ActionTypeId()); + invalidAction.insert("actionTypeId", ActionTypeId("f32c7efb-38b6-4576-a496-c75bbb23132f")); invalidAction.insert("deviceId", m_mockDeviceId); invalidAction.insert("ruleActionParams", QVariantList()); @@ -423,7 +424,7 @@ void TestRules::addRemoveRules_data() validExitActionNoParams.insert("ruleActionParams", QVariantList()); QVariantMap invalidExitAction; - invalidExitAction.insert("actionTypeId", ActionTypeId()); + invalidExitAction.insert("actionTypeId", ActionTypeId("f32c7efb-38b6-4576-a496-c75bbb23132f")); invalidExitAction.insert("deviceId", m_mockDeviceId); invalidExitAction.insert("ruleActionParams", QVariantList()); @@ -472,7 +473,7 @@ void TestRules::addRemoveRules_data() QVariantMap invalidEventDescriptor; invalidEventDescriptor.insert("eventTypeId", mockEvent1EventTypeId); - invalidEventDescriptor.insert("deviceId", DeviceId()); + invalidEventDescriptor.insert("deviceId", DeviceId("2c4825c8-dfb9-4ba4-bd0e-1d827d945d41")); invalidEventDescriptor.insert("paramDescriptors", QVariantList()); // RuleAction event based @@ -501,7 +502,7 @@ void TestRules::addRemoveRules_data() QVariantMap invalidActionEventBasedParam2; invalidActionEventBasedParam2.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); invalidActionEventBasedParam2.insert("eventTypeId", mockEvent1EventTypeId); - invalidActionEventBasedParam2.insert("eventParamTypeId", "value"); + invalidActionEventBasedParam2.insert("eventParamTypeId", ParamTypeId("7dbf5266-5179-4e09-ac31-631cc63f1d7b")); QVariantMap invalidActionEventBasedParam3; invalidActionEventBasedParam3.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); invalidActionEventBasedParam3.insert("value", 2); @@ -532,9 +533,9 @@ void TestRules::addRemoveRules_data() QTest::newRow("invalid rule. enabled, 1 Action (eventBased), types not matching, name") << true << invalidActionEventBased3 << QVariantMap() << validEventDescriptor1 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorTypesNotMatching << false << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorTypesNotMatching << false << "TestRule"; + QTest::newRow("invalid rule. enabled, 1 invalid Action (eventBased), 1 EventDescriptor, name") << true << invalidActionEventBased << QVariantMap() << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorTypesNotMatching << false << "TestRule"; QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 StateEvaluator, name") << true << validActionEventBased << QVariantMap() << QVariantMap() << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorInvalidRuleActionParameter << false << "TestRule"; - QTest::newRow("invalid rule. enabled, 1 Action (eventBased), 1 EventDescriptor, name") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleFormat << false << "TestRule"; + QTest::newRow("invalid rule. enabled, invalid rule format") << true << validActionEventBased << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleFormat << false << "TestRule"; QTest::newRow("invalid rule. enabled, 1 Action, 1 ExitAction (EventBased), name") << true << validActionNoParams << validActionEventBased << validEventDescriptor2 << QVariantList() << QVariantMap() << RuleEngine::RuleErrorInvalidRuleFormat << false << "TestRule"; // Rules with exit actions @@ -550,7 +551,7 @@ void TestRules::addRemoveRules_data() QTest::newRow("valid rule. disabled, 1 EventDescriptor, StateEvaluator, 1 Action, name") << false << validActionNoParams << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule"; QTest::newRow("valid rule. 2 EventDescriptors, 1 Action, name") << true << validActionNoParams << QVariantMap() << QVariantMap() << eventDescriptorList << validStateEvaluator << RuleEngine::RuleErrorNoError << true << "TestRule"; QTest::newRow("invalid action") << true << invalidAction << QVariantMap() << validEventDescriptor1 << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorActionTypeNotFound << false << "TestRule"; - QTest::newRow("invalid event descriptor") << true << validActionNoParams << QVariantMap() << invalidEventDescriptor << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorEventTypeNotFound << false << "TestRule"; + QTest::newRow("invalid event descriptor") << true << validActionNoParams << QVariantMap() << invalidEventDescriptor << QVariantList() << validStateEvaluator << RuleEngine::RuleErrorDeviceNotFound << false << "TestRule"; } void TestRules::addRemoveRules() @@ -587,6 +588,7 @@ void TestRules::addRemoveRules() if (!enabled) { params.insert("enabled", enabled); } + qCDebug(dcTests()) << "Calling with params:" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson()); QVariant response = injectAndWait("Rules.AddRule", params); if (!jsonError) { verifyRuleError(response, error); @@ -744,7 +746,7 @@ void TestRules::editRules_data() QVariantMap invalidActionEventBasedParam2; invalidActionEventBasedParam2.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); invalidActionEventBasedParam2.insert("eventTypeId", mockEvent1EventTypeId); - invalidActionEventBasedParam2.insert("eventParamTypeId", "value"); + invalidActionEventBasedParam2.insert("eventParamTypeId", ParamTypeId("2c4825c8-dfb9-4ba4-bd0e-1d827d945d41")); QVariantMap invalidActionEventBasedParam3; invalidActionEventBasedParam3.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); invalidActionEventBasedParam3.insert("value", 2); @@ -1078,7 +1080,7 @@ void TestRules::findRule() response = injectAndWait("Rules.FindRules", params); QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().count(), 1); - QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().first().toString(), ruleId.toString()); + QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().first().toUuid(), ruleId); // REMOVE rule QVariantMap removeParams; diff --git a/tests/auto/tags/testtags.cpp b/tests/auto/tags/testtags.cpp index 2a25e28a..0384afd0 100644 --- a/tests/auto/tags/testtags.cpp +++ b/tests/auto/tags/testtags.cpp @@ -43,7 +43,7 @@ private slots: private: QVariantMap createDeviceTag(const QString &deviceId, const QString &appId, const QString &tagId, const QString &value); - bool compareDeviceTag(const QVariantMap &tag, const QString &deviceId, const QString &appId, const QString &tagId, const QString &value); + bool compareDeviceTag(const QVariantMap &tag, const QUuid &deviceId, const QString &appId, const QString &tagId, const QString &value); QVariantMap createRuleTag(const QString &ruleId, const QString &appId, const QString &tagId, const QString &value); bool comapreRuleTag(const QVariantMap &tag, const QString &ruleId, const QString &appId, const QString &tagId, const QString &value); }; @@ -68,9 +68,9 @@ QVariantMap TestTags::createRuleTag(const QString &ruleId, const QString &appId, return tag; } -bool TestTags::compareDeviceTag(const QVariantMap &tag, const QString &deviceId, const QString &appId, const QString &tagId, const QString &value) +bool TestTags::compareDeviceTag(const QVariantMap &tag, const QUuid &deviceId, const QString &appId, const QString &tagId, const QString &value) { - return tag.value("deviceId").toString() == deviceId && + return tag.value("deviceId").toUuid() == deviceId && tag.value("appId").toString() == appId && tag.value("tagId").toString() == tagId && tag.value("value").toString() == value; @@ -114,7 +114,7 @@ void TestTags::addTag() // Make sure the TagAdded notification is emitted. QVariantMap notificationTagMap = checkNotification(clientSpy, "Tags.TagAdded").toMap().value("params").toMap().value("tag").toMap(); QJsonDocument jsonDoc = QJsonDocument::fromVariant(notificationTagMap); - QVERIFY2(compareDeviceTag(notificationTagMap, deviceId.toString(), appId, tagId, value), QString("Tag in notification not matching: %1").arg(qUtf8Printable(jsonDoc.toJson())).toLatin1()); + QVERIFY2(compareDeviceTag(notificationTagMap, deviceId, appId, tagId, value), QString("Tag in notification not matching: %1").arg(qUtf8Printable(jsonDoc.toJson())).toLatin1()); // Try getting the tag via GetTag params.clear(); @@ -124,7 +124,7 @@ void TestTags::addTag() response = injectAndWait("Tags.GetTags", params); QVariantList tagsList = response.toMap().value("params").toMap().value("tags").toList(); QCOMPARE(tagsList.count(), 1); - QVERIFY2(compareDeviceTag(tagsList.first().toMap(), deviceId.toString(), appId, tagId, value), "Fetched tag isn't matching the one we added"); + QVERIFY2(compareDeviceTag(tagsList.first().toMap(), deviceId, appId, tagId, value), "Fetched tag isn't matching the one we added"); } void TestTags::updateTagValue() diff --git a/tests/auto/timemanager/testtimemanager.cpp b/tests/auto/timemanager/testtimemanager.cpp index c917042e..62e31b52 100644 --- a/tests/auto/timemanager/testtimemanager.cpp +++ b/tests/auto/timemanager/testtimemanager.cpp @@ -46,6 +46,9 @@ private slots: void addTimeDescriptor_data(); void addTimeDescriptor(); + void addTimeDescriptorInvalidTimes_data(); + void addTimeDescriptorInvalidTimes(); + // CalendarItems void testCalendarDateTime_data(); void testCalendarDateTime(); @@ -335,10 +338,8 @@ void TestTimeManager::addTimeDescriptor_data() QTest::newRow("valid: timeEventItem - weekly - multiple days") << createTimeDescriptorTimeEvent(timeEventItems) << RuleEngine::RuleErrorNoError; QTest::newRow("valid: timeEventItem - monthly - multiple days") << createTimeDescriptorTimeEvent(createTimeEventItem("23:00", repeatingOptionMonthlyMultiple)) << RuleEngine::RuleErrorNoError; - QTest::newRow("invalid: calendarItem empty") << createTimeDescriptorCalendar(createCalendarItem()) << RuleEngine::RuleErrorInvalidCalendarItem; QTest::newRow("invalid: calendarItem none") << createTimeDescriptorCalendar(createCalendarItem("00:12", 12, repeatingOptionInvalidNone)) << RuleEngine::RuleErrorInvalidRepeatingOption; QTest::newRow("invalid: calendarItem dateTime - daily") << createTimeDescriptorCalendar(createCalendarItem(QDateTime::currentDateTime().toTime_t(), 5, repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidCalendarItem; - QTest::newRow("invalid: calendarItem invalid time") << createTimeDescriptorCalendar(createCalendarItem("35:80", 5)) << RuleEngine::RuleErrorInvalidCalendarItem; QTest::newRow("invalid: calendarItem invalid duration") << createTimeDescriptorCalendar(createCalendarItem("12:00", 0)) << RuleEngine::RuleErrorInvalidCalendarItem; QTest::newRow("invalid: calendarItem - monthly - weekDays") << createTimeDescriptorCalendar(createCalendarItem("13:13", 5, repeatingOptionInvalidMonthly)) << RuleEngine::RuleErrorInvalidRepeatingOption; QTest::newRow("invalid: calendarItem - weekly - monthDays") << createTimeDescriptorCalendar(createCalendarItem("15:30", 20, repeatingOptionInvalidWeekly)) << RuleEngine::RuleErrorInvalidRepeatingOption; @@ -347,10 +348,8 @@ void TestTimeManager::addTimeDescriptor_data() QTest::newRow("invalid: calendarItem - invalid monthdays (negative)") << createTimeDescriptorCalendar(createCalendarItem("13:13", 5, repeatingOptionInvalidMonthDays)) << RuleEngine::RuleErrorInvalidRepeatingOption; QTest::newRow("invalid: calendarItem - invalid monthdays (to big)") << createTimeDescriptorCalendar(createCalendarItem("13:13", 5, repeatingOptionInvalidMonthDays2)) << RuleEngine::RuleErrorInvalidRepeatingOption; - QTest::newRow("invalid: timeEventItem empty") << createTimeDescriptorTimeEvent(createTimeEventItem()) << RuleEngine::RuleErrorInvalidTimeEventItem; QTest::newRow("invalid: timeEventItem none") << createTimeDescriptorTimeEvent(createTimeEventItem("00:12", repeatingOptionInvalidNone)) << RuleEngine::RuleErrorInvalidRepeatingOption; QTest::newRow("invalid: timeEventItem - dateTime + repeatingOption") << createTimeDescriptorTimeEvent(createTimeEventItem(QDateTime::currentDateTime().toTime_t(), repeatingOptionDaily)) << RuleEngine::RuleErrorInvalidTimeEventItem; - QTest::newRow("invalid: timeEventItem invalid time") << createTimeDescriptorTimeEvent(createTimeEventItem("35:80")) << RuleEngine::RuleErrorInvalidTimeEventItem; QTest::newRow("invalid: timeEventItem - monthly - weekDays") << createTimeDescriptorTimeEvent(createTimeEventItem("13:13", repeatingOptionInvalidMonthly)) << RuleEngine::RuleErrorInvalidRepeatingOption; QTest::newRow("invalid: timeEventItem - weekly - monthDays") << createTimeDescriptorTimeEvent(createTimeEventItem("15:30", repeatingOptionInvalidWeekly)) << RuleEngine::RuleErrorInvalidRepeatingOption; QTest::newRow("invalid: timeEventItem - invalid weekdays (negative)") << createTimeDescriptorTimeEvent(createTimeEventItem("13:13", repeatingOptionInvalidWeekDays)) << RuleEngine::RuleErrorInvalidRepeatingOption; @@ -387,6 +386,34 @@ void TestTimeManager::addTimeDescriptor() verifyRuleError(response); } +void TestTimeManager::addTimeDescriptorInvalidTimes_data() +{ + QTest::addColumn("timeDescriptor"); + + QTest::newRow("invalid: calendarItem empty") << createTimeDescriptorCalendar(createCalendarItem()); + QTest::newRow("invalid: calendarItem invalid time") << createTimeDescriptorCalendar(createCalendarItem("35:80", 5)); + + QTest::newRow("invalid: timeEventItem empty") << createTimeDescriptorTimeEvent(createTimeEventItem()); + QTest::newRow("invalid: timeEventItem invalid time") << createTimeDescriptorTimeEvent(createTimeEventItem("35:80")); +} + +void TestTimeManager::addTimeDescriptorInvalidTimes() +{ + QFETCH(QVariantMap, timeDescriptor); + + // ADD the rule + QVariantMap ruleMap; QVariantMap action; + action.insert("actionTypeId", mockWithoutParamsActionTypeId); + action.insert("deviceId", m_mockDeviceId); + action.insert("ruleActionParams", QVariantList()); + ruleMap.insert("name", "TimeBased rule"); + ruleMap.insert("timeDescriptor", timeDescriptor); + ruleMap.insert("actions", QVariantList() << action); + + QVariant response = injectAndWait("Rules.AddRule", ruleMap); + QVERIFY2(response.toMap().value("status").toString() == "error", "Invalid time must fail JSON verification."); +} + void TestTimeManager::testCalendarDateTime_data() { QTest::addColumn("dateTime"); diff --git a/tests/testlib/nymeatestbase.cpp b/tests/testlib/nymeatestbase.cpp index 226ff84c..d4d730d6 100644 --- a/tests/testlib/nymeatestbase.cpp +++ b/tests/testlib/nymeatestbase.cpp @@ -71,6 +71,7 @@ void NymeaTestBase::initTestCase() // Wait unitl the server is initialized QSignalSpy coreInitializedSpy(NymeaCore::instance(), SIGNAL(initialized())); QVERIFY(coreInitializedSpy.wait()); + qApp->processEvents(); // Yes, we're intentionally mixing upper/lower case email here... username should not be case sensitive NymeaCore::instance()->userManager()->removeUser("dummy@guh.io"); From 1cebaaee9dd319bcc00de8c7d585b85073b21a83 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 30 Oct 2019 00:33:06 +0100 Subject: [PATCH 10/22] Bump version --- debian/changelog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/debian/changelog b/debian/changelog index eee6047a..4dbbd4df 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,8 @@ +nymea (0.17.0) UNRELEASED; urgency=medium + + + -- Michael Zanetti Wed, 30 Oct 2019 00:32:48 +0100 + nymea (0.16.0) xenial; urgency=medium [ Michael Zanetti ] * Add account interface From feee5ef23ace0b9daf81c6f8fb02f401029d94c2 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 30 Oct 2019 11:45:21 +0100 Subject: [PATCH 11/22] Fix tests --- tests/auto/devices/testdevices.cpp | 6 +++--- tests/auto/jsonrpc/testjsonrpc.cpp | 6 +++--- tests/auto/logging/testlogging.cpp | 6 +++--- tests/auto/rules/testrules.cpp | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/auto/devices/testdevices.cpp b/tests/auto/devices/testdevices.cpp index caf121a9..760eb89e 100644 --- a/tests/auto/devices/testdevices.cpp +++ b/tests/auto/devices/testdevices.cpp @@ -371,7 +371,7 @@ void TestDevices::addConfiguredDevice() QVariant response = injectAndWait("Devices.AddConfiguredDevice", params); if (!jsonValidation) { - QCOMPARE(response.toMap().value("status").toString(), "error"); + QCOMPARE(response.toMap().value("status").toString(), QString("error")); return; } verifyDeviceError(response, deviceError); @@ -784,7 +784,7 @@ void TestDevices::getStateTypes() QVariantList stateTypes = response.toMap().value("params").toMap().value("stateTypes").toList(); QCOMPARE(stateTypes.count(), resultCount); if (resultCount > 0) { - QCOMPARE(stateTypes.first().toMap().value("id").toUuid(), mockIntStateTypeId); + QCOMPARE(stateTypes.first().toMap().value("id").toUuid().toString(), mockIntStateTypeId.toString()); } } @@ -814,7 +814,7 @@ void TestDevices::getStateType() QVariantMap stateType = response.toMap().value("params").toMap().value("stateType").toMap(); QVERIFY2(!stateType.isEmpty(), "Got no stateType"); - QCOMPARE(stateType.value("id").toUuid(), stateTypeId); + QCOMPARE(stateType.value("id").toUuid().toString(), stateTypeId.toString()); } void TestDevices::getStateValue_data() diff --git a/tests/auto/jsonrpc/testjsonrpc.cpp b/tests/auto/jsonrpc/testjsonrpc.cpp index cfd83ddf..51a666fd 100644 --- a/tests/auto/jsonrpc/testjsonrpc.cpp +++ b/tests/auto/jsonrpc/testjsonrpc.cpp @@ -841,7 +841,7 @@ void TestJSONRPC::ruleActiveChangedNotifications() notificationVariant = checkNotification(clientSpy, "Rules.RuleActiveChanged"); verifyRuleError(response); - QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid(), ruleId); + QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid().toString(), ruleId.toString()); QCOMPARE(notificationVariant.toMap().value("params").toMap().value("active").toBool(), true); spy.clear(); clientSpy.clear(); @@ -859,7 +859,7 @@ void TestJSONRPC::ruleActiveChangedNotifications() notificationVariant = checkNotification(clientSpy, "Rules.RuleActiveChanged"); verifyRuleError(response); - QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid(), ruleId); + QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid().toString(), ruleId.toString()); QCOMPARE(notificationVariant.toMap().value("params").toMap().value("active").toBool(), false); // now remove the rule and check the RuleRemoved notification @@ -872,7 +872,7 @@ void TestJSONRPC::ruleActiveChangedNotifications() checkNotification(clientSpy, "Logging.LogDatabaseUpdated"); verifyRuleError(response); - QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid(), ruleId); + QCOMPARE(notificationVariant.toMap().value("params").toMap().value("ruleId").toUuid().toString(), ruleId.toString()); } void TestJSONRPC::deviceChangedNotifications() diff --git a/tests/auto/logging/testlogging.cpp b/tests/auto/logging/testlogging.cpp index 34aa2c85..abd0753d 100644 --- a/tests/auto/logging/testlogging.cpp +++ b/tests/auto/logging/testlogging.cpp @@ -253,7 +253,7 @@ void TestLogging::eventLogs() if (logEntry.value("deviceId").toUuid() == device->id()) { found = true; // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toUuid(), mockEvent1EventTypeId); + QCOMPARE(logEntry.value("typeId").toUuid().toString(), mockEvent1EventTypeId.toString()); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceEvents)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); @@ -323,7 +323,7 @@ void TestLogging::actionLog() if (logEntry.value("deviceId").toUuid() == m_mockDeviceId) { found = true; // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toUuid(), mockWithParamsActionTypeId); + QCOMPARE(logEntry.value("typeId").toUuid().toString(), mockWithParamsActionTypeId.toString()); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo)); @@ -382,7 +382,7 @@ void TestLogging::actionLog() if (logEntry.value("deviceId").toUuid() == m_mockDeviceId) { found = true; // Make sure the notification contains all the stuff we expect - QCOMPARE(logEntry.value("typeId").toUuid(), mockFailingActionTypeId); + QCOMPARE(logEntry.value("typeId").toUuid().toString(), mockFailingActionTypeId.toString()); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelAlert)); diff --git a/tests/auto/rules/testrules.cpp b/tests/auto/rules/testrules.cpp index 43ec378b..bb3a36f7 100644 --- a/tests/auto/rules/testrules.cpp +++ b/tests/auto/rules/testrules.cpp @@ -1080,7 +1080,7 @@ void TestRules::findRule() response = injectAndWait("Rules.FindRules", params); QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().count(), 1); - QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().first().toUuid(), ruleId); + QCOMPARE(response.toMap().value("params").toMap().value("ruleIds").toList().first().toUuid().toString(), ruleId.toString()); // REMOVE rule QVariantMap removeParams; From 3a88a25c490353ddea13f4627181c8bcbfcc06c9 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 30 Oct 2019 12:43:15 +0100 Subject: [PATCH 12/22] add copyright headers --- .../experiences/experiencemanager.cpp | 20 ++++++++++++++++ libnymea-core/experiences/experiencemanager.h | 20 ++++++++++++++++ libnymea-core/jsonrpc/jsonvalidator.cpp | 20 ++++++++++++++++ libnymea-core/jsonrpc/jsonvalidator.h | 20 ++++++++++++++++ libnymea/experiences/experienceplugin.cpp | 20 ++++++++++++++++ libnymea/experiences/experienceplugin.h | 20 ++++++++++++++++ libnymea/jsonrpc/jsonhandler.cpp | 20 ++++++++++++++++ libnymea/jsonrpc/jsonhandler.h | 20 ++++++++++++++++ libnymea/jsonrpc/jsonreply.cpp | 20 ++++++++++++++++ libnymea/jsonrpc/jsonreply.h | 20 ++++++++++++++++ libnymea/jsonrpc/jsonrpcserver.cpp | 24 +++++++++++++++++-- libnymea/jsonrpc/jsonrpcserver.h | 20 ++++++++++++++++ 12 files changed, 242 insertions(+), 2 deletions(-) diff --git a/libnymea-core/experiences/experiencemanager.cpp b/libnymea-core/experiences/experiencemanager.cpp index e0582898..88d86f23 100644 --- a/libnymea-core/experiences/experiencemanager.cpp +++ b/libnymea-core/experiences/experiencemanager.cpp @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "experiencemanager.h" #include "experiences/experienceplugin.h" diff --git a/libnymea-core/experiences/experiencemanager.h b/libnymea-core/experiences/experiencemanager.h index 1231d456..fe3db4d4 100644 --- a/libnymea-core/experiences/experiencemanager.h +++ b/libnymea-core/experiences/experiencemanager.h @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef EXPERIENCEMANAGER_H #define EXPERIENCEMANAGER_H diff --git a/libnymea-core/jsonrpc/jsonvalidator.cpp b/libnymea-core/jsonrpc/jsonvalidator.cpp index d5557bb0..b3691312 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.cpp +++ b/libnymea-core/jsonrpc/jsonvalidator.cpp @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "jsonvalidator.h" #include "jsonrpc/jsonhandler.h" diff --git a/libnymea-core/jsonrpc/jsonvalidator.h b/libnymea-core/jsonrpc/jsonvalidator.h index 8d2d1130..7b168fec 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.h +++ b/libnymea-core/jsonrpc/jsonvalidator.h @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef JSONVALIDATOR_H #define JSONVALIDATOR_H diff --git a/libnymea/experiences/experienceplugin.cpp b/libnymea/experiences/experienceplugin.cpp index 098a7824..c4356e04 100644 --- a/libnymea/experiences/experienceplugin.cpp +++ b/libnymea/experiences/experienceplugin.cpp @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "experienceplugin.h" ExperiencePlugin::ExperiencePlugin(QObject *parent) : QObject(parent) diff --git a/libnymea/experiences/experienceplugin.h b/libnymea/experiences/experienceplugin.h index 1dd7c401..092db8d9 100644 --- a/libnymea/experiences/experienceplugin.h +++ b/libnymea/experiences/experienceplugin.h @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef EXPERIENCEPLUGIN_H #define EXPERIENCEPLUGIN_H diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 0450e7cf..5de27436 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "jsonhandler.h" #include "loggingcategories.h" diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index 12398611..3d1ee9c4 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef JSONHANDLER_H #define JSONHANDLER_H diff --git a/libnymea/jsonrpc/jsonreply.cpp b/libnymea/jsonrpc/jsonreply.cpp index e917af44..45d8b744 100644 --- a/libnymea/jsonrpc/jsonreply.cpp +++ b/libnymea/jsonrpc/jsonreply.cpp @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "jsonreply.h" /*! diff --git a/libnymea/jsonrpc/jsonreply.h b/libnymea/jsonrpc/jsonreply.h index 0a33f611..acf1a517 100644 --- a/libnymea/jsonrpc/jsonreply.h +++ b/libnymea/jsonrpc/jsonreply.h @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef JSONREPLY_H #define JSONREPLY_H diff --git a/libnymea/jsonrpc/jsonrpcserver.cpp b/libnymea/jsonrpc/jsonrpcserver.cpp index 3bcc03f2..2a72c6a7 100644 --- a/libnymea/jsonrpc/jsonrpcserver.cpp +++ b/libnymea/jsonrpc/jsonrpcserver.cpp @@ -1,5 +1,25 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #include "jsonrpcserver.h" -/*! \fn void JsonRPCServer::registerJsonHandler(JsonHandler *handler) - Register a JSON RPC handler on the JSON RPC server. +/*! \fn void JsonRPCServer::registerExperienceHandler(JsonHandler *handler, int majorVersion, int minorVersion) + Register an experience JSON RPC handler on the JSON RPC server. */ diff --git a/libnymea/jsonrpc/jsonrpcserver.h b/libnymea/jsonrpc/jsonrpcserver.h index aeeddc4e..b8aab9fb 100644 --- a/libnymea/jsonrpc/jsonrpcserver.h +++ b/libnymea/jsonrpc/jsonrpcserver.h @@ -1,3 +1,23 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * nymea is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, version 2 of the License. * + * * + * nymea is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with nymea. If not, see . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + #ifndef JSONRPCSERVER_H #define JSONRPCSERVER_H From c72342e3629c20732bacec75ef72e25e64cf418e Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 30 Oct 2019 13:05:33 +0100 Subject: [PATCH 13/22] bump plugin api version --- plugins/mock/plugininfo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mock/plugininfo.h b/plugins/mock/plugininfo.h index b2c280f2..afe1447d 100644 --- a/plugins/mock/plugininfo.h +++ b/plugins/mock/plugininfo.h @@ -9,7 +9,7 @@ #include #include -extern "C" const QString libnymea_api_version() { return QString("3.0.0");} +extern "C" const QString libnymea_api_version() { return QString("4.0.0");} Q_DECLARE_LOGGING_CATEGORY(dcMockDevice) Q_LOGGING_CATEGORY(dcMockDevice, "MockDevice") From 9c5d21270e663a2e69ddca0a4164148b1bf189ff Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Fri, 1 Nov 2019 20:51:28 +0100 Subject: [PATCH 14/22] fix missing dbus dep (?) --- libnymea/libnymea.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index 0fc19205..0e6ca52d 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -3,7 +3,7 @@ include(../nymea.pri) TARGET = nymea TEMPLATE = lib -QT += network bluetooth +QT += network bluetooth dbus QT -= gui DEFINES += LIBNYMEA_LIBRARY From 3cbd01c1d254742a4a5d3a5156afee7d1e0fb07c Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 3 Nov 2019 21:24:16 +0100 Subject: [PATCH 15/22] drop all pack/unpack methds --- libnymea-core/devices/translator.cpp | 4 + libnymea-core/jsonrpc/actionhandler.cpp | 5 +- libnymea-core/jsonrpc/devicehandler.cpp | 184 ++----- libnymea-core/jsonrpc/devicehandler.h | 19 - libnymea-core/jsonrpc/eventhandler.cpp | 1 - libnymea-core/jsonrpc/ruleshandler.cpp | 482 +------------------ libnymea-core/jsonrpc/ruleshandler.h | 31 +- libnymea-core/jsonrpc/statehandler.cpp | 1 - libnymea-core/logging/logentry.cpp | 5 + libnymea-core/logging/logentry.h | 1 + libnymea-core/ruleengine/rule.cpp | 19 +- libnymea-core/ruleengine/rule.h | 35 +- libnymea-core/ruleengine/ruleaction.cpp | 5 + libnymea-core/ruleengine/ruleaction.h | 1 + libnymea-core/ruleengine/ruleactionparam.cpp | 5 + libnymea-core/ruleengine/ruleactionparam.h | 1 + libnymea-core/ruleengine/stateevaluator.cpp | 11 +- libnymea-core/ruleengine/stateevaluator.h | 28 +- libnymea-core/tagging/tag.cpp | 5 + libnymea-core/tagging/tag.h | 1 + libnymea-core/usermanager/tokeninfo.cpp | 5 + libnymea-core/usermanager/tokeninfo.h | 4 +- libnymea/devices/device.cpp | 4 +- libnymea/devices/device.h | 6 +- libnymea/devices/devicemanager.cpp | 5 +- libnymea/devices/deviceplugin.h | 4 +- libnymea/jsonrpc/jsonhandler.cpp | 284 +++++++---- libnymea/jsonrpc/jsonhandler.h | 103 ++-- libnymea/platform/package.cpp | 5 + libnymea/platform/package.h | 1 + libnymea/platform/repository.cpp | 5 + libnymea/platform/repository.h | 1 + libnymea/time/calendaritem.cpp | 8 +- libnymea/time/calendaritem.h | 3 +- libnymea/time/repeatingoption.cpp | 40 ++ libnymea/time/repeatingoption.h | 25 + libnymea/time/timedescriptor.cpp | 8 +- libnymea/time/timedescriptor.h | 14 +- libnymea/time/timeeventitem.cpp | 5 + libnymea/time/timeeventitem.h | 1 + libnymea/types/actiontype.cpp | 7 +- libnymea/types/actiontype.h | 3 +- libnymea/types/eventdescriptor.cpp | 5 + libnymea/types/eventdescriptor.h | 1 + libnymea/types/eventtype.cpp | 7 +- libnymea/types/eventtype.h | 3 +- libnymea/types/param.cpp | 10 + libnymea/types/param.h | 4 +- libnymea/types/paramdescriptor.cpp | 5 + libnymea/types/paramdescriptor.h | 1 + libnymea/types/paramtype.cpp | 7 +- libnymea/types/paramtype.h | 3 +- libnymea/types/state.cpp | 7 +- libnymea/types/state.h | 3 +- libnymea/types/statedescriptor.h | 5 +- libnymea/types/statetype.cpp | 7 +- libnymea/types/statetype.h | 3 +- libnymea/types/vendor.cpp | 5 + libnymea/types/vendor.h | 3 + tests/auto/devices/testdevices.cpp | 7 +- tests/auto/rules/testrules.cpp | 47 +- tests/auto/timemanager/testtimemanager.cpp | 17 +- tests/scripts/getruledetails.sh | 9 +- tests/scripts/getrules.sh | 8 +- tests/scripts/snoopnotifications.sh | 9 +- tests/testlib/nymeatestbase.cpp | 8 +- 66 files changed, 631 insertions(+), 938 deletions(-) diff --git a/libnymea-core/devices/translator.cpp b/libnymea-core/devices/translator.cpp index 16f2c6b1..f6e38b37 100644 --- a/libnymea-core/devices/translator.cpp +++ b/libnymea-core/devices/translator.cpp @@ -48,6 +48,10 @@ Translator::~Translator() QString Translator::translate(const PluginId &pluginId, const QString &string, const QLocale &locale) { DevicePlugin *plugin = m_deviceManager->plugins().findById(pluginId); + if (!plugin) { + qCWarning(dcDeviceManager()) << "Unable to translate" << string << "Plugin not found"; + return string; + } if (!m_translatorContexts.contains(plugin->pluginId()) || !m_translatorContexts.value(plugin->pluginId()).translators.contains(locale.name())) { loadTranslator(plugin, locale); diff --git a/libnymea-core/jsonrpc/actionhandler.cpp b/libnymea-core/jsonrpc/actionhandler.cpp index 22e721dc..9d63e618 100644 --- a/libnymea-core/jsonrpc/actionhandler.cpp +++ b/libnymea-core/jsonrpc/actionhandler.cpp @@ -33,7 +33,6 @@ */ #include "actionhandler.h" -#include "devicehandler.h" #include "nymeacore.h" #include "devices/devicemanager.h" @@ -105,7 +104,7 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap ¶ms) { DeviceId deviceId(params.value("deviceId").toString()); ActionTypeId actionTypeId(params.value("actionTypeId").toString()); - ParamList actionParams = DeviceHandler::unpackParams(params.value("params").toList()); + ParamList actionParams = unpack(params.value("params")); QLocale locale = params.value("locale").toLocale(); Action action(actionTypeId, deviceId); @@ -174,7 +173,7 @@ JsonReply *ActionHandler::ExecuteBrowserItemAction(const QVariantMap ¶ms) DeviceId deviceId = DeviceId(params.value("deviceId").toString()); QString itemId = params.value("itemId").toString(); ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString()); - ParamList paramList = DeviceHandler::unpackParams(params.value("params").toList()); + ParamList paramList = unpack(params.value("params")); BrowserItemAction browserItemAction(deviceId, itemId, actionTypeId, paramList); JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItemAction"); diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 69e749b1..5fbc2e81 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -90,7 +90,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : // Objects registerObject(); registerObject(); - registerObject(); + registerUncreatableObject(); registerObject(); registerObject(); registerObject(); @@ -98,7 +98,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : registerObject(); registerObject(); registerObject(); - registerObject(); + registerUncreatableObject(); // Regsitering browseritem manually for now. Not sure how to deal with the // polymorphism in int (e.g MediaBrowserItem) @@ -409,8 +409,7 @@ JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap ¶ms) const QVariantMap returns; DeviceClassId deviceClassId = DeviceClassId(params.value("deviceClassId").toString()); - - ParamList discoveryParams = unpackParams(params.value("discoveryParams").toList()); + ParamList discoveryParams = unpack(params.value("discoveryParams")); JsonReply *reply = createAsyncReply("GetDiscoveredDevices"); DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(deviceClassId, discoveryParams); @@ -476,7 +475,7 @@ JsonReply* DeviceHandler::SetPluginConfiguration(const QVariantMap ¶ms) { QVariantMap returns; PluginId pluginId = PluginId(params.value("pluginId").toString()); - ParamList pluginParams = unpackParams(params.value("configuration").toList()); + ParamList pluginParams = unpack(params.value("configuration")); Device::DeviceError result = NymeaCore::instance()->deviceManager()->setPluginConfig(pluginId, pluginParams); returns.insert("deviceError",enumValueName(result)); return createReply(returns); @@ -486,7 +485,7 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms) { DeviceClassId deviceClassId(params.value("deviceClassId").toString()); QString deviceName = params.value("name").toString(); - ParamList deviceParams = unpackParams(params.value("deviceParams").toList()); + ParamList deviceParams = unpack(params.value("deviceParams")); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); QLocale locale = params.value("locale").toLocale(); @@ -519,7 +518,7 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap ¶ms) JsonReply *DeviceHandler::PairDevice(const QVariantMap ¶ms) { QString deviceName = params.value("name").toString(); - ParamList deviceParams = unpackParams(params.value("deviceParams").toList()); + ParamList deviceParams = unpack(params.value("deviceParams")); QLocale locale = params.value("locale").toLocale(); DevicePairingInfo *info; @@ -598,11 +597,11 @@ JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const returns.insert("deviceError", enumValueName(Device::DeviceErrorDeviceNotFound)); return createReply(returns); } else { - configuredDeviceList.append(packDevice(device)); + configuredDeviceList.append(pack(device)); } } else { foreach (Device *device, NymeaCore::instance()->deviceManager()->configuredDevices()) { - configuredDeviceList.append(packDevice(device)); + configuredDeviceList.append(pack(device)); } } returns.insert("devices", configuredDeviceList); @@ -612,7 +611,7 @@ JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const JsonReply *DeviceHandler::ReconfigureDevice(const QVariantMap ¶ms) { DeviceId deviceId = DeviceId(params.value("deviceId").toString()); - ParamList deviceParams = unpackParams(params.value("deviceParams").toList()); + ParamList deviceParams = unpack(params.value("deviceParams")); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); QLocale locale = params.value("locale").toLocale(); @@ -692,34 +691,32 @@ JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms) JsonReply *DeviceHandler::SetDeviceSettings(const QVariantMap ¶ms) { DeviceId deviceId = DeviceId(params.value("deviceId").toString()); - ParamList settings = unpackParams(params.value("settings").toList()); + ParamList settings = unpack(params.value("settings")); Device::DeviceError status = NymeaCore::instance()->deviceManager()->setDeviceSettings(deviceId, settings); return createReply(statusToReply(status)); } JsonReply* DeviceHandler::GetEventTypes(const QVariantMap ¶ms) const { - QVariantMap returns; + QLocale locale = params.value("locale").toLocale(); - QVariantList eventList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); - foreach (const EventType &eventType, deviceClass.eventTypes()) { - eventList.append(packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); - } - returns.insert("eventTypes", eventList); + DeviceClass translatedDeviceClass = NymeaCore::instance()->deviceManager()->translateDeviceClass(deviceClass, locale); + + QVariantMap returns; + returns.insert("eventTypes", pack(translatedDeviceClass.eventTypes())); return createReply(returns); } JsonReply* DeviceHandler::GetActionTypes(const QVariantMap ¶ms) const { - QVariantMap returns; + QLocale locale = params.value("locale").toLocale(); - QVariantList actionList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); - foreach (const ActionType &actionType, deviceClass.actionTypes()) { - actionList.append(packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); - } - returns.insert("actionTypes", actionList); + DeviceClass translatedDeviceClass = NymeaCore::instance()->deviceManager()->translateDeviceClass(deviceClass, locale); + + QVariantMap returns; + returns.insert("actionTypes", pack(translatedDeviceClass.actionTypes())); return createReply(returns); } @@ -727,15 +724,11 @@ JsonReply* DeviceHandler::GetStateTypes(const QVariantMap ¶ms) const { QLocale locale = params.value("locale").toLocale(); - QVariantMap returns; - - QVariantList stateList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); - foreach (StateType stateType, deviceClass.stateTypes()) { - stateType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), stateType.displayName(), locale)); - stateList.append(pack(stateType)); - } - returns.insert("stateTypes", stateList); + DeviceClass translatedDeviceClass = NymeaCore::instance()->deviceManager()->translateDeviceClass(deviceClass, locale); + + QVariantMap returns; + returns.insert("stateTypes", pack(translatedDeviceClass.stateTypes())); return createReply(returns); } @@ -763,7 +756,7 @@ JsonReply *DeviceHandler::GetStateValues(const QVariantMap ¶ms) const } QVariantMap returns = statusToReply(Device::DeviceErrorNoError); - returns.insert("values", packDeviceStates(device)); + returns.insert("values", pack(device->states())); return createReply(returns); } @@ -811,73 +804,6 @@ JsonReply *DeviceHandler::GetBrowserItem(const QVariantMap ¶ms) const return jsonReply; } -Param DeviceHandler::unpackParam(const QVariantMap ¶m) -{ - if (param.keys().count() == 0) - return Param(); - - ParamTypeId paramTypeId = param.value("paramTypeId").toUuid(); - QVariant value = param.value("value"); - return Param(paramTypeId, value); -} - -ParamList DeviceHandler::unpackParams(const QVariantList ¶ms) -{ - ParamList paramList; - foreach (const QVariant ¶mVariant, params) { - paramList.append(unpackParam(paramVariant.toMap())); - } - - return paramList; -} - -QVariantMap DeviceHandler::packParam(const Param ¶m) -{ - QVariantMap variantMap; - variantMap.insert("paramTypeId", param.paramTypeId().toString()); - variantMap.insert("value", param.value()); - return variantMap; -} - -QVariantList DeviceHandler::packParams(const ParamList ¶mList) -{ - QVariantList ret; - foreach (const Param ¶m, paramList) { - ret << packParam(param); - } - return ret; -} - -QVariantMap DeviceHandler::packDevice(Device *device) -{ - QVariantMap variant; - variant.insert("id", device->id().toString()); - variant.insert("deviceClassId", device->deviceClassId().toString()); - variant.insert("name", device->name()); - variant.insert("params", packParams(device->params())); - variant.insert("settings", packParams(device->settings())); - - if (!device->parentId().isNull()) - variant.insert("parentId", device->parentId().toString()); - - variant.insert("states", packDeviceStates(device)); - variant.insert("setupComplete", device->setupComplete()); - return variant; -} - -QVariantList DeviceHandler::packDeviceStates(Device *device) -{ - DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(device->deviceClassId()); - QVariantList stateValues; - foreach (const StateType &stateType, deviceClass.stateTypes()) { - QVariantMap stateValue; - stateValue.insert("stateTypeId", stateType.id().toString()); - stateValue.insert("value", device->stateValue(stateType.id())); - stateValues.append(stateValue); - } - return stateValues; -} - QVariantMap DeviceHandler::packBrowserItem(const BrowserItem &item) { QVariantMap ret; @@ -900,67 +826,13 @@ QVariantMap DeviceHandler::packBrowserItem(const BrowserItem &item) return ret; } -QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) const -{ - ParamType translatedParamType = paramType; - translatedParamType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); - return pack(translatedParamType).toMap(); -} - -QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const -{ - QVariantMap variant; - variant.insert("id", eventType.id().toString()); - variant.insert("name", eventType.name()); - variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, eventType.displayName(), locale)); - variant.insert("index", eventType.index()); - - QVariantList paramTypes; - foreach (const ParamType ¶mType, eventType.paramTypes()) - paramTypes.append(packParamType(paramType, pluginId, locale)); - - variant.insert("paramTypes", paramTypes); - return variant; -} - -QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const -{ - QVariantMap variantMap; - variantMap.insert("id", actionType.id().toString()); - variantMap.insert("name", actionType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, actionType.displayName(), locale)); - variantMap.insert("index", actionType.index()); - QVariantList paramTypes; - foreach (const ParamType ¶mType, actionType.paramTypes()) - paramTypes.append(packParamType(paramType, pluginId, locale)); - - variantMap.insert("paramTypes", paramTypes); - return variantMap; -} - -QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods) const -{ - QVariantList ret; - if (createMethods.testFlag(DeviceClass::CreateMethodUser)) - ret << "CreateMethodUser"; - - if (createMethods.testFlag(DeviceClass::CreateMethodAuto)) - ret << "CreateMethodAuto"; - - if (createMethods.testFlag(DeviceClass::CreateMethodDiscovery)) - ret << "CreateMethodDiscovery"; - - return ret; -} - - void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config) { QVariantMap params; params.insert("pluginId", id); QVariantList configList; foreach (const Param ¶m, config) { - configList << packParam(param); + configList << pack(param); } params.insert("configuration", configList); emit PluginConfigurationChanged(params); @@ -985,14 +857,14 @@ void DeviceHandler::deviceRemovedNotification(const QUuid &deviceId) void DeviceHandler::deviceAddedNotification(Device *device) { QVariantMap params; - params.insert("device", packDevice(device)); + params.insert("device", pack(device)); emit DeviceAdded(params); } void DeviceHandler::deviceChangedNotification(Device *device) { QVariantMap params; - params.insert("device", packDevice(device)); + params.insert("device", pack(device)); emit DeviceChanged(params); } diff --git a/libnymea-core/jsonrpc/devicehandler.h b/libnymea-core/jsonrpc/devicehandler.h index 07dbb6c4..fcde2d3c 100644 --- a/libnymea-core/jsonrpc/devicehandler.h +++ b/libnymea-core/jsonrpc/devicehandler.h @@ -60,27 +60,8 @@ public: Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap ¶ms) const; - QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) const; -// QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale) const; - QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const; -// QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) const; - QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const; - QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods) const; -// QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) const; - QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor) const; - - static QVariantMap packParam(const Param ¶m); - static QVariantList packParams(const ParamList ¶mList); - - static QVariantMap packDevice(Device *device); - static QVariantList packDeviceStates(Device *device); - static QVariantMap packBrowserItem(const BrowserItem &item); - static Param unpackParam(const QVariantMap ¶m); - static ParamList unpackParams(const QVariantList ¶ms); - - signals: void PluginConfigurationChanged(const QVariantMap ¶ms); void StateChanged(const QVariantMap ¶ms); diff --git a/libnymea-core/jsonrpc/eventhandler.cpp b/libnymea-core/jsonrpc/eventhandler.cpp index 7d8fcbfc..283fa26d 100644 --- a/libnymea-core/jsonrpc/eventhandler.cpp +++ b/libnymea-core/jsonrpc/eventhandler.cpp @@ -38,7 +38,6 @@ */ #include "eventhandler.h" -#include "devicehandler.h" #include "nymeacore.h" #include "loggingcategories.h" diff --git a/libnymea-core/jsonrpc/ruleshandler.cpp b/libnymea-core/jsonrpc/ruleshandler.cpp index cd9075c8..12345a65 100644 --- a/libnymea-core/jsonrpc/ruleshandler.cpp +++ b/libnymea-core/jsonrpc/ruleshandler.cpp @@ -58,6 +58,7 @@ #include "loggingcategories.h" #include +#include namespace nymeaserver { @@ -245,13 +246,14 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap ¶ms) } QVariantMap returns; returns.insert("ruleError", enumValueName(RuleEngine::RuleErrorNoError)); - returns.insert("rule", packRule(rule)); + returns.insert("rule", pack(rule)); return createReply(returns); } JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) { - Rule rule = unpackRule(params); + Rule rule = unpack(params); + qWarning() << "Unpacked rule" << rule; rule.setId(RuleId::createRuleId()); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->addRule(rule); @@ -265,11 +267,15 @@ JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) JsonReply *RulesHandler::EditRule(const QVariantMap ¶ms) { - Rule rule = unpackRule(params); + Rule rule = unpack(params); + + // FIXME: Edit rule API currently has "ruleId" while the Rule type has "id". Auto unpacking will fail for this property + rule.setId(params.value("ruleId").toUuid()); + RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->editRule(rule); QVariantMap returns; if (status == RuleEngine::RuleErrorNoError) { - returns.insert("rule", packRule(NymeaCore::instance()->ruleEngine()->findRule(rule.id()))); + returns.insert("rule", pack(NymeaCore::instance()->ruleEngine()->findRule(rule.id()))); } returns.insert("ruleError", enumValueName(status)); return createReply(returns); @@ -344,7 +350,7 @@ void RulesHandler::ruleRemovedNotification(const RuleId &ruleId) void RulesHandler::ruleAddedNotification(const Rule &rule) { QVariantMap params; - params.insert("rule", packRule(rule)); + params.insert("rule", pack(rule)); emit RuleAdded(params); } @@ -361,7 +367,7 @@ void RulesHandler::ruleActiveChangedNotification(const Rule &rule) void RulesHandler::ruleConfigurationChangedNotification(const Rule &rule) { QVariantMap params; - params.insert("rule", packRule(rule)); + params.insert("rule", pack(rule)); emit RuleConfigurationChanged(params); } @@ -377,468 +383,4 @@ QVariantMap RulesHandler::packRuleDescription(const Rule &rule) return ruleDescriptionMap; } -QVariantMap RulesHandler::packParamDescriptor(const ParamDescriptor ¶mDescriptor) -{ - QVariantMap variantMap; - if (!paramDescriptor.paramTypeId().isNull()) { - variantMap.insert("paramTypeId", paramDescriptor.paramTypeId().toString()); - } else { - variantMap.insert("paramName", paramDescriptor.paramName()); - } - variantMap.insert("value", paramDescriptor.value()); - variantMap.insert("operator", enumValueName(paramDescriptor.operatorType())); - return variantMap; -} - -QVariantMap RulesHandler::packEventDescriptor(const EventDescriptor &eventDescriptor) -{ - QVariantMap variant; - if (eventDescriptor.type() == EventDescriptor::TypeDevice) { - variant.insert("eventTypeId", eventDescriptor.eventTypeId().toString()); - variant.insert("deviceId", eventDescriptor.deviceId().toString()); - } else { - variant.insert("interface", eventDescriptor.interface()); - variant.insert("interfaceEvent", eventDescriptor.interfaceEvent()); - } - QVariantList params; - foreach (const ParamDescriptor ¶mDescriptor, eventDescriptor.paramDescriptors()) - params.append(packParamDescriptor(paramDescriptor)); - - variant.insert("paramDescriptors", params); - return variant; -} - -QVariantMap RulesHandler::packStateEvaluator(const StateEvaluator &stateEvaluator) -{ - QVariantMap variantMap; - if (stateEvaluator.stateDescriptor().isValid()) - variantMap.insert("stateDescriptor", packStateDescriptor(stateEvaluator.stateDescriptor())); - - QVariantList childEvaluators; - foreach (const StateEvaluator &childEvaluator, stateEvaluator.childEvaluators()) - childEvaluators.append(packStateEvaluator(childEvaluator)); - - if (!childEvaluators.isEmpty() || stateEvaluator.stateDescriptor().isValid()) - variantMap.insert("operator", enumValueName(stateEvaluator.operatorType())); - - if (childEvaluators.count() > 0) - variantMap.insert("childEvaluators", childEvaluators); - - return variantMap; -} - -QVariantMap RulesHandler::packStateDescriptor(const StateDescriptor &stateDescriptor) -{ - QVariantMap variantMap; - if (stateDescriptor.type() == StateDescriptor::TypeDevice) { - variantMap.insert("stateTypeId", stateDescriptor.stateTypeId().toString()); - variantMap.insert("deviceId", stateDescriptor.deviceId().toString()); - } else { - variantMap.insert("interface", stateDescriptor.interface()); - variantMap.insert("interfaceState", stateDescriptor.interfaceState()); - } - variantMap.insert("value", stateDescriptor.stateValue()); - variantMap.insert("operator", enumValueName(stateDescriptor.operatorType())); - return variantMap; -} - -QVariantMap RulesHandler::packTimeDescriptor(const TimeDescriptor &timeDescriptor) -{ - QVariantMap timeDescriptorVariant; - - if (!timeDescriptor.calendarItems().isEmpty()) { - QVariantList calendarItems; - foreach (const CalendarItem &calendarItem, timeDescriptor.calendarItems()) - calendarItems.append(packCalendarItem(calendarItem)); - - timeDescriptorVariant.insert("calendarItems", calendarItems); - } - - if (!timeDescriptor.timeEventItems().isEmpty()) { - QVariantList timeEventItems; - foreach (const TimeEventItem &timeEventItem, timeDescriptor.timeEventItems()) - timeEventItems.append(packTimeEventItem(timeEventItem)); - - timeDescriptorVariant.insert("timeEventItems", timeEventItems); - } - - return timeDescriptorVariant; -} - -QVariantMap RulesHandler::packCalendarItem(const CalendarItem &calendarItem) -{ - QVariantMap calendarItemVariant; - calendarItemVariant.insert("duration", calendarItem.duration()); - - if (!calendarItem.dateTime().isNull() && calendarItem.dateTime().toTime_t() != 0) - calendarItemVariant.insert("datetime", calendarItem.dateTime().toTime_t()); - - if (!calendarItem.startTime().isNull()) - calendarItemVariant.insert("startTime", calendarItem.startTime().toString("hh:mm")); - - if (!calendarItem.repeatingOption().isEmtpy()) - calendarItemVariant.insert("repeating", packRepeatingOption(calendarItem.repeatingOption())); - - return calendarItemVariant; -} - -QVariantMap RulesHandler::packRepeatingOption(const RepeatingOption &option) -{ - QVariantMap optionVariant; - optionVariant.insert("mode", enumValueName(option.mode())); - if (!option.weekDays().isEmpty()) { - QVariantList weekDaysVariantList; - foreach (const int& weekDay, option.weekDays()) - weekDaysVariantList.append(QVariant(weekDay)); - - optionVariant.insert("weekDays", weekDaysVariantList); - } - - if (!option.monthDays().isEmpty()) { - QVariantList monthDaysVariantList; - foreach (const int& monthDay, option.monthDays()) - monthDaysVariantList.append(QVariant(monthDay)); - - optionVariant.insert("monthDays", monthDaysVariantList); - } - return optionVariant; -} - -QVariantMap RulesHandler::packTimeEventItem(const TimeEventItem &timeEventItem) -{ - QVariantMap timeEventItemVariant; - - if (!timeEventItem.dateTime().isNull() && timeEventItem.dateTime().toTime_t() != 0) - timeEventItemVariant.insert("datetime", timeEventItem.dateTime().toTime_t()); - - if (!timeEventItem.time().isNull()) - timeEventItemVariant.insert("time", timeEventItem.time().toString("hh:mm")); - - if (!timeEventItem.repeatingOption().isEmtpy()) - timeEventItemVariant.insert("repeating", packRepeatingOption(timeEventItem.repeatingOption())); - - return timeEventItemVariant; -} - -QVariantMap RulesHandler::packRuleActionParam(const RuleActionParam &ruleActionParam) -{ - QVariantMap variantMap; - if (!ruleActionParam.paramTypeId().isNull()) { - variantMap.insert("paramTypeId", ruleActionParam.paramTypeId().toString()); - } else { - variantMap.insert("paramName", ruleActionParam.paramName()); - } - - if (ruleActionParam.isEventBased()) { - variantMap.insert("eventTypeId", ruleActionParam.eventTypeId().toString()); - variantMap.insert("eventParamTypeId", ruleActionParam.eventParamTypeId().toString()); - } else if (ruleActionParam.isStateBased()) { - variantMap.insert("stateDeviceId", ruleActionParam.stateDeviceId().toString()); - variantMap.insert("stateTypeId", ruleActionParam.stateTypeId().toString()); - } else { - variantMap.insert("value", ruleActionParam.value()); - } - return variantMap; -} - -QVariantMap RulesHandler::packRuleAction(const RuleAction &ruleAction) -{ - QVariantMap variant; - if (ruleAction.type() == RuleAction::TypeDevice) { - variant.insert("deviceId", ruleAction.deviceId().toString()); - variant.insert("actionTypeId", ruleAction.actionTypeId().toString()); - } else if (ruleAction.type() == RuleAction::TypeBrowser) { - variant.insert("deviceId", ruleAction.deviceId().toString()); - variant.insert("browserItemId", ruleAction.browserItemId()); - } else { - variant.insert("interface", ruleAction.interface()); - variant.insert("interfaceAction", ruleAction.interfaceAction()); - } - QVariantList params; - foreach (const RuleActionParam &ruleActionParam, ruleAction.ruleActionParams()) - params.append(packRuleActionParam(ruleActionParam)); - - variant.insert("ruleActionParams", params); - return variant; -} - -QVariantMap RulesHandler::packRule(const Rule &rule) -{ - QVariantMap ruleMap; - ruleMap.insert("id", rule.id().toString()); - ruleMap.insert("name", rule.name()); - ruleMap.insert("enabled", rule.enabled()); - ruleMap.insert("active", rule.active()); - ruleMap.insert("executable", rule.executable()); - ruleMap.insert("timeDescriptor", packTimeDescriptor(rule.timeDescriptor())); - - QVariantList eventDescriptorList; - foreach (const EventDescriptor &eventDescriptor, rule.eventDescriptors()) - eventDescriptorList.append(packEventDescriptor(eventDescriptor)); - - ruleMap.insert("eventDescriptors", eventDescriptorList); - ruleMap.insert("stateEvaluator", packStateEvaluator(rule.stateEvaluator())); - - QVariantList actionList; - foreach (const RuleAction &action, rule.actions()) - actionList.append(packRuleAction(action)); - - ruleMap.insert("actions", actionList); - - QVariantList exitActionList; - foreach (const RuleAction &action, rule.exitActions()) - exitActionList.append(packRuleAction(action)); - - ruleMap.insert("exitActions", exitActionList); - return ruleMap; -} - -QList RulesHandler::unpackParamDescriptors(const QVariantList ¶mList) -{ - QList params; - foreach (const QVariant ¶mVariant, paramList) - params.append(unpackParamDescriptor(paramVariant.toMap())); - - return params; -} - -ParamDescriptor RulesHandler::unpackParamDescriptor(const QVariantMap ¶mMap) -{ - QString operatorString = paramMap.value("operator").toString(); - Types::ValueOperator valueOperator = enumNameToValue(operatorString); - - if (paramMap.contains("paramTypeId")) { - ParamDescriptor param = ParamDescriptor(ParamTypeId(paramMap.value("paramTypeId").toString()), paramMap.value("value")); - param.setOperatorType(valueOperator); - return param; - } - ParamDescriptor param = ParamDescriptor(paramMap.value("paramName").toString(), paramMap.value("value")); - param.setOperatorType(valueOperator); - return param; -} - -EventDescriptor RulesHandler::unpackEventDescriptor(const QVariantMap &eventDescriptorMap) -{ - EventTypeId eventTypeId(eventDescriptorMap.value("eventTypeId").toString()); - DeviceId eventDeviceId(eventDescriptorMap.value("deviceId").toString()); - QString interface = eventDescriptorMap.value("interface").toString(); - QString interfaceEvent = eventDescriptorMap.value("interfaceEvent").toString(); - QList eventParams = unpackParamDescriptors(eventDescriptorMap.value("paramDescriptors").toList()); - if (!eventDeviceId.isNull() && !eventTypeId.isNull()) { - return EventDescriptor(eventTypeId, eventDeviceId, eventParams); - } - return EventDescriptor(interface, interfaceEvent, eventParams); -} - -RepeatingOption RulesHandler::unpackRepeatingOption(const QVariantMap &repeatingOptionMap) -{ - RepeatingOption::RepeatingMode mode = enumNameToValue(repeatingOptionMap.value("mode").toString()); - - QList weekDays; - if (repeatingOptionMap.contains("weekDays")) { - foreach (const QVariant weekDayVariant, repeatingOptionMap.value("weekDays").toList()) { - weekDays.append(weekDayVariant.toInt()); - } - } - - QList monthDays; - if (repeatingOptionMap.contains("monthDays")) { - foreach (const QVariant monthDayVariant, repeatingOptionMap.value("monthDays").toList()) { - monthDays.append(monthDayVariant.toInt()); - } - } - - return RepeatingOption(mode, weekDays, monthDays); -} - -CalendarItem RulesHandler::unpackCalendarItem(const QVariantMap &calendarItemMap) -{ - CalendarItem calendarItem; - calendarItem.setDuration(calendarItemMap.value("duration").toUInt()); - - if (calendarItemMap.contains("datetime")) - calendarItem.setDateTime(QDateTime::fromTime_t(calendarItemMap.value("datetime").toUInt())); - - if (calendarItemMap.contains("startTime")) - calendarItem.setStartTime(QTime::fromString(calendarItemMap.value("startTime").toString(), "hh:mm")); - - if (calendarItemMap.contains("repeating")) - calendarItem.setRepeatingOption(unpackRepeatingOption(calendarItemMap.value("repeating").toMap())); - - return calendarItem; -} - -TimeDescriptor RulesHandler::unpackTimeDescriptor(const QVariantMap &timeDescriptorMap) -{ - TimeDescriptor timeDescriptor; - - if (timeDescriptorMap.contains("calendarItems")) { - QList calendarItems; - foreach (const QVariant &calendarItemValiant, timeDescriptorMap.value("calendarItems").toList()) { - calendarItems.append(unpackCalendarItem(calendarItemValiant.toMap())); - } - timeDescriptor.setCalendarItems(calendarItems); - } - - if (timeDescriptorMap.contains("timeEventItems")) { - QList timeEventItems; - foreach (const QVariant &timeEventItemValiant, timeDescriptorMap.value("timeEventItems").toList()) { - timeEventItems.append(unpackTimeEventItem(timeEventItemValiant.toMap())); - } - timeDescriptor.setTimeEventItems(timeEventItems); - } - - return timeDescriptor; -} - -TimeEventItem RulesHandler::unpackTimeEventItem(const QVariantMap &timeEventItemMap) -{ - TimeEventItem timeEventItem; - - if (timeEventItemMap.contains("datetime")) - timeEventItem.setDateTime(QDateTime::fromTime_t(timeEventItemMap.value("datetime").toUInt())); - - if (timeEventItemMap.contains("time")) - timeEventItem.setTime(timeEventItemMap.value("time").toTime()); - - if (timeEventItemMap.contains("repeating")) - timeEventItem.setRepeatingOption(unpackRepeatingOption(timeEventItemMap.value("repeating").toMap())); - - return timeEventItem; -} - -StateDescriptor RulesHandler::unpackStateDescriptor(const QVariantMap &stateDescriptorMap) -{ - StateTypeId stateTypeId(stateDescriptorMap.value("stateTypeId").toString()); - DeviceId deviceId(stateDescriptorMap.value("deviceId").toString()); - QString interface(stateDescriptorMap.value("interface").toString()); - QString interfaceState(stateDescriptorMap.value("interfaceState").toString()); - QVariant value = stateDescriptorMap.value("value"); - Types::ValueOperator operatorType = enumNameToValue(stateDescriptorMap.value("operator").toString()); - if (!deviceId.isNull() && !stateTypeId.isNull()) { - StateDescriptor stateDescriptor(stateTypeId, deviceId, value, operatorType); - return stateDescriptor; - } - StateDescriptor stateDescriptor(interface, interfaceState, value, operatorType); - return stateDescriptor; -} - -StateEvaluator RulesHandler::unpackStateEvaluator(const QVariantMap &stateEvaluatorMap) -{ - StateEvaluator ret(unpackStateDescriptor(stateEvaluatorMap.value("stateDescriptor").toMap())); - if (stateEvaluatorMap.contains("operator")) { - ret.setOperatorType(enumNameToValue(stateEvaluatorMap.value("operator").toString())); - } else { - ret.setOperatorType(Types::StateOperatorAnd); - } - - QList childEvaluators; - foreach (const QVariant &childEvaluator, stateEvaluatorMap.value("childEvaluators").toList()) - childEvaluators.append(unpackStateEvaluator(childEvaluator.toMap())); - - ret.setChildEvaluators(childEvaluators); - return ret; -} - -RuleActionParam RulesHandler::unpackRuleActionParam(const QVariantMap &ruleActionParamMap) -{ - if (ruleActionParamMap.keys().count() == 0) - return RuleActionParam(); - - ParamTypeId paramTypeId = ParamTypeId(ruleActionParamMap.value("paramTypeId").toString()); - QString paramName = ruleActionParamMap.value("paramName").toString(); - - RuleActionParam param; - if (paramTypeId.isNull()) { - param = RuleActionParam(paramName); - } else { - param = RuleActionParam(paramTypeId); - } - param.setValue(ruleActionParamMap.value("value")); - param.setEventTypeId(EventTypeId(ruleActionParamMap.value("eventTypeId").toString())); - param.setEventParamTypeId(ParamTypeId(ruleActionParamMap.value("eventParamTypeId").toString())); - param.setStateDeviceId(DeviceId(ruleActionParamMap.value("stateDeviceId").toString())); - param.setStateTypeId(StateTypeId(ruleActionParamMap.value("stateTypeId").toString())); - return param; -} - -RuleActionParams RulesHandler::unpackRuleActionParams(const QVariantList &ruleActionParamList) -{ - RuleActionParams ruleActionParams; - foreach (const QVariant ¶mVariant, ruleActionParamList) - ruleActionParams.append(unpackRuleActionParam(paramVariant.toMap())); - - return ruleActionParams; -} - -RuleAction RulesHandler::unpackRuleAction(const QVariantMap &ruleActionMap) -{ - ActionTypeId actionTypeId(ruleActionMap.value("actionTypeId").toString()); - DeviceId actionDeviceId(ruleActionMap.value("deviceId").toString()); - QString interface = ruleActionMap.value("interface").toString(); - QString interfaceAction = ruleActionMap.value("interfaceAction").toString(); - QString browserItemId = ruleActionMap.value("browserItemId").toString(); - RuleActionParams actionParamList = unpackRuleActionParams(ruleActionMap.value("ruleActionParams").toList()); - - if (!actionDeviceId.isNull() && !actionTypeId.isNull()) { - return RuleAction(actionTypeId, actionDeviceId, actionParamList); - } else if (!actionDeviceId.isNull() && !browserItemId.isNull()) { - return RuleAction(actionDeviceId, browserItemId); - } - return RuleAction(interface, interfaceAction, actionParamList); -} - -Rule RulesHandler::unpackRule(const QVariantMap &ruleMap) -{ - // The rule id will only be valid if unpacking for edit - RuleId ruleId = RuleId(ruleMap.value("ruleId").toString()); - - QString name = ruleMap.value("name", QString()).toString(); - - // By default enabled - bool enabled = ruleMap.value("enabled", true).toBool(); - - // By default executable - bool executable = ruleMap.value("executable", true).toBool(); - - StateEvaluator stateEvaluator = unpackStateEvaluator(ruleMap.value("stateEvaluator").toMap()); - TimeDescriptor timeDescriptor = unpackTimeDescriptor(ruleMap.value("timeDescriptor").toMap()); - - QList eventDescriptors; - if (ruleMap.contains("eventDescriptors")) { - QVariantList eventDescriptorVariantList = ruleMap.value("eventDescriptors").toList(); - foreach (const QVariant &eventDescriptorVariant, eventDescriptorVariantList) { - eventDescriptors.append(unpackEventDescriptor(eventDescriptorVariant.toMap())); - } - } - - QList actions; - if (ruleMap.contains("actions")) { - QVariantList actionsVariantList = ruleMap.value("actions").toList(); - foreach (const QVariant &actionVariant, actionsVariantList) { - actions.append(unpackRuleAction(actionVariant.toMap())); - } - } - - QList exitActions; - if (ruleMap.contains("exitActions")) { - QVariantList exitActionsVariantList = ruleMap.value("exitActions").toList(); - foreach (const QVariant &exitActionVariant, exitActionsVariantList) { - exitActions.append(unpackRuleAction(exitActionVariant.toMap())); - } - } - - Rule rule; - rule.setId(ruleId); - rule.setName(name); - rule.setTimeDescriptor(timeDescriptor); - rule.setStateEvaluator(stateEvaluator); - rule.setEventDescriptors(eventDescriptors); - rule.setActions(actions); - rule.setExitActions(exitActions); - rule.setEnabled(enabled); - rule.setExecutable(executable); - return rule; -} - } diff --git a/libnymea-core/jsonrpc/ruleshandler.h b/libnymea-core/jsonrpc/ruleshandler.h index 56b25a41..57e42edf 100644 --- a/libnymea-core/jsonrpc/ruleshandler.h +++ b/libnymea-core/jsonrpc/ruleshandler.h @@ -63,36 +63,7 @@ private slots: void ruleConfigurationChangedNotification(const Rule &rule); private: - static QVariantMap packRuleDescription(const Rule &rule); - static QVariantMap packParamDescriptor(const ParamDescriptor ¶mDescriptor); - static QVariantMap packEventDescriptor(const EventDescriptor &eventDescriptor); - static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator); - static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor); - static QVariantMap packTimeDescriptor(const TimeDescriptor &timeDescriptor); - static QVariantMap packCalendarItem(const CalendarItem &calendarItem); - static QVariantMap packRepeatingOption(const RepeatingOption &option); - static QVariantMap packTimeEventItem(const TimeEventItem &timeEventItem); - static QVariantMap packRuleActionParam(const RuleActionParam &ruleActionParam); - static QVariantMap packRuleAction(const RuleAction &ruleAction); - - static QVariantMap packRule(const Rule &rule); - - static QList unpackParamDescriptors(const QVariantList ¶mList); - static ParamDescriptor unpackParamDescriptor(const QVariantMap ¶mMap); - static EventDescriptor unpackEventDescriptor(const QVariantMap &eventDescriptorMap); - static RepeatingOption unpackRepeatingOption(const QVariantMap &repeatingOptionMap); - static CalendarItem unpackCalendarItem(const QVariantMap &calendarItemMap); - static TimeDescriptor unpackTimeDescriptor(const QVariantMap &timeDescriptorMap); - static TimeEventItem unpackTimeEventItem(const QVariantMap &timeEventItemMap); - static StateDescriptor unpackStateDescriptor(const QVariantMap &stateDescriptorMap); - static StateEvaluator unpackStateEvaluator(const QVariantMap &stateEvaluatorMap); - static RuleActionParam unpackRuleActionParam(const QVariantMap &ruleActionParamMap); - static RuleActionParams unpackRuleActionParams(const QVariantList &ruleActionParamList); - static RuleAction unpackRuleAction(const QVariantMap &ruleActionMap); - - static Rule unpackRule(const QVariantMap &ruleMap); - - + QVariantMap packRuleDescription(const Rule &rule); }; } diff --git a/libnymea-core/jsonrpc/statehandler.cpp b/libnymea-core/jsonrpc/statehandler.cpp index ed103716..07eb1b88 100644 --- a/libnymea-core/jsonrpc/statehandler.cpp +++ b/libnymea-core/jsonrpc/statehandler.cpp @@ -33,7 +33,6 @@ */ #include "statehandler.h" -#include "devicehandler.h" #include "nymeacore.h" #include "loggingcategories.h" diff --git a/libnymea-core/logging/logentry.cpp b/libnymea-core/logging/logentry.cpp index 290952ab..159ee7bc 100644 --- a/libnymea-core/logging/logentry.cpp +++ b/libnymea-core/logging/logentry.cpp @@ -193,4 +193,9 @@ QVariant LogEntries::get(int index) const return QVariant::fromValue(at(index)); } +void LogEntries::put(const QVariant &variant) +{ + append(variant.value()); +} + } diff --git a/libnymea-core/logging/logentry.h b/libnymea-core/logging/logentry.h index 4561aa2c..706175c1 100644 --- a/libnymea-core/logging/logentry.h +++ b/libnymea-core/logging/logentry.h @@ -100,6 +100,7 @@ public: LogEntries(); LogEntries(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; QDebug operator<<(QDebug dbg, const LogEntry &entry); diff --git a/libnymea-core/ruleengine/rule.cpp b/libnymea-core/ruleengine/rule.cpp index 2e0259a7..8d2b9b46 100644 --- a/libnymea-core/ruleengine/rule.cpp +++ b/libnymea-core/ruleengine/rule.cpp @@ -49,7 +49,7 @@ Rule::Rule(): m_eventDescriptors(QList()), m_actions(QList()), m_exitActions(QList()), - m_enabled(false), + m_enabled(true), m_active(false), m_statesActive(false), m_timeActive(false), @@ -128,37 +128,37 @@ void Rule::setStateEvaluator(const StateEvaluator &stateEvaluator) } /*! Returns the \l{EventDescriptor} for this Rule.*/ -QList Rule::eventDescriptors() const +EventDescriptors Rule::eventDescriptors() const { return m_eventDescriptors; } /*! Sets the \a eventDescriptors of this \l{Rule}. */ -void Rule::setEventDescriptors(const QList &eventDescriptors) +void Rule::setEventDescriptors(const EventDescriptors &eventDescriptors) { m_eventDescriptors = eventDescriptors; } /*! Returns the \l{RuleAction}{RuleActions} to be executed when this Rule is matched and states match. */ -QList Rule::actions() const +RuleActions Rule::actions() const { return m_actions; } /*! Sets the \a actions of this \l{Rule}. */ -void Rule::setActions(const QList actions) +void Rule::setActions(const RuleActions actions) { m_actions = actions; } /*! Returns the \l{RuleAction}{RuleActions} to be executed when this Rule leaves the active state. */ -QList Rule::exitActions() const +RuleActions Rule::exitActions() const { return m_exitActions; } /*! Sets the \a exitActions of this \l{Rule}. */ -void Rule::setExitActions(const QList exitActions) +void Rule::setExitActions(const RuleActions exitActions) { m_exitActions = exitActions; } @@ -265,4 +265,9 @@ QVariant Rules::get(int index) const return QVariant::fromValue(at(index)); } +void Rules::put(const QVariant &variant) +{ + append(variant.value()); +} + } diff --git a/libnymea-core/ruleengine/rule.h b/libnymea-core/ruleengine/rule.h index cb3fbfd4..5759a0ef 100644 --- a/libnymea-core/ruleengine/rule.h +++ b/libnymea-core/ruleengine/rule.h @@ -35,16 +35,16 @@ namespace nymeaserver { class Rule { Q_GADGET - Q_PROPERTY(QUuid id READ id WRITE setId) + Q_PROPERTY(QUuid id READ id WRITE setId USER true) Q_PROPERTY(QString name READ name WRITE setName) - Q_PROPERTY(bool active READ active) - Q_PROPERTY(bool enabled READ enabled WRITE setEnabled) - Q_PROPERTY(bool executable READ executable WRITE setExecutable) - Q_PROPERTY(EventDescriptors eventDescriptors READ eventDescriptors WRITE setEventDescriptors) + Q_PROPERTY(bool active READ active USER true) + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled USER true) + Q_PROPERTY(bool executable READ executable WRITE setExecutable USER true) + Q_PROPERTY(EventDescriptors eventDescriptors READ eventDescriptors WRITE setEventDescriptors USER true) Q_PROPERTY(RuleActions actions READ actions WRITE setActions) - Q_PROPERTY(RuleActions exitActions READ exitActions WRITE setExitActions) - Q_PROPERTY(StateEvaluator stateEvaluator READ stateEvaluator WRITE setStateEvaluator) - Q_PROPERTY(TimeDescriptor timeDescriptor READ timeDescriptor WRITE setTimeDescriptor) + Q_PROPERTY(RuleActions exitActions READ exitActions WRITE setExitActions USER true) + Q_PROPERTY(nymeaserver::StateEvaluator stateEvaluator READ stateEvaluator WRITE setStateEvaluator USER true) + Q_PROPERTY(TimeDescriptor timeDescriptor READ timeDescriptor WRITE setTimeDescriptor USER true) public: Rule(); @@ -65,14 +65,14 @@ public: StateEvaluator stateEvaluator() const; void setStateEvaluator(const StateEvaluator &stateEvaluator); - QList eventDescriptors() const; - void setEventDescriptors(const QList &eventDescriptors); + EventDescriptors eventDescriptors() const; + void setEventDescriptors(const EventDescriptors &eventDescriptors); - QList actions() const; - void setActions(const QList actions); + RuleActions actions() const; + void setActions(const RuleActions actions); - QList exitActions() const; - void setExitActions(const QList exitActions); + RuleActions exitActions() const; + void setExitActions(const RuleActions exitActions); bool enabled() const; void setEnabled(const bool &enabled); @@ -95,9 +95,9 @@ private: QString m_name; TimeDescriptor m_timeDescriptor; StateEvaluator m_stateEvaluator; - QList m_eventDescriptors; - QList m_actions; - QList m_exitActions; + EventDescriptors m_eventDescriptors; + RuleActions m_actions; + RuleActions m_exitActions; bool m_enabled; bool m_active; @@ -114,6 +114,7 @@ public: Rules(); Rules(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; QDebug operator<<(QDebug dbg, const Rule &rule); diff --git a/libnymea-core/ruleengine/ruleaction.cpp b/libnymea-core/ruleengine/ruleaction.cpp index 5995ed07..a3a53789 100644 --- a/libnymea-core/ruleengine/ruleaction.cpp +++ b/libnymea-core/ruleengine/ruleaction.cpp @@ -300,3 +300,8 @@ QVariant RuleActions::get(int index) const { return QVariant::fromValue(at(index)); } + +void RuleActions::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea-core/ruleengine/ruleaction.h b/libnymea-core/ruleengine/ruleaction.h index f94fe2e8..02a15690 100644 --- a/libnymea-core/ruleengine/ruleaction.h +++ b/libnymea-core/ruleengine/ruleaction.h @@ -102,6 +102,7 @@ public: RuleActions(); RuleActions(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(RuleActions) diff --git a/libnymea-core/ruleengine/ruleactionparam.cpp b/libnymea-core/ruleengine/ruleactionparam.cpp index 10728861..349a3e41 100644 --- a/libnymea-core/ruleengine/ruleactionparam.cpp +++ b/libnymea-core/ruleengine/ruleactionparam.cpp @@ -312,3 +312,8 @@ QVariant RuleActionParams::get(int index) const { return QVariant::fromValue(at(index)); } + +void RuleActionParams::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea-core/ruleengine/ruleactionparam.h b/libnymea-core/ruleengine/ruleactionparam.h index 5ed19acd..5f1a1407 100644 --- a/libnymea-core/ruleengine/ruleactionparam.h +++ b/libnymea-core/ruleengine/ruleactionparam.h @@ -101,6 +101,7 @@ public: bool hasParam(const ParamTypeId &ruleActionParamTypeId) const; bool hasParam(const QString &ruleActionParamName) const; Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); QVariant paramValue(const ParamTypeId &ruleActionParamName) const; bool setParamValue(const ParamTypeId &ruleActionParamTypeId, const QVariant &value); RuleActionParams operator<<(const RuleActionParam &ruleActionParam); diff --git a/libnymea-core/ruleengine/stateevaluator.cpp b/libnymea-core/ruleengine/stateevaluator.cpp index c6a7f623..677c122d 100644 --- a/libnymea-core/ruleengine/stateevaluator.cpp +++ b/libnymea-core/ruleengine/stateevaluator.cpp @@ -69,13 +69,13 @@ void StateEvaluator::setStateDescriptor(const StateDescriptor &stateDescriptor) } /*! Returns the list of child \l {StateEvaluator}{StateEvaluators} of this \l StateEvaluator. */ -QList StateEvaluator::childEvaluators() const +StateEvaluators StateEvaluator::childEvaluators() const { return m_childEvaluators; } /*! Sets the list of child evaluators of this \l StateEvaluator to the given \a stateEvaluators.*/ -void StateEvaluator::setChildEvaluators(const QList &stateEvaluators) +void StateEvaluator::setChildEvaluators(const StateEvaluators &stateEvaluators) { m_childEvaluators = stateEvaluators; } @@ -389,7 +389,14 @@ StateEvaluators::StateEvaluators(const QList &other): QList()); +} + } diff --git a/libnymea-core/ruleengine/stateevaluator.h b/libnymea-core/ruleengine/stateevaluator.h index 434a22a3..cdb3a596 100644 --- a/libnymea-core/ruleengine/stateevaluator.h +++ b/libnymea-core/ruleengine/stateevaluator.h @@ -30,12 +30,24 @@ class NymeaSettings; namespace nymeaserver { +class StateEvaluator; + +class StateEvaluators: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + StateEvaluators(); + StateEvaluators(const QList &other); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); +}; class StateEvaluator { Q_GADGET Q_PROPERTY(StateDescriptor stateDescriptor READ stateDescriptor WRITE setStateDescriptor USER true) - Q_PROPERTY(StateEvaluators childEvaluators READ childEvaluators WRITE setChildEvaluators USER true) + Q_PROPERTY(nymeaserver::StateEvaluators childEvaluators READ childEvaluators WRITE setChildEvaluators USER true) Q_PROPERTY(Types::StateOperator operator READ operatorType WRITE setOperatorType USER true) public: StateEvaluator(const StateDescriptor &stateDescriptor); @@ -44,8 +56,8 @@ public: StateDescriptor stateDescriptor() const; void setStateDescriptor(const StateDescriptor &stateDescriptor); - QList childEvaluators() const; - void setChildEvaluators(const QList &childEvaluators); + StateEvaluators childEvaluators() const; + void setChildEvaluators(const StateEvaluators &childEvaluators); void appendEvaluator(const StateEvaluator &stateEvaluator); Types::StateOperator operatorType() const; @@ -70,19 +82,11 @@ private: Types::StateOperator m_operatorType; }; -class StateEvaluators: public QList -{ - Q_GADGET - Q_PROPERTY(int count READ count) -public: - StateEvaluators(); - StateEvaluators(const QList &other); - Q_INVOKABLE QVariant get(int index) const; -}; QDebug operator<<(QDebug dbg, const StateEvaluator &stateEvaluator); } +Q_DECLARE_METATYPE(nymeaserver::StateEvaluator) Q_DECLARE_METATYPE(nymeaserver::StateEvaluators) #endif // STATEEVALUATOR_H diff --git a/libnymea-core/tagging/tag.cpp b/libnymea-core/tagging/tag.cpp index 68945958..df8b2df8 100644 --- a/libnymea-core/tagging/tag.cpp +++ b/libnymea-core/tagging/tag.cpp @@ -132,4 +132,9 @@ QVariant Tags::get(int index) const return QVariant::fromValue(at(index)); } +void Tags::put(const QVariant &variant) +{ + append(variant.value()); +} + } diff --git a/libnymea-core/tagging/tag.h b/libnymea-core/tagging/tag.h index a58ed1fb..1a201846 100644 --- a/libnymea-core/tagging/tag.h +++ b/libnymea-core/tagging/tag.h @@ -74,6 +74,7 @@ public: Tags(); Tags(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; QDebug operator<<(QDebug dbg, const Tag &tag); diff --git a/libnymea-core/usermanager/tokeninfo.cpp b/libnymea-core/usermanager/tokeninfo.cpp index 03d04c16..0eb385a8 100644 --- a/libnymea-core/usermanager/tokeninfo.cpp +++ b/libnymea-core/usermanager/tokeninfo.cpp @@ -34,6 +34,11 @@ namespace nymeaserver { +TokenInfo::TokenInfo() +{ + +} + /*! Constructs a new token info with the given \a id, \a username, \a creationTime and \a deviceName. */ TokenInfo::TokenInfo(const QUuid &id, const QString &username, const QDateTime &creationTime, const QString &deviceName): m_id(id), diff --git a/libnymea-core/usermanager/tokeninfo.h b/libnymea-core/usermanager/tokeninfo.h index ccc2b7c6..7e3c73ca 100644 --- a/libnymea-core/usermanager/tokeninfo.h +++ b/libnymea-core/usermanager/tokeninfo.h @@ -23,7 +23,7 @@ #include #include -#include +#include namespace nymeaserver { @@ -36,6 +36,7 @@ class TokenInfo Q_PROPERTY(QString deviveName READ deviceName) public: + TokenInfo(); TokenInfo(const QUuid &id, const QString &username, const QDateTime &creationTime, const QString &deviceName); QUuid id() const; @@ -51,5 +52,6 @@ private: }; } +Q_DECLARE_METATYPE(nymeaserver::TokenInfo) #endif // TOKENINFO_H diff --git a/libnymea/devices/device.cpp b/libnymea/devices/device.cpp index f138181a..a0e2b0b4 100644 --- a/libnymea/devices/device.cpp +++ b/libnymea/devices/device.cpp @@ -271,7 +271,7 @@ void Device::setSettingValue(const ParamTypeId ¶mTypeId, const QVariant &val } /*! Returns the states of this Device. It must match the \l{StateType} description in the associated \l{DeviceClass}. */ -QList Device::states() const +States Device::states() const { return m_states; } @@ -283,7 +283,7 @@ bool Device::hasParam(const ParamTypeId ¶mTypeId) const } /*! Set the \l{State}{States} of this \l{Device} to the given \a states.*/ -void Device::setStates(const QList &states) +void Device::setStates(const States &states) { m_states = states; } diff --git a/libnymea/devices/device.h b/libnymea/devices/device.h index ac24b82b..3ddc64f4 100644 --- a/libnymea/devices/device.h +++ b/libnymea/devices/device.h @@ -106,9 +106,9 @@ public: QVariant setting(const ParamTypeId ¶mTypeId) const; void setSettingValue(const ParamTypeId ¶mTypeId, const QVariant &value); - QList states() const; + States states() const; bool hasState(const StateTypeId &stateTypeId) const; - void setStates(const QList &states); + void setStates(const States &states); QVariant stateValue(const StateTypeId &stateTypeId) const; void setStateValue(const StateTypeId &stateTypeId, const QVariant &value); @@ -144,7 +144,7 @@ private: QString m_name; ParamList m_params; ParamList m_settings; - QList m_states; + States m_states; bool m_setupComplete = false; bool m_autoCreated = false; }; diff --git a/libnymea/devices/devicemanager.cpp b/libnymea/devices/devicemanager.cpp index a2bb77e4..eb2044ca 100644 --- a/libnymea/devices/devicemanager.cpp +++ b/libnymea/devices/devicemanager.cpp @@ -37,5 +37,8 @@ DeviceManager::DeviceManager(QObject *parent) : QObject(parent) { - + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); } diff --git a/libnymea/devices/deviceplugin.h b/libnymea/devices/deviceplugin.h index 0b6726c1..8d485312 100644 --- a/libnymea/devices/deviceplugin.h +++ b/libnymea/devices/deviceplugin.h @@ -55,6 +55,7 @@ #include #include #include +#include class DeviceManager; @@ -140,8 +141,8 @@ private: PluginMetadata m_metaData; ParamList m_config; }; - Q_DECLARE_INTERFACE(DevicePlugin, "io.nymea.DevicePlugin") +Q_DECLARE_METATYPE(DevicePlugin*) class LIBNYMEA_EXPORT DevicePlugins: public QList @@ -151,5 +152,6 @@ public: DevicePlugins(const QList &other); DevicePlugin* findById(const PluginId &id) const; }; +Q_DECLARE_METATYPE(DevicePlugins) #endif // DEVICEPLUGIN_H diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 5de27436..df43d22c 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -27,6 +27,7 @@ JsonHandler::JsonHandler(QObject *parent) : QObject(parent) { + qRegisterMetaType(); registerEnum(); } @@ -155,13 +156,52 @@ JsonReply *JsonHandler::createAsyncReply(const QString &method) const return JsonReply::createAsyncReply(const_cast(this), method); } +void JsonHandler::registerObject(const QMetaObject &metaObject) +{ + QString className = QString(metaObject.className()).split("::").last(); + QVariantMap description; + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + QString name = metaProperty.name(); + if (name == "objectName") { + continue; // Skip QObject's objectName property + } + if (metaProperty.isUser()) { + name.prepend("o:"); + } + QVariant typeName; + if (metaProperty.type() == QVariant::UserType) { + if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { + typeName = QString("$ref:BasicType"); + } else if (QString(metaProperty.typeName()).startsWith("QList")) { + QString elementType = QString(metaProperty.typeName()).remove("QList<").remove(">"); + QVariant::Type variantType = QVariant::nameToType(elementType.toUtf8()); + typeName = QVariantList() << enumValueName(variantTypeToBasicType(variantType)); + } else { + typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); + } + } else if (metaProperty.isEnumType()) { + typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); + } else if (metaProperty.isFlagType()) { + typeName = QVariantList() << "$ref:" + m_flagsEnums.value(metaProperty.name()); + } else if (metaProperty.type() == QVariant::List) { + typeName = QVariantList() << enumValueName(Variant); + } else { + typeName = enumValueName(variantTypeToBasicType(metaProperty.type())); + } + description.insert(name, typeName); + } + m_objects.insert(className, description); + m_metaObjects.insert(className, metaObject); +} + QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) const { QString className = QString(metaObject.className()).split("::").last(); if (m_listMetaObjects.contains(className)) { QVariantList ret; QMetaProperty countProperty = metaObject.property(metaObject.indexOfProperty("count")); - QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(metaObject.className())); + QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(className)); int count = countProperty.readOnGadget(value).toInt(); QMetaMethod getMethod = metaObject.method(metaObject.indexOfMethod("get(int)")); for (int i = 0; i < count; i++) { @@ -182,12 +222,18 @@ QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) con continue; } + QVariant propertyValue = metaProperty.readOnGadget(value); + // If it's optional and empty, we may skip it + if (metaProperty.isUser() && (!propertyValue.isValid() || propertyValue.isNull())) { + continue; + } + // Pack flags if (metaProperty.isFlagType()) { QString flagName = QString(metaProperty.typeName()).split("::").last(); Q_ASSERT_X(m_metaFlags.contains(flagName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(className).arg(flagName).toUtf8()); QMetaEnum metaFlag = m_metaFlags.value(flagName); - int flagValue = metaProperty.readOnGadget(value).toInt(); + int flagValue = propertyValue.toInt(); QStringList flags; for (int i = 0; i < metaFlag.keyCount(); i++) { if ((metaFlag.value(i) & flagValue) > 0) { @@ -203,118 +249,182 @@ QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) con QString enumName = QString(metaProperty.typeName()).split("::").last(); Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(className).arg(metaProperty.typeName()).toUtf8()); QMetaEnum metaEnum = m_metaEnums.value(enumName); - ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); + ret.insert(metaProperty.name(), metaEnum.key(propertyValue.toInt())); continue; } // Basic type/Variant type if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { QMetaEnum metaEnum = QMetaEnum::fromType(); - ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); + ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(propertyValue.template value()))); continue; } // Our own objects if (metaProperty.type() == QVariant::UserType) { - if (m_listMetaObjects.contains(metaProperty.typeName())) { - QMetaObject entryMetaObject = m_listMetaObjects.value(metaProperty.typeName()); - ret.insert(metaProperty.name(), pack(entryMetaObject, metaProperty.readOnGadget(value).data())); + QString propertyTypeName = QString(metaProperty.typeName()).split("::").last(); + if (m_listMetaObjects.contains(propertyTypeName)) { + QMetaObject entryMetaObject = m_listMetaObjects.value(propertyTypeName); + QVariant packed = pack(entryMetaObject, propertyValue.data()); + if (!metaProperty.isUser() || packed.toList().count() > 0) { + ret.insert(metaProperty.name(), packed); + } continue; } - if (m_metaObjects.contains(metaProperty.typeName())) { - QMetaObject entryMetaObject = m_metaObjects.value(metaProperty.typeName()); - ret.insert(metaProperty.name(), pack(entryMetaObject, metaProperty.readOnGadget(value).data())); + if (m_metaObjects.contains(propertyTypeName)) { + QMetaObject entryMetaObject = m_metaObjects.value(propertyTypeName); + QVariant packed = pack(entryMetaObject, propertyValue.data()); + int isValidIndex = entryMetaObject.indexOfMethod("isValid()"); + bool isValid = true; + if (isValidIndex >= 0) { + QMetaMethod isValidMethod = entryMetaObject.method(isValidIndex); + isValidMethod.invokeOnGadget(propertyValue.data(), Q_RETURN_ARG(bool, isValid)); + } + if (isValid || !metaProperty.isUser()) { + ret.insert(metaProperty.name(), packed); + } continue; } - Q_ASSERT_X(false, this->metaObject()->className(), QString("Unregistered property type: %1").arg(metaProperty.typeName()).toUtf8()); - qCWarning(dcJsonRpc()) << "Cannot pack property of unregistered object type" << metaProperty.typeName(); + // Manually converting QList... Only QVariantList is known to the meta system + if (propertyTypeName.startsWith("QList")) { + qWarning() << "Packing list" << metaProperty.name() << propertyValue.toList(); + QVariantList list; + foreach (int entry, propertyValue.value>()) { + list << entry; + } + if (!list.isEmpty() || !metaProperty.isUser()) { + ret.insert(metaProperty.name(), list); + } + continue; + } + + Q_ASSERT_X(false, this->metaObject()->className(), QString("Unregistered property type: %1").arg(propertyTypeName).toUtf8()); + qCWarning(dcJsonRpc()) << "Cannot pack property of unregistered object type" << propertyTypeName; continue; } - // Standard properties, QString, int etc... If it's not optional, or if it's not empty, pack it up - if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { - QVariant variant = metaProperty.readOnGadget(value); - // Special treatment for QDateTime (converting to time_t) - if (metaProperty.type() == QVariant::DateTime) { - variant = variant.toDateTime().toTime_t(); + // Standard properties, QString, int etc... + // Special treatment for QDateTime (converting to time_t) + if (metaProperty.type() == QVariant::DateTime) { + QDateTime dateTime = propertyValue.toDateTime(); + if (metaProperty.isUser() && dateTime.toTime_t() == 0) { + continue; } - ret.insert(metaProperty.name(), variant); + propertyValue = propertyValue.toDateTime().toTime_t(); + } else if (metaProperty.type() == QVariant::Time) { + propertyValue = propertyValue.toTime().toString("hh:mm"); } + ret.insert(metaProperty.name(), propertyValue); } return ret; } Q_ASSERT_X(false, this->metaObject()->className(), QString("Unregistered object type: %1").arg(className).toUtf8()); qCWarning(dcJsonRpc()) << "Cannot pack object of unregistered type" << className; - return QVariant(); -// QVariantMap ret; -//// qWarning() << "+ Packing" << metaObject.className(); -// for (int i = 0; i < metaObject.propertyCount(); i++) { -// QMetaProperty metaProperty = metaObject.property(i); -// if (metaProperty.name() == QStringLiteral("objectName")) { -// continue; // Skip QObject's objectName property -// } - -// QVariant val = metaProperty.readOnGadget(value); -//// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName(); -//// qWarning() << "|-- All list types:" << m_listMetaObjects.keys(); -// if (metaProperty.type() == QVariant::UserType) { -// if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { -// QMetaEnum metaEnum = QMetaEnum::fromType(); -//// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt()); -// ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); -// } else if (m_listMetaObjects.contains(metaProperty.typeName())) { -// QVariant listObject = metaProperty.readOnGadget(value); -// QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName()); -// QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count")); -// int listCount = countProperty.readOnGadget(listObject.constData()).toInt(); -//// qWarning() << "Packing list type" << listObject << "count is" << listCount; -// QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)")); -//// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)"); - -// QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className())); -// QVariantList list; -// for (int i = 0; i < listCount; i++) { -// QVariant entry; -// metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); -//// qWarning() << "|---Feckin hell" << entry; - -// list.append(pack(entryMetaObject, entry.data())); -// } - -// ret.insert(metaProperty.name(), list); - - -// } else { -// Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); -// } -// } else if (metaProperty.isFlagType()) { -// QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last()); -//// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name())); -// int flagValue = metaProperty.readOnGadget(value).toInt(); -//// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type(); -// QStringList flags; -// for (int i = 0; i < metaFlag.keyCount(); i++) { -//// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i); -// if ((metaFlag.value(i) & flagValue) > 0) { -// flags.append(metaFlag.key(i)); -// } -// } -// ret.insert(metaProperty.name(), flags); -// } else if (metaProperty.isEnumType()) { -// QString enumName = QString(metaProperty.typeName()).split("::").last(); -// Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); -// QMetaEnum metaEnum = m_metaEnums.value(enumName); -//// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys(); -// ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); -// } else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { -//// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value); -// ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); -// } -// } -// return ret; - + return QVariant(); } +QVariant JsonHandler::unpack(const QMetaObject &metaObject, const QVariant &value) const +{ + QString typeName = QString(metaObject.className()).split("::").last(); + + // If it's a list object, loop over count + if (m_listMetaObjects.contains(typeName)) { + qWarning() << "** Unpacking" << typeName; + if (value.type() != QVariant::List) { + qCWarning(dcJsonRpc()) << "Cannot unpack" << typeName << ". Value is not in list format:" << value; + return QVariant(); + } + + QVariantList list = value.toList(); + + int typeId = QMetaType::type(metaObject.className()); + void* ptr = QMetaType::create(typeId); + Q_ASSERT_X(typeId != 0, this->metaObject()->className(), QString("Cannot handle unregistered meta type %1").arg(metaObject.className()).toUtf8()); + + QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(typeName)); + QMetaMethod putMethod = metaObject.method(metaObject.indexOfMethod("put(QVariant)")); + + foreach (const QVariant &variant, list) { + QVariant value = unpack(entryMetaObject, variant); + qWarning() << "Putting" << value << putMethod.name() << ptr << typeId; + putMethod.invokeOnGadget(ptr, Q_ARG(QVariant, value)); + } + + QVariant ret = QVariant(typeId, ptr); + QMetaType::destroy(typeId, ptr); + return ret; + } + + // if it's an object, loop over all properties + if (m_metaObjects.contains(typeName)) { + qWarning() << "*** Unpacking" << typeName; + QVariantMap map = value.toMap(); + int typeId = QMetaType::type(metaObject.className()); + Q_ASSERT_X(typeId != 0, this->metaObject()->className(), QString("Cannot handle unregistered meta type %1").arg(typeName).toUtf8()); + void* ptr = QMetaType::create(typeId); + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + if (metaProperty.name() == QStringLiteral("objectName")) { + continue; + } + if (!metaProperty.isWritable()) { + continue; + } + if (!metaProperty.isUser()) { + Q_ASSERT_X(map.contains(metaProperty.name()), this->metaObject()->className(), QString("Missing property %1 in map.").arg(metaProperty.name()).toUtf8()); + } + + if (map.contains(metaProperty.name())) { + + QString propertyTypeName = QString(metaProperty.typeName()).split("::").last(); + QVariant variant = map.value(metaProperty.name()); + + // recurse into child lists + if (m_listMetaObjects.contains(propertyTypeName)) { + QMetaObject propertyMetaObject = m_listMetaObjects.value(propertyTypeName); + qWarning() << "Entering list object" << propertyTypeName << propertyMetaObject.className(); + metaProperty.writeOnGadget(ptr, unpack(propertyMetaObject, variant)); + continue; + } + + // recurse into child objects + if (m_metaObjects.contains(propertyTypeName)) { + QMetaObject propertyMetaObject = m_metaObjects.value(propertyTypeName); + metaProperty.writeOnGadget(ptr, unpack(propertyMetaObject, variant)); + continue; + } + + if (metaProperty.typeName() == QStringLiteral("QList")) { + QList intList; + foreach (const QVariant &val, variant.toList()) { + intList.append(val.toInt()); + } + metaProperty.writeOnGadget(ptr, QVariant::fromValue(intList)); + continue; + } + + // Special treatment for QDateTime (convert from time_t) + if (metaProperty.type() == QVariant::DateTime) { + variant = QDateTime::fromTime_t(variant.toUInt()); + } else if (metaProperty.type() == QVariant::Time) { + variant = QTime::fromString(variant.toString(), "hh:mm"); + } + + // For basic properties just write the veriant as is + metaProperty.writeOnGadget(ptr, variant); + } + + } + QVariant ret = QVariant(typeId, ptr); + QMetaType::destroy(typeId, ptr); + return ret; + } + + return QVariant(); +} + + + diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index 3d1ee9c4..d4f5fa5f 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -72,13 +72,16 @@ public: static QVariant::Type basicTypeToVariantType(BasicType basicType); template QVariant pack(const T &value) const; - template T unpack(const QVariantMap &map) const; + template QVariant pack(T *value) const; + template T unpack(const QVariant &value) const; protected: template void registerEnum(); template void registerEnum(); template void registerObject(); + template void registerUncreatableObject(); template void registerObject(); + template void registerList(BasicTypeName typeName); void registerObject(const QString &name, const QVariantMap &object); void registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool deprecated = false); void registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool deprecated = false); @@ -87,7 +90,11 @@ protected: JsonReply *createAsyncReply(const QString &method) const; private: + + void registerObject(const QMetaObject &metaObject); + QVariant pack(const QMetaObject &metaObject, const void *gadget) const; + QVariant unpack(const QMetaObject &metaObject, const QVariant &value) const; private: QVariantMap m_enums; @@ -130,50 +137,23 @@ void JsonHandler::registerEnum() template void JsonHandler::registerObject() { - qRegisterMetaType(); + qRegisterMetaType(); QMetaObject metaObject = ObjectType::staticMetaObject; - QString className = QString(metaObject.className()).split("::").last(); - QVariantMap description; - for (int i = 0; i < metaObject.propertyCount(); i++) { - QMetaProperty metaProperty = metaObject.property(i); - QString name = metaProperty.name(); - if (name == "objectName") { - continue; // Skip QObject's objectName property - } - if (metaProperty.isUser()) { - name.prepend("o:"); - } - QVariant typeName; -// qWarning() << ".-.-.-.-.-" << metaProperty.name() << metaProperty.type() << metaProperty.typeName(); - if (metaProperty.type() == QVariant::UserType) { - if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { - typeName = QString("$ref:BasicType"); - } else if (QString(metaProperty.typeName()).startsWith("QList")) { - QString elementType = QString(metaProperty.typeName()).remove("QList<").remove(">"); - QVariant::Type variantType = QVariant::nameToType(elementType.toUtf8()); - typeName = QVariantList() << enumValueName(variantTypeToBasicType(variantType)); - } else { - typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); - } - } else if (metaProperty.isEnumType()) { - typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); - } else if (metaProperty.isFlagType()) { - typeName = QVariantList() << "$ref:" + m_flagsEnums.value(metaProperty.name()); - } else if (metaProperty.type() == QVariant::List) { - typeName = QVariantList() << enumValueName(Variant); - } else { - typeName = enumValueName(variantTypeToBasicType(metaProperty.type())); - } - description.insert(name, typeName); - } - m_objects.insert(className, description); - m_metaObjects.insert(className, metaObject); + registerObject(metaObject); +} + +template +void JsonHandler::registerUncreatableObject() +{ + QMetaObject metaObject = ObjectType::staticMetaObject; + registerObject(metaObject); } template void JsonHandler::registerObject() { registerObject(); + qRegisterMetaType(); QMetaObject metaObject = ObjectType::staticMetaObject; QMetaObject listMetaObject = ListType::staticMetaObject; QString listTypeName = QString(listMetaObject.className()).split("::").last(); @@ -184,6 +164,19 @@ void JsonHandler::registerObject() m_listEntryTypes.insert(listTypeName, objectTypeName); Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", QString("List type %1 does not implement \"count\" property!").arg(listTypeName).toUtf8()); Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE QVariant get(int index)\" method!").arg(listTypeName).toUtf8()); + Q_ASSERT_X(listMetaObject.indexOfMethod("put(QVariant)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE void put(QVariant variant)\" method!").arg(listTypeName).toUtf8()); +} + +template +void JsonHandler::registerList(BasicTypeName typeName) +{ + QMetaObject listMetaObject = ListType::staticMetaObject; + QString listTypeName = QString(listMetaObject.className()).split("::").last(); + m_metaObjects.insert(listTypeName, listMetaObject); + m_objects.insert(listTypeName, QVariantList() << QVariant(QString("$ref:%1").arg(enumValueName(typeName)))); + Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", QString("List type %1 does not implement \"count\" property!").arg(listTypeName).toUtf8()); + Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE QVariant get(int index)\" method!").arg(listTypeName).toUtf8()); + Q_ASSERT_X(listMetaObject.indexOfMethod("put(QVariant)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE void put(QVariant variant)\" method!").arg(listTypeName).toUtf8()); } template @@ -222,33 +215,19 @@ QVariant JsonHandler::pack(const T &value) const } template -T JsonHandler::unpack(const QVariantMap &map) const +QVariant JsonHandler::pack(T *value) const { - T ret; QMetaObject metaObject = T::staticMetaObject; - for (int i = 0; i < metaObject.propertyCount(); i++) { - QMetaProperty metaProperty = metaObject.property(i); - if (metaProperty.name() == QStringLiteral("objectName")) { - continue; - } - if (!metaProperty.isWritable()) { - continue; - } - if (!metaProperty.isUser()) { - Q_ASSERT_X(map.contains(metaProperty.name()), this->metaObject()->className(), QString("Missing property %1 in map.").arg(metaProperty.name()).toUtf8()); - } - if (map.contains(metaProperty.name())) { - // Special treatment for QDateTime (convert from time_t) - QVariant variant = map.value(metaProperty.name()); - if (metaProperty.type() == QVariant::DateTime) { - variant = QDateTime::fromTime_t(variant.toUInt()); - } - metaProperty.writeOnGadget(&ret, variant); - } - } - return ret; + return pack(metaObject, static_cast(value)); +} + +template +T JsonHandler::unpack(const QVariant &value) const +{ + QMetaObject metaObject = T::staticMetaObject; + QVariant ret = unpack(metaObject, value); + return ret.value(); } - #endif // JSONHANDLER_H diff --git a/libnymea/platform/package.cpp b/libnymea/platform/package.cpp index fff64f53..42715acf 100644 --- a/libnymea/platform/package.cpp +++ b/libnymea/platform/package.cpp @@ -144,3 +144,8 @@ QVariant Packages::get(int index) const { return QVariant::fromValue(at(index)); } + +void Packages::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/platform/package.h b/libnymea/platform/package.h index 9e891008..65453251 100644 --- a/libnymea/platform/package.h +++ b/libnymea/platform/package.h @@ -93,6 +93,7 @@ public: Packages(); Packages(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(Packages) diff --git a/libnymea/platform/repository.cpp b/libnymea/platform/repository.cpp index d3b1fc5f..ead662f7 100644 --- a/libnymea/platform/repository.cpp +++ b/libnymea/platform/repository.cpp @@ -69,3 +69,8 @@ QVariant Repositories::get(int index) const { return QVariant::fromValue(at(index)); } + +void Repositories::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/platform/repository.h b/libnymea/platform/repository.h index 798331b5..1ba7d6ca 100644 --- a/libnymea/platform/repository.h +++ b/libnymea/platform/repository.h @@ -57,6 +57,7 @@ public: Repositories(); Repositories(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; #endif // REPOSITORY_H diff --git a/libnymea/time/calendaritem.cpp b/libnymea/time/calendaritem.cpp index ee39e1ee..3bc1e849 100644 --- a/libnymea/time/calendaritem.cpp +++ b/libnymea/time/calendaritem.cpp @@ -285,7 +285,13 @@ CalendarItems::CalendarItems(const QList &other): QList()); +} diff --git a/libnymea/time/calendaritem.h b/libnymea/time/calendaritem.h index 4d2b5534..a5793fb2 100644 --- a/libnymea/time/calendaritem.h +++ b/libnymea/time/calendaritem.h @@ -74,7 +74,8 @@ class CalendarItems: public QList public: CalendarItems(); CalendarItems(const QList &other); - Q_INVOKABLE QVariant get(int index); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(CalendarItems) diff --git a/libnymea/time/repeatingoption.cpp b/libnymea/time/repeatingoption.cpp index 6dea237f..159be676 100644 --- a/libnymea/time/repeatingoption.cpp +++ b/libnymea/time/repeatingoption.cpp @@ -210,3 +210,43 @@ QDebug operator<<(QDebug dbg, const RepeatingOption &repeatingOption) dbg.nospace() << "RepeatingOption(Mode:" << repeatingOption.mode() << ", Monthdays:" << repeatingOption.monthDays() << "Weekdays:" << repeatingOption.weekDays() << ")"; return dbg; } + +WeekDays::WeekDays() +{ + +} + +WeekDays::WeekDays(const QList &other): QList(other) +{ + +} + +QVariant WeekDays::get(int index) const +{ + return at(index); +} + +void WeekDays::put(const QVariant &value) +{ + append(value.toInt()); +} + +MonthDays::MonthDays() +{ + +} + +MonthDays::MonthDays(const QList &other): QList(other) +{ + +} + +QVariant MonthDays::get(int index) const +{ + return at(index); +} + +void MonthDays::put(const QVariant &value) +{ + append(value.toInt()); +} diff --git a/libnymea/time/repeatingoption.h b/libnymea/time/repeatingoption.h index 3af9b6c1..4015b5a7 100644 --- a/libnymea/time/repeatingoption.h +++ b/libnymea/time/repeatingoption.h @@ -23,9 +23,34 @@ #include #include +#include class QDateTime; +class WeekDays: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + WeekDays(); + WeekDays(const QList &other); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &value); +}; +Q_DECLARE_METATYPE(WeekDays) + +class MonthDays: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + MonthDays(); + MonthDays(const QList &other); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &value); +}; +Q_DECLARE_METATYPE(MonthDays) + class RepeatingOption { Q_GADGET diff --git a/libnymea/time/timedescriptor.cpp b/libnymea/time/timedescriptor.cpp index dda50d2a..45c7b764 100644 --- a/libnymea/time/timedescriptor.cpp +++ b/libnymea/time/timedescriptor.cpp @@ -43,25 +43,25 @@ TimeDescriptor::TimeDescriptor() } /*! Returns the list of \l{TimeEventItem}{TimeEventItems} of this \l{TimeDescriptor}.*/ -QList TimeDescriptor::timeEventItems() const +TimeEventItems TimeDescriptor::timeEventItems() const { return m_timeEventItems; } /*! Set the list of \l{TimeEventItem}{TimeEventItems} of this \l{TimeDescriptor} to the given \a timeEventItems.*/ -void TimeDescriptor::setTimeEventItems(const QList &timeEventItems) +void TimeDescriptor::setTimeEventItems(const TimeEventItems &timeEventItems) { m_timeEventItems = timeEventItems; } /*! Returns the list of \l{CalendarItem}{CalendarItems} of this \l{TimeDescriptor}.*/ -QList TimeDescriptor::calendarItems() const +CalendarItems TimeDescriptor::calendarItems() const { return m_calendarItems; } /*! Set the list of \l{CalendarItem}{CalendarItems} of this \l{TimeDescriptor} to the given \a calendarItems.*/ -void TimeDescriptor::setCalendarItems(const QList &calendarItems) +void TimeDescriptor::setCalendarItems(const CalendarItems &calendarItems) { m_calendarItems = calendarItems; } diff --git a/libnymea/time/timedescriptor.h b/libnymea/time/timedescriptor.h index c7e0b898..78dba4d1 100644 --- a/libnymea/time/timedescriptor.h +++ b/libnymea/time/timedescriptor.h @@ -32,13 +32,13 @@ class TimeDescriptor public: explicit TimeDescriptor(); - QList timeEventItems() const; - void setTimeEventItems(const QList &timeEventItems); + TimeEventItems timeEventItems() const; + void setTimeEventItems(const TimeEventItems &timeEventItems); - QList calendarItems() const; - void setCalendarItems(const QList &calendarItems); + CalendarItems calendarItems() const; + void setCalendarItems(const CalendarItems &calendarItems); - bool isValid() const; + Q_INVOKABLE bool isValid() const; bool isEmpty() const; bool evaluate(const QDateTime &lastEvaluationTime, const QDateTime &dateTime) const; @@ -48,8 +48,8 @@ public: private: - QList m_timeEventItems; - QList m_calendarItems; + TimeEventItems m_timeEventItems; + CalendarItems m_calendarItems; }; diff --git a/libnymea/time/timeeventitem.cpp b/libnymea/time/timeeventitem.cpp index 93c793c9..47bda84c 100644 --- a/libnymea/time/timeeventitem.cpp +++ b/libnymea/time/timeeventitem.cpp @@ -154,3 +154,8 @@ QVariant TimeEventItems::get(int index) const { return QVariant::fromValue(at(index)); } + +void TimeEventItems::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/time/timeeventitem.h b/libnymea/time/timeeventitem.h index 94d31515..016fb0da 100644 --- a/libnymea/time/timeeventitem.h +++ b/libnymea/time/timeeventitem.h @@ -66,6 +66,7 @@ public: TimeEventItems(); TimeEventItems(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(TimeEventItems) diff --git a/libnymea/types/actiontype.cpp b/libnymea/types/actiontype.cpp index 94e35701..0f3194d0 100644 --- a/libnymea/types/actiontype.cpp +++ b/libnymea/types/actiontype.cpp @@ -123,11 +123,16 @@ ActionTypes::ActionTypes(const QList &other) } } -QVariant ActionTypes::get(int index) +QVariant ActionTypes::get(int index) const { return QVariant::fromValue(at(index)); } +void ActionTypes::put(const QVariant &variant) +{ + append(variant.value()); +} + ActionType ActionTypes::findByName(const QString &name) { foreach (const ActionType &actionType, *this) { diff --git a/libnymea/types/actiontype.h b/libnymea/types/actiontype.h index 6b03e6b9..5dd44ceb 100644 --- a/libnymea/types/actiontype.h +++ b/libnymea/types/actiontype.h @@ -77,7 +77,8 @@ class ActionTypes: public QList public: ActionTypes() = default; ActionTypes(const QList &other); - Q_INVOKABLE QVariant get(int index); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); ActionType findByName(const QString &name); ActionType findById(const ActionTypeId &id); }; diff --git a/libnymea/types/eventdescriptor.cpp b/libnymea/types/eventdescriptor.cpp index 69cbc35d..0c57d8f0 100644 --- a/libnymea/types/eventdescriptor.cpp +++ b/libnymea/types/eventdescriptor.cpp @@ -204,3 +204,8 @@ QVariant EventDescriptors::get(int index) const { return QVariant::fromValue(at(index)); } + +void EventDescriptors::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/types/eventdescriptor.h b/libnymea/types/eventdescriptor.h index 5d032f39..378c9daa 100644 --- a/libnymea/types/eventdescriptor.h +++ b/libnymea/types/eventdescriptor.h @@ -89,6 +89,7 @@ public: EventDescriptors(); EventDescriptors(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(EventDescriptors) diff --git a/libnymea/types/eventtype.cpp b/libnymea/types/eventtype.cpp index 9b563736..0241ac43 100644 --- a/libnymea/types/eventtype.cpp +++ b/libnymea/types/eventtype.cpp @@ -128,11 +128,16 @@ EventTypes::EventTypes(const QList &other) } } -QVariant EventTypes::get(int index) +QVariant EventTypes::get(int index) const { return QVariant::fromValue(at(index)); } +void EventTypes::put(const QVariant &variant) +{ + append(variant.value()); +} + EventType EventTypes::findByName(const QString &name) { foreach (const EventType &eventType, *this) { diff --git a/libnymea/types/eventtype.h b/libnymea/types/eventtype.h index fbdb4628..4e4b629c 100644 --- a/libnymea/types/eventtype.h +++ b/libnymea/types/eventtype.h @@ -78,7 +78,8 @@ class EventTypes: public QList public: EventTypes() = default; EventTypes(const QList &other); - Q_INVOKABLE QVariant get(int index); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); EventType findByName(const QString &name); EventType findById(const EventTypeId &id); }; diff --git a/libnymea/types/param.cpp b/libnymea/types/param.cpp index 0d3b81aa..7c8f70e1 100644 --- a/libnymea/types/param.cpp +++ b/libnymea/types/param.cpp @@ -48,6 +48,11 @@ ParamTypeId Param::paramTypeId() const return m_paramTypeId; } +void Param::setParamTypeId(const ParamTypeId ¶mTypeId) +{ + m_paramTypeId = paramTypeId; +} + /*! Returns the value of this \l Param. */ QVariant Param::value() const { @@ -114,6 +119,11 @@ QVariant ParamList::get(int index) return QVariant::fromValue(at(index)); } +void ParamList::put(const QVariant &variant) +{ + append(variant.value()); +} + /*! Returns true if this ParamList contains a Param with the given \a paramTypeId. */ bool ParamList::hasParam(const ParamTypeId ¶mTypeId) const { diff --git a/libnymea/types/param.h b/libnymea/types/param.h index 036b1fd2..a37981e4 100644 --- a/libnymea/types/param.h +++ b/libnymea/types/param.h @@ -33,12 +33,13 @@ class LIBNYMEA_EXPORT Param { Q_GADGET - Q_PROPERTY(QUuid paramTypeId READ paramTypeId USER true) + Q_PROPERTY(QUuid paramTypeId READ paramTypeId WRITE setParamTypeId USER true) Q_PROPERTY(QVariant value READ value WRITE setValue) public: Param(const ParamTypeId ¶mTypeId = ParamTypeId(), const QVariant &value = QVariant()); ParamTypeId paramTypeId() const; + void setParamTypeId(const ParamTypeId ¶mTypeId); QVariant value() const; void setValue(const QVariant &value); @@ -61,6 +62,7 @@ public: ParamList(); ParamList(const QList &other); Q_INVOKABLE QVariant get(int index); + Q_INVOKABLE void put(const QVariant &variant); bool hasParam(const ParamTypeId ¶mTypeId) const; QVariant paramValue(const ParamTypeId ¶mTypeId) const; bool setParamValue(const ParamTypeId ¶mTypeId, const QVariant &value); diff --git a/libnymea/types/paramdescriptor.cpp b/libnymea/types/paramdescriptor.cpp index 69679ab4..b8d60cf8 100644 --- a/libnymea/types/paramdescriptor.cpp +++ b/libnymea/types/paramdescriptor.cpp @@ -101,3 +101,8 @@ QVariant ParamDescriptors::get(int index) const { return QVariant::fromValue(at(index)); } + +void ParamDescriptors::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/types/paramdescriptor.h b/libnymea/types/paramdescriptor.h index ecfcb564..4244bb2a 100644 --- a/libnymea/types/paramdescriptor.h +++ b/libnymea/types/paramdescriptor.h @@ -59,6 +59,7 @@ public: ParamDescriptors(); ParamDescriptors(const QList &other); Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(ParamDescriptors) diff --git a/libnymea/types/paramtype.cpp b/libnymea/types/paramtype.cpp index cb69b88f..05283b9a 100644 --- a/libnymea/types/paramtype.cpp +++ b/libnymea/types/paramtype.cpp @@ -255,11 +255,16 @@ ParamTypes::ParamTypes(const QList &other): QList(other) { } -QVariant ParamTypes::get(int index) +QVariant ParamTypes::get(int index) const { return QVariant::fromValue(at(index)); } +void ParamTypes::put(const QVariant &variant) +{ + append(variant.value()); +} + ParamType ParamTypes::findByName(const QString &name) { foreach (const ParamType ¶mType, *this) { diff --git a/libnymea/types/paramtype.h b/libnymea/types/paramtype.h index 217e4185..cb6d5c37 100644 --- a/libnymea/types/paramtype.h +++ b/libnymea/types/paramtype.h @@ -115,7 +115,8 @@ class ParamTypes: public QList public: ParamTypes() = default; ParamTypes(const QList &other); - Q_INVOKABLE QVariant get(int index); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); ParamType findByName(const QString &name); ParamType findById(const ParamTypeId &id); }; diff --git a/libnymea/types/state.cpp b/libnymea/types/state.cpp index e1c3185e..b1e582b1 100644 --- a/libnymea/types/state.cpp +++ b/libnymea/types/state.cpp @@ -108,7 +108,12 @@ States::States(const QList &other): QList(other) } -QVariant States::get(int index) +QVariant States::get(int index) const { return QVariant::fromValue(at(index)); } + +void States::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/types/state.h b/libnymea/types/state.h index 969323af..d01bfd8e 100644 --- a/libnymea/types/state.h +++ b/libnymea/types/state.h @@ -63,7 +63,8 @@ class States: public QList public: States(); States(const QList &other); - Q_INVOKABLE QVariant get(int index); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(States) diff --git a/libnymea/types/statedescriptor.h b/libnymea/types/statedescriptor.h index 83f00250..b0022442 100644 --- a/libnymea/types/statedescriptor.h +++ b/libnymea/types/statedescriptor.h @@ -73,7 +73,7 @@ public: Types::ValueOperator operatorType() const; void setOperatorType(Types::ValueOperator opertatorType); - bool isValid() const; + Q_INVOKABLE bool isValid() const; bool operator ==(const StateDescriptor &other) const; @@ -86,8 +86,9 @@ private: QString m_interface; QString m_interfaceState; QVariant m_stateValue; - Types::ValueOperator m_operatorType; + Types::ValueOperator m_operatorType = Types::ValueOperatorEquals; }; +Q_DECLARE_METATYPE(StateDescriptor) QDebug operator<<(QDebug dbg, const StateDescriptor &stateDescriptor); diff --git a/libnymea/types/statetype.cpp b/libnymea/types/statetype.cpp index 6953f6e1..2905bebe 100644 --- a/libnymea/types/statetype.cpp +++ b/libnymea/types/statetype.cpp @@ -198,11 +198,16 @@ StateTypes::StateTypes(const QList &other) } } -QVariant StateTypes::get(int index) +QVariant StateTypes::get(int index) const { return QVariant::fromValue(at(index)); } +void StateTypes::put(const QVariant &variant) +{ + append(variant.value()); +} + StateType StateTypes::findByName(const QString &name) { foreach (const StateType &stateType, *this) { diff --git a/libnymea/types/statetype.h b/libnymea/types/statetype.h index 7a3a0905..a66486eb 100644 --- a/libnymea/types/statetype.h +++ b/libnymea/types/statetype.h @@ -105,7 +105,8 @@ class StateTypes: public QList public: StateTypes() = default; StateTypes(const QList &other); - Q_INVOKABLE QVariant get(int index); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); StateType findByName(const QString &name); StateType findById(const StateTypeId &id); }; diff --git a/libnymea/types/vendor.cpp b/libnymea/types/vendor.cpp index 1f0faa71..fc0904bd 100644 --- a/libnymea/types/vendor.cpp +++ b/libnymea/types/vendor.cpp @@ -33,6 +33,11 @@ #include "vendor.h" +Vendor::Vendor() +{ + +} + /*! Constructs an Vendor with the given \a id and the given \a name. */ Vendor::Vendor(const VendorId &id, const QString &name): m_id(id), diff --git a/libnymea/types/vendor.h b/libnymea/types/vendor.h index 27010619..08cce26d 100644 --- a/libnymea/types/vendor.h +++ b/libnymea/types/vendor.h @@ -38,6 +38,7 @@ class LIBNYMEA_EXPORT Vendor Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) public: + Vendor(); Vendor(const VendorId &id, const QString &name = QString()); VendorId id() const; @@ -56,6 +57,7 @@ private: QString m_name; QString m_displayName; }; +Q_DECLARE_METATYPE(Vendor) class LIBNYMEA_EXPORT Vendors: public QList { @@ -65,5 +67,6 @@ public: Vendor findById(const VendorId &vendorId) const; }; +Q_DECLARE_METATYPE(Vendors) #endif // VENDOR_H diff --git a/tests/auto/devices/testdevices.cpp b/tests/auto/devices/testdevices.cpp index 760eb89e..02ee3ea8 100644 --- a/tests/auto/devices/testdevices.cpp +++ b/tests/auto/devices/testdevices.cpp @@ -353,7 +353,10 @@ void TestDevices::addConfiguredDevice_data() QTest::newRow("User, JustAdd, wrong param") << mockDeviceClassId << invalidDeviceParams << true << Device::DeviceErrorInvalidParameter; deviceParams.clear(); deviceParams << httpportParam << fakeparam; - QTest::newRow("USer, JustAdd, additional invalid param") << mockDeviceClassId << deviceParams << Device::DeviceErrorNoError; + QTest::newRow("USer, JustAdd, additional invalid param") << mockDeviceClassId << deviceParams << false << Device::DeviceErrorNoError; + + deviceParams.clear(); deviceParams << httpportParam << fakeparam2; + QTest::newRow("USer, JustAdd, additional param, valid but unused") << mockDeviceClassId << deviceParams << true << Device::DeviceErrorNoError; } @@ -655,8 +658,8 @@ void TestDevices::parentChildDevices() if (deviceMap.value("deviceClassId").toString() == mockChildDeviceClassId.toString()) { if (deviceMap.value("parentId") == parentDeviceId.toString()) { - //qDebug() << QJsonDocument::fromVariant(deviceVariant).toJson(); childDeviceId = DeviceId(deviceMap.value("id").toString()); + break; } } } diff --git a/tests/auto/rules/testrules.cpp b/tests/auto/rules/testrules.cpp index bb3a36f7..82fb41b8 100644 --- a/tests/auto/rules/testrules.cpp +++ b/tests/auto/rules/testrules.cpp @@ -410,23 +410,19 @@ void TestRules::addRemoveRules_data() QVariantMap validActionNoParams; validActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); validActionNoParams.insert("deviceId", m_mockDeviceId); - validActionNoParams.insert("ruleActionParams", QVariantList()); QVariantMap invalidAction; invalidAction.insert("actionTypeId", ActionTypeId("f32c7efb-38b6-4576-a496-c75bbb23132f")); invalidAction.insert("deviceId", m_mockDeviceId); - invalidAction.insert("ruleActionParams", QVariantList()); // RuleExitAction QVariantMap validExitActionNoParams; validExitActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); validExitActionNoParams.insert("deviceId", m_mockDeviceId); - validExitActionNoParams.insert("ruleActionParams", QVariantList()); QVariantMap invalidExitAction; invalidExitAction.insert("actionTypeId", ActionTypeId("f32c7efb-38b6-4576-a496-c75bbb23132f")); invalidExitAction.insert("deviceId", m_mockDeviceId); - invalidExitAction.insert("ruleActionParams", QVariantList()); // StateDescriptor QVariantMap stateDescriptor; @@ -448,7 +444,6 @@ void TestRules::addRemoveRules_data() QVariantMap validEventDescriptor1; validEventDescriptor1.insert("eventTypeId", mockEvent1EventTypeId); validEventDescriptor1.insert("deviceId", m_mockDeviceId); - validEventDescriptor1.insert("paramDescriptors", QVariantList()); QVariantMap validEventDescriptor2; validEventDescriptor2.insert("eventTypeId", mockEvent2EventTypeId); @@ -464,7 +459,6 @@ void TestRules::addRemoveRules_data() QVariantMap validEventDescriptor3; validEventDescriptor3.insert("eventTypeId", mockEvent2EventTypeId); validEventDescriptor3.insert("deviceId", m_mockDeviceId); - validEventDescriptor3.insert("paramDescriptors", QVariantList()); // EventDescriptorList QVariantList eventDescriptorList; @@ -474,7 +468,6 @@ void TestRules::addRemoveRules_data() QVariantMap invalidEventDescriptor; invalidEventDescriptor.insert("eventTypeId", mockEvent1EventTypeId); invalidEventDescriptor.insert("deviceId", DeviceId("2c4825c8-dfb9-4ba4-bd0e-1d827d945d41")); - invalidEventDescriptor.insert("paramDescriptors", QVariantList()); // RuleAction event based QVariantMap validActionEventBased; @@ -617,7 +610,10 @@ void TestRules::addRemoveRules() QVariantList eventDescriptors = rule.value("eventDescriptors").toList(); if (!eventDescriptor.isEmpty()) { QVERIFY2(eventDescriptors.count() == 1, "There should be exactly one eventDescriptor"); - QVERIFY2(eventDescriptors.first().toMap() == eventDescriptor, "Event descriptor doesn't match"); + QVERIFY2(eventDescriptors.first().toMap() == eventDescriptor, + QString("Event descriptor doesn't match:\nExpected: %1\nGot: %2") + .arg(QString(QJsonDocument::fromVariant(eventDescriptor).toJson())) + .arg(QString(QJsonDocument::fromVariant(eventDescriptors.first().toMap()).toJson())).toUtf8()); } else if (eventDescriptorList.isEmpty()){ QVERIFY2(eventDescriptors.count() == eventDescriptorList.count(), QString("There should be exactly %1 eventDescriptor").arg(eventDescriptorList.count()).toLatin1().data()); foreach (const QVariant &eventDescriptorVariant, eventDescriptorList) { @@ -634,7 +630,11 @@ void TestRules::addRemoveRules() } QVariantList replyActions = rule.value("actions").toList(); - QVERIFY2(actions == replyActions, "Actions don't match"); + QVERIFY2(actions == replyActions, + QString("Actions don't match.\nExpected: %1\nGot: %2") + .arg(QString(QJsonDocument::fromVariant(actions).toJson())) + .arg(QString(QJsonDocument::fromVariant(replyActions).toJson())) + .toUtf8()); QVariantList replyExitActions = rule.value("exitActions").toList(); QVERIFY2(exitActions == replyExitActions, "ExitActions don't match"); @@ -655,23 +655,19 @@ void TestRules::editRules_data() QVariantMap validActionNoParams; validActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); validActionNoParams.insert("deviceId", m_mockDeviceId); - validActionNoParams.insert("ruleActionParams", QVariantList()); QVariantMap invalidAction; invalidAction.insert("actionTypeId", ActionTypeId()); invalidAction.insert("deviceId", m_mockDeviceId); - invalidAction.insert("ruleActionParams", QVariantList()); // RuleExitAction QVariantMap validExitActionNoParams; validExitActionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); validExitActionNoParams.insert("deviceId", m_mockDeviceId); - validExitActionNoParams.insert("ruleActionParams", QVariantList()); QVariantMap invalidExitAction; invalidExitAction.insert("actionTypeId", ActionTypeId()); invalidExitAction.insert("deviceId", m_mockDeviceId); - invalidExitAction.insert("ruleActionParams", QVariantList()); // StateDescriptor QVariantMap stateDescriptor; @@ -693,7 +689,6 @@ void TestRules::editRules_data() QVariantMap validEventDescriptor1; validEventDescriptor1.insert("eventTypeId", mockEvent1EventTypeId); validEventDescriptor1.insert("deviceId", m_mockDeviceId); - validEventDescriptor1.insert("paramDescriptors", QVariantList()); QVariantMap validEventDescriptor2; validEventDescriptor2.insert("eventTypeId", mockEvent2EventTypeId); @@ -709,7 +704,6 @@ void TestRules::editRules_data() QVariantMap validEventDescriptor3; validEventDescriptor3.insert("eventTypeId", mockEvent2EventTypeId); validEventDescriptor3.insert("deviceId", m_mockDeviceId); - validEventDescriptor3.insert("paramDescriptors", QVariantList()); // EventDescriptorList QVariantList eventDescriptorList; @@ -719,7 +713,6 @@ void TestRules::editRules_data() QVariantMap invalidEventDescriptor; invalidEventDescriptor.insert("eventTypeId", mockEvent1EventTypeId); invalidEventDescriptor.insert("deviceId", DeviceId()); - invalidEventDescriptor.insert("paramDescriptors", QVariantList()); // RuleAction event based QVariantMap validActionEventBased; @@ -809,11 +802,9 @@ void TestRules::editRules() QVariantMap eventDescriptor1; eventDescriptor1.insert("eventTypeId", mockEvent1EventTypeId); eventDescriptor1.insert("deviceId", m_mockDeviceId); - eventDescriptor1.insert("paramDescriptors", QVariantList()); QVariantMap eventDescriptor2; eventDescriptor2.insert("eventTypeId", mockEvent2EventTypeId); eventDescriptor2.insert("deviceId", m_mockDeviceId); - eventDescriptor2.insert("paramDescriptors", QVariantList()); QVariantMap eventParam1; eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); eventParam1.insert("value", 3); @@ -948,7 +939,10 @@ void TestRules::editRules() QVariantList eventDescriptors = rule.value("eventDescriptors").toList(); if (!eventDescriptor.isEmpty()) { QVERIFY2(eventDescriptors.count() == 1, "There should be exactly one eventDescriptor"); - QVERIFY2(eventDescriptors.first().toMap() == eventDescriptor, "Event descriptor doesn't match"); + QVERIFY2(eventDescriptors.first().toMap() == eventDescriptor, + QString("Event descriptor doesn't match.\nExpected:%1\nGot:%2") + .arg(QString(QJsonDocument::fromVariant(eventDescriptor).toJson())) + .arg(QString(QJsonDocument::fromVariant(eventDescriptors.first().toMap()).toJson())).toUtf8()); } else if (eventDescriptorList.isEmpty()){ QVERIFY2(eventDescriptors.count() == eventDescriptorList.count(), QString("There should be exactly %1 eventDescriptor").arg(eventDescriptorList.count()).toLatin1().data()); foreach (const QVariant &eventDescriptorVariant, eventDescriptorList) { @@ -965,7 +959,11 @@ void TestRules::editRules() } QVariantList replyActions = rule.value("actions").toList(); - QVERIFY2(actions == replyActions, "Actions don't match"); + QVERIFY2(actions == replyActions, + QString("Actions don't match.\nExpected: %1\nGot: %2") + .arg(QString(QJsonDocument::fromVariant(actions).toJson())) + .arg(QString(QJsonDocument::fromVariant(replyActions).toJson())) + .toUtf8()); QVariantList replyExitActions = rule.value("exitActions").toList(); QVERIFY2(exitActions == replyExitActions, "ExitActions don't match"); @@ -1103,12 +1101,10 @@ void TestRules::loadStoreConfig() QVariantMap eventDescriptor1; eventDescriptor1.insert("eventTypeId", mockEvent1EventTypeId); eventDescriptor1.insert("deviceId", m_mockDeviceId); - eventDescriptor1.insert("paramDescriptors", QVariantList()); QVariantMap eventDescriptor2; eventDescriptor2.insert("eventTypeId", mockEvent2EventTypeId); eventDescriptor2.insert("deviceId", m_mockDeviceId); - eventDescriptor2.insert("paramDescriptors", QVariantList()); QVariantList eventParamDescriptors; QVariantMap eventParam1; eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); @@ -1195,7 +1191,6 @@ void TestRules::loadStoreConfig() QVariantMap validEventDescriptor3; validEventDescriptor3.insert("eventTypeId", mockEvent2EventTypeId); validEventDescriptor3.insert("deviceId", m_mockDeviceId); - validEventDescriptor3.insert("paramDescriptors", QVariantList()); validEventDescriptors3.append(validEventDescriptor3); // Interface based event descriptor @@ -1332,7 +1327,11 @@ void TestRules::loadStoreConfig() expectedEventDescriptorVariant.toMap().value("deviceId") == replyEventDescriptorVariant.toMap().value("deviceId")) { found = true; qDebug() << endl << replyEventDescriptorVariant << endl << expectedEventDescriptorVariant; - QVERIFY2(replyEventDescriptorVariant == expectedEventDescriptorVariant, "EventDescriptor doesn't match"); + QVERIFY2(replyEventDescriptorVariant == expectedEventDescriptorVariant, + QString("EventDescriptor doesn't match.\nExpected: %1\nGot: %2") + .arg(QString(QJsonDocument::fromVariant(expectedEventDescriptorVariant).toJson())) + .arg(QString(QJsonDocument::fromVariant(replyEventDescriptorVariant).toJson())) + .toUtf8()); } } QVERIFY2(found, "missing eventdescriptor"); diff --git a/tests/auto/timemanager/testtimemanager.cpp b/tests/auto/timemanager/testtimemanager.cpp index 62e31b52..a3585600 100644 --- a/tests/auto/timemanager/testtimemanager.cpp +++ b/tests/auto/timemanager/testtimemanager.cpp @@ -204,7 +204,7 @@ void TestTimeManager::loadSaveTimeDescriptor_data() QTest::addColumn("timeDescriptor"); QTest::newRow("calendarItems") << createTimeDescriptorCalendar(calendarItems); - QTest::newRow("timeEventItems") << createTimeDescriptorTimeEvent(timeEventItems); +// QTest::newRow("timeEventItems") << createTimeDescriptorTimeEvent(timeEventItems); } void TestTimeManager::loadSaveTimeDescriptor() @@ -225,6 +225,7 @@ void TestTimeManager::loadSaveTimeDescriptor() ruleMap.insert("actions", QVariantList() << action); // Add the rule + qCDebug(dcTests()) << "Adding rule:" << qUtf8Printable(QJsonDocument::fromVariant(ruleMap).toJson()); QVariant response = injectAndWait("Rules.AddRule", ruleMap); verifyRuleError(response); @@ -237,6 +238,12 @@ void TestTimeManager::loadSaveTimeDescriptor() QVariantMap timeDescriptorMap = response.toMap().value("params").toMap().value("rule").toMap().value("timeDescriptor").toMap(); + QVERIFY2(timeDescriptorMap == timeDescriptor, + QString("TimeDescriptor not matching:\nExpected: %1\nGot: %2") + .arg(QString(QJsonDocument::fromVariant(timeDescriptor).toJson())) + .arg(QString(QJsonDocument::fromVariant(timeDescriptorMap).toJson())) + .toUtf8()); + // Restart the server restartServer(); @@ -246,8 +253,14 @@ void TestTimeManager::loadSaveTimeDescriptor() QVariantMap timeDescriptorMapLoaded = response.toMap().value("params").toMap().value("rule").toMap().value("timeDescriptor").toMap(); - QCOMPARE(timeDescriptorMap, timeDescriptorMapLoaded); + QVERIFY2(timeDescriptorMap == timeDescriptorMapLoaded, + QString("TimeDescriptor not matching:\nExpected: %1\nGot: %2") + .arg(QString(QJsonDocument::fromVariant(timeDescriptorMap).toJson())) + .arg(QString(QJsonDocument::fromVariant(timeDescriptorMapLoaded).toJson())) + .toUtf8()); +// qWarning() << "+++" << QString(QJsonDocument::fromVariant(timeDescriptorMap).toJson()); +// qWarning() << "---" << QString(QJsonDocument::fromVariant(timeDescriptorMapLoaded).toJson()); // REMOVE rule QVariantMap removeParams; removeParams.insert("ruleId", ruleId); diff --git a/tests/scripts/getruledetails.sh b/tests/scripts/getruledetails.sh index f23490d1..0b096ff4 100755 --- a/tests/scripts/getruledetails.sh +++ b/tests/scripts/getruledetails.sh @@ -2,6 +2,11 @@ if [ -z $2 ]; then echo "usage: $0 host ruleId" -else - (echo '{"id":1, "method":"Rules.GetRuleDetails", "params": {"ruleId": "'$2'"}}'; sleep 1) | nc $1 2222 + exit 1 fi + + +cat << EOD | nc $1 2222 | jq +{"id":0, "method":"JSONRPC.Hello"} +{"id":1, "method":"Rules.GetRuleDetails", "params": {"ruleId": "$2"}} +EOD diff --git a/tests/scripts/getrules.sh b/tests/scripts/getrules.sh index 52c24be5..fb90a39e 100755 --- a/tests/scripts/getrules.sh +++ b/tests/scripts/getrules.sh @@ -2,6 +2,10 @@ if [ -z $1 ]; then echo "usage: $0 host" -else - (echo '{"id":1, "method":"Rules.GetRules"}'; sleep 1) | nc $1 2222 + exit 1 fi + +cat << EOD | nc $1 2222 +{"id":0, "method":"JSONRPC.Hello"} +{"id":1, "method":"Rules.GetRules"} +EOD diff --git a/tests/scripts/snoopnotifications.sh b/tests/scripts/snoopnotifications.sh index 3e99765c..2ea06de9 100755 --- a/tests/scripts/snoopnotifications.sh +++ b/tests/scripts/snoopnotifications.sh @@ -2,6 +2,11 @@ if [ -z $1 ]; then echo "usage $0 host" -else - (echo '{"id":1, "method":"JSONRPC.SetNotificationStatus", "params":{"enabled":"true"}}'; read) | nc $1 2222 + exit 1 fi + + +cat <init(); // Wait unitl the server is initialized QSignalSpy coreInitializedSpy(NymeaCore::instance(), SIGNAL(initialized())); QVERIFY(coreInitializedSpy.wait()); qApp->processEvents(); + qCDebug(dcTests()) << "Nymea core instance initialized. Creating dummy user."; // Yes, we're intentionally mixing upper/lower case email here... username should not be case sensitive NymeaCore::instance()->userManager()->removeUser("dummy@guh.io"); @@ -79,7 +80,7 @@ void NymeaTestBase::initTestCase() m_apiToken = NymeaCore::instance()->userManager()->authenticate("Dummy@guh.io", "DummyPW1!", "testcase"); if (MockTcpServer::servers().isEmpty()) { - qWarning() << "no mock tcp server found"; + qCWarning(dcTests) << "no mock tcp server found"; exit(-1); } @@ -88,6 +89,7 @@ void NymeaTestBase::initTestCase() m_clientId = QUuid::createUuid(); m_mockTcpServer->clientConnected(m_clientId); + qCDebug(dcTests()) << "Starting JSON handshake"; QVariant response = injectAndWait("JSONRPC.Hello"); createMockDevice(); From 0e7edd5abd501a777d309497ac527339e5649350 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 4 Nov 2019 00:51:02 +0100 Subject: [PATCH 16/22] cleanup --- libnymea-core/jsonrpc/actionhandler.cpp | 6 +- .../jsonrpc/configurationhandler.cpp | 32 +- libnymea-core/jsonrpc/devicehandler.cpp | 51 +- .../jsonrpc/jsonrpcserverimplementation.cpp | 2 +- .../jsonrpc/networkmanagerhandler.cpp | 19 +- libnymea-core/jsonrpc/networkmanagerhandler.h | 6 +- .../networkmanager/networkdevice.cpp | 2 +- .../networkmanager/wirednetworkdevice.h | 8 +- .../networkmanager/wirelessaccesspoint.h | 8 +- .../networkmanager/wirelessnetworkdevice.h | 8 +- libnymea/devices/device.cpp | 10 + libnymea/devices/device.h | 4 + libnymea/devices/devicedescriptor.cpp | 10 + libnymea/devices/devicedescriptor.h | 4 + libnymea/devices/deviceplugin.cpp | 10 + libnymea/devices/deviceplugin.h | 4 + libnymea/jsonrpc/jsonhandler.cpp | 14 + libnymea/jsonrpc/jsonhandler.h | 37 +- libnymea/types/deviceclass.cpp | 10 + libnymea/types/deviceclass.h | 4 + libnymea/types/vendor.cpp | 10 + libnymea/types/vendor.h | 6 +- tests/auto/api.json | 937 +++++++++--------- .../configurations/testconfigurations.cpp | 8 +- tests/auto/jsonrpc/testjsonrpc.cpp | 12 +- tests/scripts/getconfigureddevices.sh | 4 +- tests/scripts/getstatevalue.sh | 8 +- tests/scripts/getstatevalues.sh | 11 + 28 files changed, 656 insertions(+), 589 deletions(-) create mode 100755 tests/scripts/getstatevalues.sh diff --git a/libnymea-core/jsonrpc/actionhandler.cpp b/libnymea-core/jsonrpc/actionhandler.cpp index 9d63e618..e981dda4 100644 --- a/libnymea-core/jsonrpc/actionhandler.cpp +++ b/libnymea-core/jsonrpc/actionhandler.cpp @@ -64,7 +64,7 @@ ActionHandler::ActionHandler(QObject *parent) : description = "Execute a single action."; params.insert("actionTypeId", enumValueName(Uuid)); params.insert("deviceId", enumValueName(Uuid)); - params.insert("o:params", QVariantList() << objectRef("Param")); + params.insert("o:params", objectRef()); returns.insert("deviceError", enumRef()); returns.insert("o:displayMessage", enumValueName(String)); registerMethod("ExecuteAction", description, params, returns); @@ -73,7 +73,7 @@ ActionHandler::ActionHandler(QObject *parent) : description = "Get the ActionType for the given ActionTypeId"; params.insert("actionTypeId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); - returns.insert("o:actionType", objectRef("ActionType")); + returns.insert("o:actionType", objectRef()); registerMethod("GetActionType", description, params, returns); params.clear(); returns.clear(); @@ -88,7 +88,7 @@ ActionHandler::ActionHandler(QObject *parent) : params.insert("deviceId", enumValueName(Uuid)); params.insert("itemId", enumValueName(String)); params.insert("actionTypeId", enumValueName(Uuid)); - params.insert("o:params", QVariantList() << objectRef("Param")); + params.insert("o:params", objectRef()); returns.insert("deviceError", enumRef()); registerMethod("ExecuteBrowserItemAction", description, params, returns); diff --git a/libnymea-core/jsonrpc/configurationhandler.cpp b/libnymea-core/jsonrpc/configurationhandler.cpp index 92b3b0eb..faf2ebff 100644 --- a/libnymea-core/jsonrpc/configurationhandler.cpp +++ b/libnymea-core/jsonrpc/configurationhandler.cpp @@ -98,16 +98,16 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): basicConfiguration.insert("debugServerEnabled", enumValueName(Bool)); returns.insert("basicConfiguration", basicConfiguration); QVariantList tcpServerConfigurations; - tcpServerConfigurations.append(objectRef("ServerConfiguration")); + tcpServerConfigurations.append(objectRef()); returns.insert("tcpServerConfigurations", tcpServerConfigurations); QVariantList webServerConfigurations; - webServerConfigurations.append(objectRef("WebServerConfiguration")); + webServerConfigurations.append(objectRef()); returns.insert("webServerConfigurations", webServerConfigurations); QVariantList webSocketServerConfigurations; - webSocketServerConfigurations.append(objectRef("ServerConfiguration")); + webSocketServerConfigurations.append(objectRef()); returns.insert("webSocketServerConfigurations", webSocketServerConfigurations); QVariantList mqttServerConfigurations; - mqttServerConfigurations.append(objectRef("ServerConfiguration")); + mqttServerConfigurations.append(objectRef()); QVariantMap cloudConfiguration; cloudConfiguration.insert("enabled", enumValueName(Bool)); returns.insert("cloud", cloudConfiguration); @@ -139,7 +139,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Configure a TCP interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped."; - params.insert("configuration", objectRef("ServerConfiguration")); + params.insert("configuration", objectRef()); returns.insert("configurationError", enumRef()); registerMethod("SetTcpServerConfiguration", description, params, returns); @@ -151,7 +151,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Configure a WebSocket Server interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped."; - params.insert("configuration", objectRef("ServerConfiguration")); + params.insert("configuration", objectRef()); returns.insert("configurationError", enumRef()); registerMethod("SetWebSocketServerConfiguration", description, params, returns); @@ -163,7 +163,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Configure a WebServer interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added."; - params.insert("configuration", objectRef("WebServerConfiguration")); + params.insert("configuration", objectRef()); returns.insert("configurationError", enumRef()); registerMethod("SetWebServerConfiguration", description, params, returns); @@ -182,12 +182,12 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): // MQTT params.clear(); returns.clear(); description = "Get all MQTT Server configurations."; - returns.insert("mqttServerConfigurations", QVariantList() << objectRef("ServerConfiguration")); + returns.insert("mqttServerConfigurations", QVariantList() << objectRef()); registerMethod("GetMqttServerConfigurations", description, params, returns); params.clear(); returns.clear(); description = "Configure a MQTT Server interface on the MQTT broker. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Setting authenticationEnabled to true will require MQTT clients to use credentials set in the MQTT broker policies."; - params.insert("configuration", objectRef("ServerConfiguration")); + params.insert("configuration", objectRef()); returns.insert("configurationError", enumRef()); registerMethod("SetMqttServerConfiguration", description, params, returns); @@ -199,12 +199,12 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Get all MQTT broker policies."; - returns.insert("mqttPolicies", QVariantList() << objectRef("MqttPolicy")); + returns.insert("mqttPolicies", QVariantList() << objectRef()); registerMethod("GetMqttPolicies", description, params, returns); params.clear(); returns.clear(); description = "Configure a MQTT broker policy. If the ID is an existing one, the existing policy will be modified, otherwise a new one will be added."; - params.insert("policy", objectRef("MqttPolicy")); + params.insert("policy", objectRef()); returns.insert("configurationError", enumRef()); registerMethod("SetMqttPolicy", description, params, returns); @@ -227,7 +227,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Emitted whenever the TCP server configuration changes."; - params.insert("tcpServerConfiguration", objectRef("ServerConfiguration")); + params.insert("tcpServerConfiguration", objectRef()); registerNotification("TcpServerConfigurationChanged", description, params); params.clear(); returns.clear(); @@ -237,7 +237,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Emitted whenever the web socket server configuration changes."; - params.insert("webSocketServerConfiguration", objectRef("ServerConfiguration")); + params.insert("webSocketServerConfiguration", objectRef()); registerNotification("WebSocketServerConfigurationChanged", description, params); params.clear(); returns.clear(); @@ -247,7 +247,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Emitted whenever the MQTT broker configuration is changed."; - params.insert("mqttServerConfiguration", objectRef("ServerConfiguration")); + params.insert("mqttServerConfiguration", objectRef()); registerNotification("MqttServerConfigurationChanged", description, params); params.clear(); returns.clear(); @@ -257,7 +257,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Emitted whenever the web server configuration changes."; - params.insert("webServerConfiguration", objectRef("WebServerConfiguration")); + params.insert("webServerConfiguration", objectRef()); registerNotification("WebServerConfigurationChanged", description, params); params.clear(); returns.clear(); @@ -272,7 +272,7 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): params.clear(); returns.clear(); description = "Emitted whenever a MQTT broker policy is changed."; - params.insert("policy", objectRef("MqttPolicy")); + params.insert("policy", objectRef()); registerNotification("MqttPolicyChanged", description, params); params.clear(); returns.clear(); diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 5fbc2e81..42e51c11 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -90,15 +90,15 @@ DeviceHandler::DeviceHandler(QObject *parent) : // Objects registerObject(); registerObject(); - registerUncreatableObject(); - registerObject(); + registerUncreatableObject(); + registerObject(); registerObject(); registerObject(); registerObject(); - registerObject(); - registerObject(); + registerObject(); + registerObject(); registerObject(); - registerUncreatableObject(); + registerUncreatableObject(); // Regsitering browseritem manually for now. Not sure how to deal with the // polymorphism in int (e.g MediaBrowserItem) @@ -119,31 +119,31 @@ DeviceHandler::DeviceHandler(QObject *parent) : // Methods QString description; QVariantMap returns; QVariantMap params; description = "Returns a list of supported Vendors."; - returns.insert("vendors", QVariantList() << objectRef("Vendor")); + returns.insert("vendors", objectRef()); registerMethod("GetSupportedVendors", description, params, returns); params.clear(); returns.clear(); description = "Returns a list of supported Device classes, optionally filtered by vendorId."; params.insert("o:vendorId", enumValueName(Uuid)); - returns.insert("deviceClasses", QVariantList() << objectRef("DeviceClass")); + returns.insert("deviceClasses", objectRef()); registerMethod("GetSupportedDevices", description, params, returns); params.clear(); returns.clear(); description = "Returns a list of loaded plugins."; - returns.insert("plugins", QVariantList() << objectRef("DevicePlugin")); + returns.insert("plugins", objectRef()); registerMethod("GetPlugins", description, params, returns); params.clear(); returns.clear(); description = "Get a plugin's params."; params.insert("pluginId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); - returns.insert("o:configuration", QVariantList() << objectRef("Param")); + returns.insert("o:configuration", objectRef()); registerMethod("GetPluginConfiguration", description, params, returns); params.clear(); returns.clear(); description = "Set a plugin's params."; params.insert("pluginId", enumValueName(Uuid)); - params.insert("configuration", QVariantList() << objectRef("Param")); + params.insert("configuration", objectRef()); returns.insert("deviceError", enumRef()); registerMethod("SetPluginConfiguration", description, params, returns); @@ -157,7 +157,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.insert("deviceClassId", enumValueName(Uuid)); params.insert("name", enumValueName(String)); params.insert("o:deviceDescriptorId", enumValueName(Uuid)); - params.insert("o:deviceParams", QVariantList() << objectRef("Param")); + params.insert("o:deviceParams", objectRef()); returns.insert("deviceError", enumRef()); returns.insert("o:deviceId", enumValueName(Uuid)); returns.insert("o:displayMessage", enumValueName(String)); @@ -184,7 +184,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.insert("o:deviceClassId", enumValueName(Uuid)); params.insert("o:name", enumValueName(String)); params.insert("o:deviceDescriptorId", enumValueName(Uuid)); - params.insert("o:deviceParams", QVariantList() << objectRef("Param")); + params.insert("o:deviceParams", objectRef()); params.insert("o:deviceId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); returns.insert("o:setupMethod", enumRef()); @@ -210,7 +210,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Returns a list of configured devices, optionally filtered by deviceId."; params.insert("o:deviceId", enumValueName(Uuid)); - returns.insert("devices", QVariantList() << objectRef("Device")); + returns.insert("devices", objectRef()); registerMethod("GetConfiguredDevices", description, params, returns); params.clear(); returns.clear(); @@ -220,10 +220,10 @@ DeviceHandler::DeviceHandler(QObject *parent) : "added device. Such results may be used to reconfigure existing devices and might be filtered " "in cases where only unknown devices are of interest."; params.insert("deviceClassId", enumValueName(Uuid)); - params.insert("o:discoveryParams", QVariantList() << objectRef("Param")); + params.insert("o:discoveryParams", objectRef()); returns.insert("deviceError", enumRef()); returns.insert("o:displayMessage", enumValueName(String)); - returns.insert("o:deviceDescriptors", QVariantList() << objectRef("DeviceDescriptor")); + returns.insert("o:deviceDescriptors", objectRef()); registerMethod("GetDiscoveredDevices", description, params, returns); params.clear(); returns.clear(); @@ -236,7 +236,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : "be changed."; params.insert("o:deviceId", enumValueName(Uuid)); params.insert("o:deviceDescriptorId", enumValueName(Uuid)); - params.insert("o:deviceParams", QVariantList() << objectRef("Param")); + params.insert("o:deviceParams", objectRef()); returns.insert("deviceError", enumRef()); returns.insert("o:displayMessage", enumValueName(String)); registerMethod("ReconfigureDevice", description, params, returns); @@ -252,7 +252,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Change the settings of a device."; params.insert("deviceId", enumValueName(Uuid)); - params.insert("settings", QVariantList() << objectRef("Param")); + params.insert("settings", objectRef()); returns.insert("deviceError", enumRef()); registerMethod("SetDeviceSettings", description, params, returns); @@ -273,19 +273,19 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Get event types for a specified deviceClassId."; params.insert("deviceClassId", enumValueName(Uuid)); - returns.insert("eventTypes", QVariantList() << objectRef("EventType")); + returns.insert("eventTypes", objectRef()); registerMethod("GetEventTypes", description, params, returns); params.clear(); returns.clear(); description = "Get action types for a specified deviceClassId."; params.insert("deviceClassId", enumValueName(Uuid)); - returns.insert("actionTypes", QVariantList() << objectRef("ActionType")); + returns.insert("actionTypes", objectRef()); registerMethod("GetActionTypes", description, params, returns); params.clear(); returns.clear(); description = "Get state types for a specified deviceClassId."; params.insert("deviceClassId", enumValueName(Uuid)); - returns.insert("stateTypes", QVariantList() << objectRef("StateType")); + returns.insert("stateTypes", objectRef()); registerMethod("GetStateTypes", description, params, returns); params.clear(); returns.clear(); @@ -300,10 +300,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : description = "Get all the state values of the given device."; params.insert("deviceId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); - QVariantMap state; - state.insert("stateTypeId", enumValueName(Uuid)); - state.insert("value", enumValueName(Variant)); - returns.insert("o:values", QVariantList() << state); + returns.insert("o:values", objectRef()); registerMethod("GetStateValues", description, params, returns); params.clear(); returns.clear(); @@ -337,12 +334,12 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Emitted whenever a Device was added."; - params.insert("device", objectRef("Device")); + params.insert("device", objectRef()); registerNotification("DeviceAdded", description, params); params.clear(); returns.clear(); description = "Emitted whenever the params or name of a Device are changed (by EditDevice or ReconfigureDevice)."; - params.insert("device", objectRef("Device")); + params.insert("device", objectRef()); registerNotification("DeviceChanged", description, params); params.clear(); returns.clear(); @@ -355,7 +352,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Emitted whenever a plugin's configuration is changed."; params.insert("pluginId", enumValueName(Uuid)); - params.insert("configuration", QVariantList() << objectRef("Param")); + params.insert("configuration", objectRef()); registerNotification("PluginConfigurationChanged", description, params); connect(NymeaCore::instance(), &NymeaCore::pluginConfigChanged, this, &DeviceHandler::pluginConfigChanged); diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp index a66b28c0..69ce0848 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp @@ -737,7 +737,7 @@ void JsonRPCServerImplementation::asyncReplyFinished() JsonValidator validator; Q_ASSERT_X(validator.validateReturns(reply->data(), reply->handler()->name() + '.' + reply->method(), m_api).success() ,validator.result().where().toUtf8() - ,validator.result().errorString().toUtf8()); + ,validator.result().errorString().toUtf8() + "\nReturn value:\n" + QJsonDocument::fromVariant(reply->data()).toJson()); sendResponse(interface, reply->clientId(), reply->commandId(), reply->data()); } else { qCWarning(dcJsonRpc()) << "RPC call timed out:" << reply->handler()->name() << ":" << reply->method(); diff --git a/libnymea-core/jsonrpc/networkmanagerhandler.cpp b/libnymea-core/jsonrpc/networkmanagerhandler.cpp index 0535e621..e38c82ee 100644 --- a/libnymea-core/jsonrpc/networkmanagerhandler.cpp +++ b/libnymea-core/jsonrpc/networkmanagerhandler.cpp @@ -85,28 +85,15 @@ NetworkManagerHandler::NetworkManagerHandler(QObject *parent) : registerEnum(); // Objects - QVariantMap wirelessAccessPoint; - wirelessAccessPoint.insert("ssid", enumValueName(String)); - wirelessAccessPoint.insert("macAddress", enumValueName(String)); - wirelessAccessPoint.insert("frequency", enumValueName(Double)); - wirelessAccessPoint.insert("signalStrength", enumValueName(Int)); - wirelessAccessPoint.insert("protected", enumValueName(Bool)); - registerObject("WirelessAccessPoint", wirelessAccessPoint); - - QVariantMap wiredNetworkDevice; - wiredNetworkDevice.insert("interface", enumValueName(String)); - wiredNetworkDevice.insert("macAddress", enumValueName(String)); - wiredNetworkDevice.insert("state", enumRef()); - wiredNetworkDevice.insert("bitRate", enumValueName(String)); - wiredNetworkDevice.insert("pluggedIn", enumValueName(Bool)); - registerObject("WiredNetworkDevice", wiredNetworkDevice); + registerUncreatableObject(); + registerUncreatableObject(); QVariantMap wirelessNetworkDevice; wirelessNetworkDevice.insert("interface", enumValueName(String)); wirelessNetworkDevice.insert("macAddress", enumValueName(String)); wirelessNetworkDevice.insert("state", enumRef()); wirelessNetworkDevice.insert("bitRate", enumValueName(String)); - wirelessNetworkDevice.insert("o:currentAccessPoint", objectRef("WirelessAccessPoint")); + wirelessNetworkDevice.insert("o:currentAccessPoint", objectRef()); registerObject("WirelessNetworkDevice", wirelessNetworkDevice); // Methods diff --git a/libnymea-core/jsonrpc/networkmanagerhandler.h b/libnymea-core/jsonrpc/networkmanagerhandler.h index 6ef9d93c..d9d15b75 100644 --- a/libnymea-core/jsonrpc/networkmanagerhandler.h +++ b/libnymea-core/jsonrpc/networkmanagerhandler.h @@ -75,9 +75,9 @@ private slots: void onWiredNetworkDeviceChanged(WiredNetworkDevice *networkDevice); private: - static QVariantMap packWirelessAccessPoint(WirelessAccessPoint *wirelessAccessPoint); - static QVariantMap packWiredNetworkDevice(WiredNetworkDevice *networkDevice); - static QVariantMap packWirelessNetworkDevice(WirelessNetworkDevice *networkDevice); + QVariantMap packWirelessAccessPoint(WirelessAccessPoint *wirelessAccessPoint); + QVariantMap packWiredNetworkDevice(WiredNetworkDevice *networkDevice); + QVariantMap packWirelessNetworkDevice(WirelessNetworkDevice *networkDevice); QVariantMap statusToReply(NetworkManager::NetworkManagerError status) const; diff --git a/libnymea-core/networkmanager/networkdevice.cpp b/libnymea-core/networkmanager/networkdevice.cpp index c875cbcc..c31272e5 100644 --- a/libnymea-core/networkmanager/networkdevice.cpp +++ b/libnymea-core/networkmanager/networkdevice.cpp @@ -334,7 +334,7 @@ QString NetworkDevice::deviceStateReasonToString(const NetworkDevice::NetworkDev void NetworkDevice::onStateChanged(uint newState, uint oldState, uint reason) { - Q_UNUSED(oldState); + Q_UNUSED(oldState) qCDebug(dcNetworkManager()) << m_interface << "--> State changed:" << deviceStateToString(NetworkDeviceState(newState)) << ":" << deviceStateReasonToString(NetworkDeviceStateReason(reason)); if (m_deviceState != NetworkDeviceState(newState)) { m_deviceState = NetworkDeviceState(newState); diff --git a/libnymea-core/networkmanager/wirednetworkdevice.h b/libnymea-core/networkmanager/wirednetworkdevice.h index a3d12510..e605cc68 100644 --- a/libnymea-core/networkmanager/wirednetworkdevice.h +++ b/libnymea-core/networkmanager/wirednetworkdevice.h @@ -31,8 +31,14 @@ namespace nymeaserver { class WiredNetworkDevice : public NetworkDevice { Q_OBJECT + Q_PROPERTY(QString interface READ interface) + Q_PROPERTY(QString macAddress READ macAddress) + Q_PROPERTY(NetworkDeviceState state READ deviceState) + Q_PROPERTY(QString bitRate READ bitRate) + Q_PROPERTY(bool pluggedIn READ pluggedIn) + public: - explicit WiredNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit WiredNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = nullptr); QString macAddress() const; int bitRate() const; diff --git a/libnymea-core/networkmanager/wirelessaccesspoint.h b/libnymea-core/networkmanager/wirelessaccesspoint.h index 6900658e..6c8375c9 100644 --- a/libnymea-core/networkmanager/wirelessaccesspoint.h +++ b/libnymea-core/networkmanager/wirelessaccesspoint.h @@ -36,6 +36,12 @@ class WirelessAccessPoint : public QObject Q_OBJECT Q_FLAGS(ApSecurityModes) + Q_PROPERTY(QString ssid READ ssid) + Q_PROPERTY(QString macAddress READ macAddress) + Q_PROPERTY(double frequency READ frequency) + Q_PROPERTY(int signalStrength READ signalStrength NOTIFY signalStrengthChanged) + Q_PROPERTY(bool protected READ isProtected) + public: enum ApSecurityMode{ ApSecurityModeNone = 0x000, @@ -53,7 +59,7 @@ public: Q_DECLARE_FLAGS(ApSecurityModes, ApSecurityMode) - explicit WirelessAccessPoint(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit WirelessAccessPoint(const QDBusObjectPath &objectPath, QObject *parent = nullptr); QDBusObjectPath objectPath() const; diff --git a/libnymea-core/networkmanager/wirelessnetworkdevice.h b/libnymea-core/networkmanager/wirelessnetworkdevice.h index f33ac6ea..90c10079 100644 --- a/libnymea-core/networkmanager/wirelessnetworkdevice.h +++ b/libnymea-core/networkmanager/wirelessnetworkdevice.h @@ -37,9 +37,15 @@ namespace nymeaserver { class WirelessNetworkDevice : public NetworkDevice { Q_OBJECT + Q_PROPERTY(QString interface READ interface) + Q_PROPERTY(QString macAddress READ macAddress) + Q_PROPERTY(NetworkDeviceState state READ deviceState) + Q_PROPERTY(QString bitRate READ bitRate) + Q_PROPERTY(WirelessAccessPoint* currentAccessPoint READ activeAccessPoint) + public: - explicit WirelessNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = 0); + explicit WirelessNetworkDevice(const QDBusObjectPath &objectPath, QObject *parent = nullptr); // Properties QString macAddress() const; diff --git a/libnymea/devices/device.cpp b/libnymea/devices/device.cpp index a0e2b0b4..a6126261 100644 --- a/libnymea/devices/device.cpp +++ b/libnymea/devices/device.cpp @@ -471,3 +471,13 @@ Devices Devices::filterByInterface(const QString &interface) } return ret; } + +QVariant Devices::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + +void Devices::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/devices/device.h b/libnymea/devices/device.h index 3ddc64f4..f2f14382 100644 --- a/libnymea/devices/device.h +++ b/libnymea/devices/device.h @@ -153,6 +153,8 @@ QDebug operator<<(QDebug dbg, Device *device); class LIBNYMEA_EXPORT Devices: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: Devices() = default; Devices(const QList &other); @@ -162,6 +164,8 @@ public: Devices filterByDeviceClassId(const DeviceClassId &deviceClassId); Devices filterByParentDeviceId(const DeviceId &deviceId); Devices filterByInterface(const QString &interface); + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(Device::DeviceError) diff --git a/libnymea/devices/devicedescriptor.cpp b/libnymea/devices/devicedescriptor.cpp index 654f5897..2d30d252 100644 --- a/libnymea/devices/devicedescriptor.cpp +++ b/libnymea/devices/devicedescriptor.cpp @@ -143,3 +143,13 @@ void DeviceDescriptor::setParams(const ParamList ¶ms) { m_params = params; } + +QVariant DeviceDescriptors::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + +void DeviceDescriptors::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/devices/devicedescriptor.h b/libnymea/devices/devicedescriptor.h index 15e84fc7..b4032ccf 100644 --- a/libnymea/devices/devicedescriptor.h +++ b/libnymea/devices/devicedescriptor.h @@ -76,10 +76,14 @@ private: class DeviceDescriptors: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: DeviceDescriptors() {} inline DeviceDescriptors(std::initializer_list args): QList(args) {} DeviceDescriptors(const QList &other): QList(other) {} + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(DeviceDescriptor) diff --git a/libnymea/devices/deviceplugin.cpp b/libnymea/devices/deviceplugin.cpp index c0e00d16..f3409c19 100644 --- a/libnymea/devices/deviceplugin.cpp +++ b/libnymea/devices/deviceplugin.cpp @@ -487,3 +487,13 @@ DevicePlugin *DevicePlugins::findById(const PluginId &id) const } return nullptr; } + +QVariant DevicePlugins::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + +void DevicePlugins::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/devices/deviceplugin.h b/libnymea/devices/deviceplugin.h index 8d485312..5efe5563 100644 --- a/libnymea/devices/deviceplugin.h +++ b/libnymea/devices/deviceplugin.h @@ -147,10 +147,14 @@ Q_DECLARE_METATYPE(DevicePlugin*) class LIBNYMEA_EXPORT DevicePlugins: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: DevicePlugins(); DevicePlugins(const QList &other); DevicePlugin* findById(const PluginId &id) const; + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; Q_DECLARE_METATYPE(DevicePlugins) diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index df43d22c..fd44089b 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -195,6 +195,20 @@ void JsonHandler::registerObject(const QMetaObject &metaObject) m_metaObjects.insert(className, metaObject); } +void JsonHandler::registerObject(const QMetaObject &metaObject, const QMetaObject &listMetaObject) +{ + registerObject(metaObject); + QString listTypeName = QString(listMetaObject.className()).split("::").last(); + QString objectTypeName = QString(metaObject.className()).split("::").last(); + m_objects.insert(listTypeName, QVariantList() << QVariant(QString("$ref:%1").arg(objectTypeName))); + m_metaObjects.insert(listTypeName, listMetaObject); + m_listMetaObjects.insert(listTypeName, listMetaObject); + m_listEntryTypes.insert(listTypeName, objectTypeName); + Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", QString("List type %1 does not implement \"count\" property!").arg(listTypeName).toUtf8()); + Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE QVariant get(int index)\" method!").arg(listTypeName).toUtf8()); + Q_ASSERT_X(listMetaObject.indexOfMethod("put(QVariant)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE void put(QVariant variant)\" method!").arg(listTypeName).toUtf8()); +} + QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) const { QString className = QString(metaObject.className()).split("::").last(); diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index d4f5fa5f..c477856a 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -78,11 +78,19 @@ public: protected: template void registerEnum(); template void registerEnum(); + template void registerObject(); - template void registerUncreatableObject(); template void registerObject(); + + template void registerUncreatableObject(); + template void registerUncreatableObject(); + template void registerList(BasicTypeName typeName); + + // Deprecated QString based registerObject void registerObject(const QString &name, const QVariantMap &object); + + void registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool deprecated = false); void registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool deprecated = false); @@ -92,6 +100,7 @@ protected: private: void registerObject(const QMetaObject &metaObject); + void registerObject(const QMetaObject &metaObject, const QMetaObject &listMetaObject); QVariant pack(const QMetaObject &metaObject, const void *gadget) const; QVariant unpack(const QMetaObject &metaObject, const QVariant &value) const; @@ -142,6 +151,16 @@ void JsonHandler::registerObject() registerObject(metaObject); } +template +void JsonHandler::registerObject() +{ + qRegisterMetaType(); + qRegisterMetaType(); + QMetaObject metaObject = ObjectType::staticMetaObject; + QMetaObject listMetaObject = ListType::staticMetaObject; + registerObject(metaObject, listMetaObject); +} + template void JsonHandler::registerUncreatableObject() { @@ -149,22 +168,12 @@ void JsonHandler::registerUncreatableObject() registerObject(metaObject); } -template -void JsonHandler::registerObject() +template +void JsonHandler::registerUncreatableObject() { - registerObject(); - qRegisterMetaType(); QMetaObject metaObject = ObjectType::staticMetaObject; QMetaObject listMetaObject = ListType::staticMetaObject; - QString listTypeName = QString(listMetaObject.className()).split("::").last(); - QString objectTypeName = QString(metaObject.className()).split("::").last(); - m_objects.insert(listTypeName, QVariantList() << QVariant(QString("$ref:%1").arg(objectTypeName))); - m_metaObjects.insert(listTypeName, listMetaObject); - m_listMetaObjects.insert(listTypeName, listMetaObject); - m_listEntryTypes.insert(listTypeName, objectTypeName); - Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", QString("List type %1 does not implement \"count\" property!").arg(listTypeName).toUtf8()); - Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE QVariant get(int index)\" method!").arg(listTypeName).toUtf8()); - Q_ASSERT_X(listMetaObject.indexOfMethod("put(QVariant)") >= 0, "JsonHandler", QString("List type %1 does not implement \"Q_INVOKABLE void put(QVariant variant)\" method!").arg(listTypeName).toUtf8()); + registerObject(metaObject, listMetaObject); } template diff --git a/libnymea/types/deviceclass.cpp b/libnymea/types/deviceclass.cpp index 7a62f26e..986c79cb 100644 --- a/libnymea/types/deviceclass.cpp +++ b/libnymea/types/deviceclass.cpp @@ -375,3 +375,13 @@ DeviceClass DeviceClasses::findById(const DeviceClassId &id) const } return DeviceClass(); } + +QVariant DeviceClasses::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + +void DeviceClasses::put(const QVariant &variant) +{ + append(variant.value()); +} diff --git a/libnymea/types/deviceclass.h b/libnymea/types/deviceclass.h index e03c494c..d65244a2 100644 --- a/libnymea/types/deviceclass.h +++ b/libnymea/types/deviceclass.h @@ -157,10 +157,14 @@ QDebug operator<<(QDebug &dbg, const DeviceClass &deviceClass); class LIBNYMEA_EXPORT DeviceClasses: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: DeviceClasses(); DeviceClasses(const QList &other); DeviceClass findById(const DeviceClassId &id) const; + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); }; #endif diff --git a/libnymea/types/vendor.cpp b/libnymea/types/vendor.cpp index fc0904bd..b0d63b84 100644 --- a/libnymea/types/vendor.cpp +++ b/libnymea/types/vendor.cpp @@ -95,6 +95,16 @@ Vendors::Vendors(const QList &other): QList(other) } +QVariant Vendors::get(int index) const +{ + return QVariant::fromValue(at(index)); +} + +void Vendors::put(const QVariant &variant) +{ + append(variant.value()); +} + Vendor Vendors::findById(const VendorId &vendorId) const { foreach (const Vendor &vendor, *this) { diff --git a/libnymea/types/vendor.h b/libnymea/types/vendor.h index 08cce26d..d8c383ba 100644 --- a/libnymea/types/vendor.h +++ b/libnymea/types/vendor.h @@ -29,6 +29,7 @@ #include #include +#include class LIBNYMEA_EXPORT Vendor { @@ -61,10 +62,13 @@ Q_DECLARE_METATYPE(Vendor) class LIBNYMEA_EXPORT Vendors: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: Vendors(); Vendors(const QList &other); - + Q_INVOKABLE QVariant get(int index) const; + Q_INVOKABLE void put(const QVariant &variant); Vendor findById(const VendorId &vendorId) const; }; Q_DECLARE_METATYPE(Vendors) diff --git a/tests/auto/api.json b/tests/auto/api.json index b703132d..57f5c4e5 100644 --- a/tests/auto/api.json +++ b/tests/auto/api.json @@ -1,14 +1,314 @@ -3.2 +4.0 { + "enums": { + "BasicType": [ + "Uuid", + "String", + "StringList", + "Int", + "Uint", + "Double", + "Bool", + "Variant", + "Color", + "Time", + "Object" + ], + "BrowserIcon": [ + "BrowserIconNone", + "BrowserIconFolder", + "BrowserIconFile", + "BrowserIconMusic", + "BrowserIconVideo", + "BrowserIconPictures", + "BrowserIconApplication", + "BrowserIconDocument", + "BrowserIconPackage", + "BrowserIconFavorites" + ], + "CloudConnectionState": [ + "CloudConnectionStateDisabled", + "CloudConnectionStateUnconfigured", + "CloudConnectionStateConnecting", + "CloudConnectionStateConnected" + ], + "ConfigurationError": [ + "ConfigurationErrorNoError", + "ConfigurationErrorInvalidTimeZone", + "ConfigurationErrorInvalidStationName", + "ConfigurationErrorInvalidId", + "ConfigurationErrorInvalidPort", + "ConfigurationErrorInvalidHostAddress", + "ConfigurationErrorBluetoothHardwareNotAvailable", + "ConfigurationErrorInvalidCertificate" + ], + "CreateMethod": [ + "CreateMethodUser", + "CreateMethodAuto", + "CreateMethodDiscovery" + ], + "DeviceError": [ + "DeviceErrorNoError", + "DeviceErrorPluginNotFound", + "DeviceErrorVendorNotFound", + "DeviceErrorDeviceNotFound", + "DeviceErrorDeviceClassNotFound", + "DeviceErrorActionTypeNotFound", + "DeviceErrorStateTypeNotFound", + "DeviceErrorEventTypeNotFound", + "DeviceErrorDeviceDescriptorNotFound", + "DeviceErrorMissingParameter", + "DeviceErrorInvalidParameter", + "DeviceErrorSetupFailed", + "DeviceErrorDuplicateUuid", + "DeviceErrorCreationMethodNotSupported", + "DeviceErrorSetupMethodNotSupported", + "DeviceErrorHardwareNotAvailable", + "DeviceErrorHardwareFailure", + "DeviceErrorAuthenticationFailure", + "DeviceErrorDeviceInUse", + "DeviceErrorDeviceInRule", + "DeviceErrorDeviceIsChild", + "DeviceErrorPairingTransactionIdNotFound", + "DeviceErrorParameterNotWritable", + "DeviceErrorItemNotFound", + "DeviceErrorItemNotExecutable", + "DeviceErrorUnsupportedFeature", + "DeviceErrorTimeout" + ], + "InputType": [ + "InputTypeNone", + "InputTypeTextLine", + "InputTypeTextArea", + "InputTypePassword", + "InputTypeSearch", + "InputTypeMail", + "InputTypeIPv4Address", + "InputTypeIPv6Address", + "InputTypeUrl", + "InputTypeMacAddress" + ], + "LoggingError": [ + "LoggingErrorNoError", + "LoggingErrorLogEntryNotFound", + "LoggingErrorInvalidFilterParameter" + ], + "LoggingEventType": [ + "LoggingEventTypeTrigger", + "LoggingEventTypeActiveChange", + "LoggingEventTypeEnabledChange", + "LoggingEventTypeActionsExecuted", + "LoggingEventTypeExitActionsExecuted" + ], + "LoggingLevel": [ + "LoggingLevelInfo", + "LoggingLevelAlert" + ], + "LoggingSource": [ + "LoggingSourceSystem", + "LoggingSourceEvents", + "LoggingSourceActions", + "LoggingSourceStates", + "LoggingSourceRules", + "LoggingSourceBrowserActions" + ], + "MediaBrowserIcon": [ + "MediaBrowserIconNone", + "MediaBrowserIconPlaylist", + "MediaBrowserIconRecentlyPlayed", + "MediaBrowserIconLibrary", + "MediaBrowserIconMusicLibrary", + "MediaBrowserIconVideoLibrary", + "MediaBrowserIconPictureLibrary", + "MediaBrowserIconDisk", + "MediaBrowserIconUSB", + "MediaBrowserIconNetwork", + "MediaBrowserIconAux", + "MediaBrowserIconSpotify", + "MediaBrowserIconAmazon", + "MediaBrowserIconTuneIn", + "MediaBrowserIconSiriusXM", + "MediaBrowserIconVTuner", + "MediaBrowserIconTidal", + "MediaBrowserIconAirable", + "MediaBrowserIconDeezer", + "MediaBrowserIconNapster", + "MediaBrowserIconSoundCloud" + ], + "NetworkDeviceState": [ + "NetworkDeviceStateUnknown", + "NetworkDeviceStateUnmanaged", + "NetworkDeviceStateUnavailable", + "NetworkDeviceStateDisconnected", + "NetworkDeviceStatePrepare", + "NetworkDeviceStateConfig", + "NetworkDeviceStateNeedAuth", + "NetworkDeviceStateIpConfig", + "NetworkDeviceStateIpCheck", + "NetworkDeviceStateSecondaries", + "NetworkDeviceStateActivated", + "NetworkDeviceStateDeactivating", + "NetworkDeviceStateFailed" + ], + "NetworkManagerError": [ + "NetworkManagerErrorNoError", + "NetworkManagerErrorUnknownError", + "NetworkManagerErrorWirelessNotAvailable", + "NetworkManagerErrorAccessPointNotFound", + "NetworkManagerErrorNetworkInterfaceNotFound", + "NetworkManagerErrorInvalidNetworkDeviceType", + "NetworkManagerErrorWirelessNetworkingDisabled", + "NetworkManagerErrorWirelessConnectionFailed", + "NetworkManagerErrorNetworkingDisabled", + "NetworkManagerErrorNetworkManagerNotAvailable" + ], + "NetworkManagerState": [ + "NetworkManagerStateUnknown", + "NetworkManagerStateAsleep", + "NetworkManagerStateDisconnected", + "NetworkManagerStateDisconnecting", + "NetworkManagerStateConnecting", + "NetworkManagerStateConnectedLocal", + "NetworkManagerStateConnectedSite", + "NetworkManagerStateConnectedGlobal" + ], + "RemovePolicy": [ + "RemovePolicyCascade", + "RemovePolicyUpdate" + ], + "RepeatingMode": [ + "RepeatingModeNone", + "RepeatingModeHourly", + "RepeatingModeDaily", + "RepeatingModeWeekly", + "RepeatingModeMonthly", + "RepeatingModeYearly" + ], + "RuleError": [ + "RuleErrorNoError", + "RuleErrorInvalidRuleId", + "RuleErrorRuleNotFound", + "RuleErrorDeviceNotFound", + "RuleErrorEventTypeNotFound", + "RuleErrorStateTypeNotFound", + "RuleErrorActionTypeNotFound", + "RuleErrorInvalidParameter", + "RuleErrorInvalidRuleFormat", + "RuleErrorMissingParameter", + "RuleErrorInvalidRuleActionParameter", + "RuleErrorInvalidStateEvaluatorValue", + "RuleErrorTypesNotMatching", + "RuleErrorNotExecutable", + "RuleErrorInvalidTimeDescriptor", + "RuleErrorInvalidRepeatingOption", + "RuleErrorInvalidCalendarItem", + "RuleErrorInvalidTimeEventItem", + "RuleErrorContainsEventBasesAction", + "RuleErrorNoExitActions", + "RuleErrorInterfaceNotFound" + ], + "SetupMethod": [ + "SetupMethodJustAdd", + "SetupMethodDisplayPin", + "SetupMethodEnterPin", + "SetupMethodPushButton", + "SetupMethodUserAndPassword", + "SetupMethodOAuth" + ], + "StateOperator": [ + "StateOperatorAnd", + "StateOperatorOr" + ], + "TagError": [ + "TagErrorNoError", + "TagErrorDeviceNotFound", + "TagErrorRuleNotFound", + "TagErrorTagNotFound" + ], + "Unit": [ + "UnitNone", + "UnitSeconds", + "UnitMinutes", + "UnitHours", + "UnitUnixTime", + "UnitMeterPerSecond", + "UnitKiloMeterPerHour", + "UnitDegree", + "UnitRadiant", + "UnitDegreeCelsius", + "UnitDegreeKelvin", + "UnitMired", + "UnitMilliBar", + "UnitBar", + "UnitPascal", + "UnitHectoPascal", + "UnitAtmosphere", + "UnitLumen", + "UnitLux", + "UnitCandela", + "UnitMilliMeter", + "UnitCentiMeter", + "UnitMeter", + "UnitKiloMeter", + "UnitGram", + "UnitKiloGram", + "UnitDezibel", + "UnitBpm", + "UnitKiloByte", + "UnitMegaByte", + "UnitGigaByte", + "UnitTeraByte", + "UnitMilliWatt", + "UnitWatt", + "UnitKiloWatt", + "UnitKiloWattHour", + "UnitEuroPerMegaWattHour", + "UnitEuroCentPerKiloWattHour", + "UnitPercentage", + "UnitPartsPerMillion", + "UnitEuro", + "UnitDollar", + "UnitHertz", + "UnitAmpere", + "UnitMilliAmpere", + "UnitVolt", + "UnitMilliVolt", + "UnitVoltAmpere", + "UnitVoltAmpereReactive", + "UnitAmpereHour", + "UnitMicroSiemensPerCentimeter", + "UnitDuration" + ], + "UserError": [ + "UserErrorNoError", + "UserErrorBackendError", + "UserErrorInvalidUserId", + "UserErrorDuplicateUserId", + "UserErrorBadPassword", + "UserErrorTokenNotFound", + "UserErrorPermissionDenied" + ], + "ValueOperator": [ + "ValueOperatorEquals", + "ValueOperatorNotEquals", + "ValueOperatorLess", + "ValueOperatorGreater", + "ValueOperatorLessOrEqual", + "ValueOperatorGreaterOrEqual" + ] + }, + "flags": { + "CreateMethods": [ + "$ref:CreateMethod" + ] + }, "methods": { "Actions.ExecuteAction": { "description": "Execute a single action.", "params": { "actionTypeId": "Uuid", "deviceId": "Uuid", - "o:params": [ - "$ref:Param" - ] + "o:params": "$ref:ParamList" }, "returns": { "deviceError": "$ref:DeviceError", @@ -31,9 +331,7 @@ "actionTypeId": "Uuid", "deviceId": "Uuid", "itemId": "String", - "o:params": [ - "$ref:Param" - ] + "o:params": "$ref:ParamList" }, "returns": { "deviceError": "$ref:DeviceError" @@ -46,15 +344,7 @@ }, "returns": { "deviceError": "$ref:DeviceError", - "o:actionType": { - "displayName": "String", - "id": "Uuid", - "index": "Int", - "name": "String", - "paramTypes": [ - "$ref:ParamType" - ] - } + "o:actionType": "$ref:ActionType" } }, "Configuration.DeleteMqttPolicy": { @@ -265,9 +555,7 @@ "deviceClassId": "Uuid", "name": "String", "o:deviceDescriptorId": "Uuid", - "o:deviceParams": [ - "$ref:Param" - ] + "o:deviceParams": "$ref:ParamList" }, "returns": { "deviceError": "$ref:DeviceError", @@ -317,9 +605,7 @@ "deviceClassId": "Uuid" }, "returns": { - "actionTypes": [ - "$ref:ActionType" - ] + "actionTypes": "$ref:ActionTypes" } }, "Devices.GetBrowserItem": { @@ -339,24 +625,18 @@ "o:deviceId": "Uuid" }, "returns": { - "devices": [ - "$ref:Device" - ] + "devices": "$ref:Devices" } }, "Devices.GetDiscoveredDevices": { "description": "Performs a device discovery and returns the results. This function may take a while to return. Note that this method will include all the found devices, that is, including devices that may already have been added. Those devices will have deviceId set to the device id of the already added device. Such results may be used to reconfigure existing devices and might be filtered in cases where only unknown devices are of interest.", "params": { "deviceClassId": "Uuid", - "o:discoveryParams": [ - "$ref:Param" - ] + "o:discoveryParams": "$ref:ParamList" }, "returns": { "deviceError": "$ref:DeviceError", - "o:deviceDescriptors": [ - "$ref:DeviceDescriptor" - ], + "o:deviceDescriptors": "$ref:DeviceDescriptors", "o:displayMessage": "String" } }, @@ -366,9 +646,7 @@ "deviceClassId": "Uuid" }, "returns": { - "eventTypes": [ - "$ref:EventType" - ] + "eventTypes": "$ref:EventTypes" } }, "Devices.GetPluginConfiguration": { @@ -378,9 +656,7 @@ }, "returns": { "deviceError": "$ref:DeviceError", - "o:configuration": [ - "$ref:Param" - ] + "o:configuration": "$ref:ParamList" } }, "Devices.GetPlugins": { @@ -388,9 +664,7 @@ "params": { }, "returns": { - "plugins": [ - "$ref:Plugin" - ] + "plugins": "$ref:DevicePlugins" } }, "Devices.GetStateTypes": { @@ -399,9 +673,7 @@ "deviceClassId": "Uuid" }, "returns": { - "stateTypes": [ - "$ref:StateType" - ] + "stateTypes": "$ref:StateTypes" } }, "Devices.GetStateValue": { @@ -422,12 +694,7 @@ }, "returns": { "deviceError": "$ref:DeviceError", - "o:values": [ - { - "stateTypeId": "Uuid", - "value": "Variant" - } - ] + "o:values": "$ref:States" } }, "Devices.GetSupportedDevices": { @@ -436,9 +703,7 @@ "o:vendorId": "Uuid" }, "returns": { - "deviceClasses": [ - "$ref:DeviceClass" - ] + "deviceClasses": "$ref:DeviceClasses" } }, "Devices.GetSupportedVendors": { @@ -446,9 +711,7 @@ "params": { }, "returns": { - "vendors": [ - "$ref:Vendor" - ] + "vendors": "$ref:Vendors" } }, "Devices.PairDevice": { @@ -457,9 +720,7 @@ "o:deviceClassId": "Uuid", "o:deviceDescriptorId": "Uuid", "o:deviceId": "Uuid", - "o:deviceParams": [ - "$ref:Param" - ], + "o:deviceParams": "$ref:ParamList", "o:name": "String" }, "returns": { @@ -476,9 +737,7 @@ "params": { "o:deviceDescriptorId": "Uuid", "o:deviceId": "Uuid", - "o:deviceParams": [ - "$ref:Param" - ] + "o:deviceParams": "$ref:ParamList" }, "returns": { "deviceError": "$ref:DeviceError", @@ -508,9 +767,7 @@ "description": "Change the settings of a device.", "params": { "deviceId": "Uuid", - "settings": [ - "$ref:Param" - ] + "settings": "$ref:ParamList" }, "returns": { "deviceError": "$ref:DeviceError" @@ -519,9 +776,7 @@ "Devices.SetPluginConfiguration": { "description": "Set a plugin's params.", "params": { - "configuration": [ - "$ref:Param" - ], + "configuration": "$ref:ParamList", "pluginId": "Uuid" }, "returns": { @@ -571,6 +826,9 @@ "language": "String", "locale": "String", "name": "String", + "o:experiences": [ + "$ref:Experience" + ], "protocol version": "String", "pushButtonAuthAvailable": "Bool", "server": "String", @@ -630,15 +888,11 @@ "description": "Enable/Disable notifications for this connections. Either \"enabled\" or \"namespaces\" needs to be given but not both of them. The boolean based \"enabled\" parameter will enable/disable all notifications at once. If instead the list-based \"namespaces\" parameter is provided, all given namespaceswill be enabled, the others will be disabled. The return value of \"success\" will indicate success of the operation. The \"enabled\" property in the return value is deprecated and used for legacy compatibilty only. It will be set to true if at least one namespace has been enabled.", "params": { "o:enabled": "Bool", - "o:namespaces": [ - "$ref:Namespace" - ] + "o:namespaces": "StringList" }, "returns": { "enabled": "Bool", - "namespaces": [ - "$ref:Namespace" - ] + "namespaces": "StringList" } }, "JSONRPC.SetupCloudConnection": { @@ -717,9 +971,7 @@ "returns": { "count": "Int", "loggingError": "$ref:LoggingError", - "o:logEntries": [ - "$ref:LogEntry" - ], + "o:logEntries": "$ref:LogEntries", "offset": "Int" } }, @@ -974,9 +1226,7 @@ "params": { }, "returns": { - "packages": [ - "$ref:Package" - ] + "packages": "$ref:Packages" } }, "System.GetRepositories": { @@ -984,9 +1234,7 @@ "params": { }, "returns": { - "repositories": [ - "$ref:Repository" - ] + "repositories": "$ref:Repositories" } }, "System.GetUpdateStatus": { @@ -1065,9 +1313,7 @@ "o:tagId": "String" }, "returns": { - "o:tags": [ - "$ref:Tag" - ], + "o:tags": "$ref:Tags", "tagError": "$ref:TagError" } }, @@ -1198,9 +1444,7 @@ "Devices.PluginConfigurationChanged": { "description": "Emitted whenever a plugin's configuration is changed.", "params": { - "configuration": [ - "$ref:Param" - ], + "configuration": "$ref:ParamList", "pluginId": "Uuid" } }, @@ -1388,43 +1632,17 @@ "Action": { "actionTypeId": "Uuid", "deviceId": "Uuid", - "o:params": [ - "$ref:Param" - ] + "o:params": "$ref:ParamList" }, "ActionType": { "displayName": "String", "id": "Uuid", "index": "Int", "name": "String", - "paramTypes": [ - "$ref:ParamType" - ] + "paramTypes": "$ref:ParamTypes" }, - "BasicType": [ - "Uuid", - "String", - "StringList", - "Int", - "Uint", - "Double", - "Bool", - "Variant", - "Color", - "Time", - "Object" - ], - "BrowserIcon": [ - "BrowserIconNone", - "BrowserIconFolder", - "BrowserIconFile", - "BrowserIconMusic", - "BrowserIconVideo", - "BrowserIconPictures", - "BrowserIconApplication", - "BrowserIconDocument", - "BrowserIconPackage", - "BrowserIconFavorites" + "ActionTypes": [ + "$ref:ActionType" ], "BrowserItem": { "actionTypeIds": [ @@ -1446,156 +1664,93 @@ "o:repeating": "$ref:RepeatingOption", "o:startTime": "Time" }, - "CloudConnectionState": [ - "CloudConnectionStateDisabled", - "CloudConnectionStateUnconfigured", - "CloudConnectionStateConnecting", - "CloudConnectionStateConnected" - ], - "ConfigurationError": [ - "ConfigurationErrorNoError", - "ConfigurationErrorInvalidTimeZone", - "ConfigurationErrorInvalidStationName", - "ConfigurationErrorInvalidId", - "ConfigurationErrorInvalidPort", - "ConfigurationErrorInvalidHostAddress", - "ConfigurationErrorBluetoothHardwareNotAvailable", - "ConfigurationErrorInvalidCertificate" - ], - "CreateMethod": [ - "CreateMethodUser", - "CreateMethodAuto", - "CreateMethodDiscovery" + "CalendarItems": [ + "$ref:CalendarItem" ], "Device": { "deviceClassId": "Uuid", "id": "Uuid", "name": "String", "o:parentId": "Uuid", - "params": [ - "$ref:Param" - ], - "settings": [ - "$ref:Param" - ], + "params": "$ref:ParamList", + "settings": "$ref:ParamList", "setupComplete": "Bool", - "states": [ - { - "stateTypeId": "Uuid", - "value": "Variant" - } - ] + "states": "$ref:States" }, "DeviceClass": { - "actionTypes": [ - "$ref:ActionType" - ], + "actionTypes": "$ref:ActionTypes", "browsable": "Bool", - "browserItemActionTypes": [ - "$ref:ActionType" - ], - "createMethods": [ - "$ref:CreateMethod" - ], - "discoveryParamTypes": [ - "$ref:ParamType" - ], + "browserItemActionTypes": "$ref:ActionTypes", + "createMethods": "$ref:CreateMethods", + "discoveryParamTypes": "$ref:ParamTypes", "displayName": "String", - "eventTypes": [ - "$ref:EventType" - ], + "eventTypes": "$ref:EventTypes", "id": "Uuid", - "interfaces": [ - "String" - ], + "interfaces": "StringList", "name": "String", - "paramTypes": [ - "$ref:ParamType" - ], + "paramTypes": "$ref:ParamTypes", "pluginId": "Uuid", - "settingsTypes": [ - "$ref:ParamType" - ], + "settingsTypes": "$ref:ParamTypes", "setupMethod": "$ref:SetupMethod", - "stateTypes": [ - "$ref:StateType" - ], + "stateTypes": "$ref:StateTypes", "vendorId": "Uuid" }, + "DeviceClasses": [ + "$ref:DeviceClass" + ], "DeviceDescriptor": { "description": "String", - "deviceId": "Uuid", - "deviceParams": [ - "$ref:Param" - ], + "deviceParams": "$ref:ParamList", "id": "Uuid", + "o:deviceId": "Uuid", "title": "String" }, - "DeviceError": [ - "DeviceErrorNoError", - "DeviceErrorPluginNotFound", - "DeviceErrorVendorNotFound", - "DeviceErrorDeviceNotFound", - "DeviceErrorDeviceClassNotFound", - "DeviceErrorActionTypeNotFound", - "DeviceErrorStateTypeNotFound", - "DeviceErrorEventTypeNotFound", - "DeviceErrorDeviceDescriptorNotFound", - "DeviceErrorMissingParameter", - "DeviceErrorInvalidParameter", - "DeviceErrorSetupFailed", - "DeviceErrorDuplicateUuid", - "DeviceErrorCreationMethodNotSupported", - "DeviceErrorSetupMethodNotSupported", - "DeviceErrorHardwareNotAvailable", - "DeviceErrorHardwareFailure", - "DeviceErrorAuthenticationFailure", - "DeviceErrorDeviceInUse", - "DeviceErrorDeviceInRule", - "DeviceErrorDeviceIsChild", - "DeviceErrorPairingTransactionIdNotFound", - "DeviceErrorParameterNotWritable", - "DeviceErrorItemNotFound", - "DeviceErrorItemNotExecutable", - "DeviceErrorUnsupportedFeature", - "DeviceErrorTimeout" + "DeviceDescriptors": [ + "$ref:DeviceDescriptor" + ], + "DevicePlugin": { + "displayName": "String", + "id": "Uuid", + "name": "String", + "paramTypes": "$ref:ParamTypes" + }, + "DevicePlugins": [ + "$ref:DevicePlugin" + ], + "Devices": [ + "$ref:Device" ], "Event": { "deviceId": "Uuid", "eventTypeId": "Uuid", - "o:params": [ - "$ref:Param" - ] + "params": "$ref:ParamList" }, "EventDescriptor": { "o:deviceId": "Uuid", "o:eventTypeId": "Uuid", "o:interface": "String", "o:interfaceEvent": "String", - "o:paramDescriptors": [ - "$ref:ParamDescriptor" - ] + "o:paramDescriptors": "$ref:ParamDescriptors" }, + "EventDescriptors": [ + "$ref:EventDescriptor" + ], "EventType": { "displayName": "String", "id": "Uuid", "index": "Int", "name": "String", - "paramTypes": [ - "$ref:ParamType" - ] + "paramTypes": "$ref:ParamTypes" }, - "InputType": [ - "InputTypeNone", - "InputTypeTextLine", - "InputTypeTextArea", - "InputTypePassword", - "InputTypeSearch", - "InputTypeMail", - "InputTypeIPv4Address", - "InputTypeIPv6Address", - "InputTypeUrl", - "InputTypeMacAddress" + "EventTypes": [ + "$ref:EventType" + ], + "Experience": { + "name": "String", + "version": "String" + }, + "LogEntries": [ + "$ref:LogEntry" ], "LogEntry": { "loggingLevel": "$ref:LoggingLevel", @@ -1603,59 +1758,11 @@ "o:deviceId": "Uuid", "o:errorCode": "String", "o:eventType": "$ref:LoggingEventType", - "o:itemId": "String", "o:typeId": "Uuid", - "o:value": "String", + "o:value": "Variant", "source": "$ref:LoggingSource", - "timestamp": "Int" + "timestamp": "Uint" }, - "LoggingError": [ - "LoggingErrorNoError", - "LoggingErrorLogEntryNotFound", - "LoggingErrorInvalidFilterParameter" - ], - "LoggingEventType": [ - "LoggingEventTypeTrigger", - "LoggingEventTypeActiveChange", - "LoggingEventTypeEnabledChange", - "LoggingEventTypeActionsExecuted", - "LoggingEventTypeExitActionsExecuted" - ], - "LoggingLevel": [ - "LoggingLevelInfo", - "LoggingLevelAlert" - ], - "LoggingSource": [ - "LoggingSourceSystem", - "LoggingSourceEvents", - "LoggingSourceActions", - "LoggingSourceStates", - "LoggingSourceRules", - "LoggingSourceBrowserActions" - ], - "MediaBrowserIcon": [ - "MediaBrowserIconNone", - "MediaBrowserIconPlaylist", - "MediaBrowserIconRecentlyPlayed", - "MediaBrowserIconLibrary", - "MediaBrowserIconMusicLibrary", - "MediaBrowserIconVideoLibrary", - "MediaBrowserIconPictureLibrary", - "MediaBrowserIconDisk", - "MediaBrowserIconUSB", - "MediaBrowserIconNetwork", - "MediaBrowserIconAux", - "MediaBrowserIconSpotify", - "MediaBrowserIconAmazon", - "MediaBrowserIconTuneIn", - "MediaBrowserIconSiriusXM", - "MediaBrowserIconVTuner", - "MediaBrowserIconTidal", - "MediaBrowserIconAirable", - "MediaBrowserIconDeezer", - "MediaBrowserIconNapster", - "MediaBrowserIconSoundCloud" - ], "MqttPolicy": { "allowedPublishTopicFilters": "StringList", "allowedSubscribeTopicFilters": "StringList", @@ -1663,56 +1770,6 @@ "password": "String", "username": "String" }, - "Namespace": [ - "Actions", - "Configuration", - "Devices", - "Events", - "JSONRPC", - "Logging", - "NetworkManager", - "Rules", - "States", - "System", - "Tags" - ], - "NetworkDeviceState": [ - "NetworkDeviceStateUnknown", - "NetworkDeviceStateUnmanaged", - "NetworkDeviceStateUnavailable", - "NetworkDeviceStateDisconnected", - "NetworkDeviceStatePrepare", - "NetworkDeviceStateConfig", - "NetworkDeviceStateNeedAuth", - "NetworkDeviceStateIpConfig", - "NetworkDeviceStateIpCheck", - "NetworkDeviceStateSecondaries", - "NetworkDeviceStateActivated", - "NetworkDeviceStateDeactivating", - "NetworkDeviceStateFailed" - ], - "NetworkManagerError": [ - "NetworkManagerErrorNoError", - "NetworkManagerErrorUnknownError", - "NetworkManagerErrorWirelessNotAvailable", - "NetworkManagerErrorAccessPointNotFound", - "NetworkManagerErrorNetworkInterfaceNotFound", - "NetworkManagerErrorInvalidNetworkDeviceType", - "NetworkManagerErrorWirelessNetworkingDisabled", - "NetworkManagerErrorWirelessConnectionFailed", - "NetworkManagerErrorNetworkingDisabled", - "NetworkManagerErrorNetworkManagerNotAvailable" - ], - "NetworkManagerState": [ - "NetworkManagerStateUnknown", - "NetworkManagerStateAsleep", - "NetworkManagerStateDisconnected", - "NetworkManagerStateDisconnecting", - "NetworkManagerStateConnecting", - "NetworkManagerStateConnectedLocal", - "NetworkManagerStateConnectedSite", - "NetworkManagerStateConnectedGlobal" - ], "Package": { "canRemove": "Bool", "candidateVersion": "String", @@ -1724,16 +1781,25 @@ "summary": "String", "updateAvailable": "Bool" }, + "Packages": [ + "$ref:Package" + ], "Param": { - "paramTypeId": "Uuid", - "value": "$ref:BasicType" + "o:paramTypeId": "Uuid", + "value": "Variant" }, "ParamDescriptor": { - "o:paramName": "Uuid", + "o:paramName": "String", "o:paramTypeId": "Uuid", "operator": "$ref:ValueOperator", - "value": "$ref:BasicType" + "value": "Variant" }, + "ParamDescriptors": [ + "$ref:ParamDescriptor" + ], + "ParamList": [ + "$ref:Param" + ], "ParamType": { "displayName": "String", "id": "Uuid", @@ -1750,25 +1816,8 @@ "o:unit": "$ref:Unit", "type": "$ref:BasicType" }, - "Plugin": { - "displayName": "String", - "id": "Uuid", - "name": "String", - "paramTypes": [ - "$ref:ParamType" - ] - }, - "RemovePolicy": [ - "RemovePolicyCascade", - "RemovePolicyUpdate" - ], - "RepeatingMode": [ - "RepeatingModeNone", - "RepeatingModeHourly", - "RepeatingModeDaily", - "RepeatingModeWeekly", - "RepeatingModeMonthly", - "RepeatingModeYearly" + "ParamTypes": [ + "$ref:ParamType" ], "RepeatingOption": { "mode": "$ref:RepeatingMode", @@ -1779,28 +1828,25 @@ "Int" ] }, + "Repositories": [ + "$ref:Repository" + ], "Repository": { "displayName": "String", "enabled": "Bool", "id": "String" }, "Rule": { - "actions": [ - "$ref:RuleAction" - ], - "active": "Bool", - "enabled": "Bool", - "eventDescriptors": [ - "$ref:EventDescriptor" - ], - "executable": "Bool", - "exitActions": [ - "$ref:RuleAction" - ], - "id": "Uuid", + "actions": "$ref:RuleActions", "name": "String", - "stateEvaluator": "$ref:StateEvaluator", - "timeDescriptor": "$ref:TimeDescriptor" + "o:active": "Bool", + "o:enabled": "Bool", + "o:eventDescriptors": "$ref:EventDescriptors", + "o:executable": "Bool", + "o:exitActions": "$ref:RuleActions", + "o:id": "Uuid", + "o:stateEvaluator": "$ref:StateEvaluator", + "o:timeDescriptor": "$ref:TimeDescriptor" }, "RuleAction": { "o:actionTypeId": "Uuid", @@ -1808,9 +1854,7 @@ "o:deviceId": "Uuid", "o:interface": "String", "o:interfaceAction": "String", - "o:ruleActionParams": [ - "$ref:RuleActionParam" - ] + "o:ruleActionParams": "$ref:RuleActionParams" }, "RuleActionParam": { "o:eventParamTypeId": "Uuid", @@ -1819,8 +1863,14 @@ "o:paramTypeId": "Uuid", "o:stateDeviceId": "Uuid", "o:stateTypeId": "Uuid", - "o:value": "$ref:BasicType" + "o:value": "Variant" }, + "RuleActionParams": [ + "$ref:RuleActionParam" + ], + "RuleActions": [ + "$ref:RuleAction" + ], "RuleDescription": { "active": "Bool", "enabled": "Bool", @@ -1828,28 +1878,8 @@ "id": "Uuid", "name": "String" }, - "RuleError": [ - "RuleErrorNoError", - "RuleErrorInvalidRuleId", - "RuleErrorRuleNotFound", - "RuleErrorDeviceNotFound", - "RuleErrorEventTypeNotFound", - "RuleErrorStateTypeNotFound", - "RuleErrorActionTypeNotFound", - "RuleErrorInvalidParameter", - "RuleErrorInvalidRuleFormat", - "RuleErrorMissingParameter", - "RuleErrorInvalidRuleActionParameter", - "RuleErrorInvalidStateEvaluatorValue", - "RuleErrorTypesNotMatching", - "RuleErrorNotExecutable", - "RuleErrorInvalidTimeDescriptor", - "RuleErrorInvalidRepeatingOption", - "RuleErrorInvalidCalendarItem", - "RuleErrorInvalidTimeEventItem", - "RuleErrorContainsEventBasesAction", - "RuleErrorNoExitActions", - "RuleErrorInterfaceNotFound" + "Rules": [ + "$ref:Rule" ], "ServerConfiguration": { "address": "String", @@ -1858,16 +1888,7 @@ "port": "Uint", "sslEnabled": "Bool" }, - "SetupMethod": [ - "SetupMethodJustAdd", - "SetupMethodDisplayPin", - "SetupMethodEnterPin", - "SetupMethodPushButton", - "SetupMethodUserAndPassword", - "SetupMethodOAuth" - ], "State": { - "deviceId": "Uuid", "stateTypeId": "Uuid", "value": "Variant" }, @@ -1880,15 +1901,12 @@ "value": "Variant" }, "StateEvaluator": { - "o:childEvaluators": [ - "$ref:StateEvaluator" - ], + "o:childEvaluators": "$ref:StateEvaluators", "o:operator": "$ref:StateOperator", "o:stateDescriptor": "$ref:StateDescriptor" }, - "StateOperator": [ - "StateOperatorAnd", - "StateOperatorOr" + "StateEvaluators": [ + "$ref:StateEvaluator" ], "StateType": { "defaultValue": "Variant", @@ -1904,6 +1922,12 @@ "o:unit": "$ref:Unit", "type": "$ref:BasicType" }, + "StateTypes": [ + "$ref:StateType" + ], + "States": [ + "$ref:State" + ], "Tag": { "appId": "String", "o:deviceId": "Uuid", @@ -1911,112 +1935,41 @@ "o:value": "String", "tagId": "String" }, - "TagError": [ - "TagErrorNoError", - "TagErrorDeviceNotFound", - "TagErrorRuleNotFound", - "TagErrorTagNotFound" + "Tags": [ + "$ref:Tag" ], "TimeDescriptor": { - "o:calendarItems": [ - "$ref:CalendarItem" - ], - "o:timeEventItems": [ - "$ref:TimeEventItem" - ] + "o:calendarItems": "$ref:CalendarItems", + "o:timeEventItems": "$ref:TimeEventItems" }, "TimeEventItem": { "o:datetime": "Uint", "o:repeating": "$ref:RepeatingOption", "o:time": "Time" }, + "TimeEventItems": [ + "$ref:TimeEventItem" + ], "TokenInfo": { "creationTime": "Uint", - "deviceName": "String", + "deviveName": "String", "id": "Uuid", - "userName": "String" + "username": "String" }, - "Unit": [ - "UnitNone", - "UnitSeconds", - "UnitMinutes", - "UnitHours", - "UnitUnixTime", - "UnitMeterPerSecond", - "UnitKiloMeterPerHour", - "UnitDegree", - "UnitRadiant", - "UnitDegreeCelsius", - "UnitDegreeKelvin", - "UnitMired", - "UnitMilliBar", - "UnitBar", - "UnitPascal", - "UnitHectoPascal", - "UnitAtmosphere", - "UnitLumen", - "UnitLux", - "UnitCandela", - "UnitMilliMeter", - "UnitCentiMeter", - "UnitMeter", - "UnitKiloMeter", - "UnitGram", - "UnitKiloGram", - "UnitDezibel", - "UnitBpm", - "UnitKiloByte", - "UnitMegaByte", - "UnitGigaByte", - "UnitTeraByte", - "UnitMilliWatt", - "UnitWatt", - "UnitKiloWatt", - "UnitKiloWattHour", - "UnitEuroPerMegaWattHour", - "UnitEuroCentPerKiloWattHour", - "UnitPercentage", - "UnitPartsPerMillion", - "UnitEuro", - "UnitDollar", - "UnitHertz", - "UnitAmpere", - "UnitMilliAmpere", - "UnitVolt", - "UnitMilliVolt", - "UnitVoltAmpere", - "UnitVoltAmpereReactive", - "UnitAmpereHour", - "UnitMicroSiemensPerCentimeter", - "UnitDuration" - ], - "UserError": [ - "UserErrorNoError", - "UserErrorBackendError", - "UserErrorInvalidUserId", - "UserErrorDuplicateUserId", - "UserErrorBadPassword", - "UserErrorTokenNotFound", - "UserErrorPermissionDenied" - ], - "ValueOperator": [ - "ValueOperatorEquals", - "ValueOperatorNotEquals", - "ValueOperatorLess", - "ValueOperatorGreater", - "ValueOperatorLessOrEqual", - "ValueOperatorGreaterOrEqual" - ], "Vendor": { "displayName": "String", "id": "Uuid", "name": "String" }, + "Vendors": [ + "$ref:Vendor" + ], "WebServerConfiguration": { "address": "String", "authenticationEnabled": "Bool", "id": "String", "port": "Uint", + "publicFolder": "String", "sslEnabled": "Bool" }, "WiredNetworkDevice": { diff --git a/tests/auto/configurations/testconfigurations.cpp b/tests/auto/configurations/testconfigurations.cpp index 3412f670..3bcdb4de 100644 --- a/tests/auto/configurations/testconfigurations.cpp +++ b/tests/auto/configurations/testconfigurations.cpp @@ -321,7 +321,7 @@ void TestConfigurations::testDebugServerConfiguration() QVariantMap basicConfigurationMap = loadBasicConfiguration(); bool debugServerEnabled = basicConfigurationMap.value("debugServerEnabled").toBool(); - qDebug() << "Debug server enabled" << debugServerEnabled; + qCDebug(dcTests) << "Debug server enabled" << debugServerEnabled; QSignalSpy notificationSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); @@ -341,6 +341,8 @@ void TestConfigurations::testDebugServerConfiguration() params.clear(); response.clear(); configurationChangedNotifications.clear(); params.insert("enabled", newValue); + qCDebug(dcTests()) << "Enabling debug server"; + notificationSpy.clear(); response = injectAndWait("Configuration.SetDebugServerEnabled", params); verifyConfigurationError(response); @@ -361,7 +363,7 @@ void TestConfigurations::testDebugServerConfiguration() QVERIFY2(basicConfigurationNotificationMap.contains("debugServerEnabled"), "Notification does not contain key debugServerEnabled"); QVERIFY2(basicConfigurationNotificationMap.value("debugServerEnabled").toBool() == newValue, "Notification does not contain the new debugServerEnabled"); - qDebug() << "TestWebserver starting"; + qCDebug(dcTests()) << "TestWebserver starting"; foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; @@ -369,7 +371,7 @@ void TestConfigurations::testDebugServerConfiguration() } } - qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; + qCDebug(dcTests) << "Creating new webserver instance on 127.0.0.1:3333"; WebServerConfiguration config; config.id = "Testwebserver for debug server interface"; config.address = QHostAddress("127.0.0.1"); diff --git a/tests/auto/jsonrpc/testjsonrpc.cpp b/tests/auto/jsonrpc/testjsonrpc.cpp index 51a666fd..e1c69d14 100644 --- a/tests/auto/jsonrpc/testjsonrpc.cpp +++ b/tests/auto/jsonrpc/testjsonrpc.cpp @@ -738,18 +738,17 @@ void TestJSONRPC::ruleAddedRemovedNotifications() QVariantMap actionNoParams; actionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); actionNoParams.insert("deviceId", m_mockDeviceId); - actionNoParams.insert("ruleActionParams", QVariantList()); // EventDescriptor QVariantMap eventDescriptor; eventDescriptor.insert("eventTypeId", mockEvent1EventTypeId); eventDescriptor.insert("deviceId", m_mockDeviceId); - eventDescriptor.insert("paramDescriptors", QVariantList()); + QVariantList eventDescriptors = QVariantList() << eventDescriptor; QVariantMap params; params.insert("name", "Test Rule notifications"); params.insert("actions", QVariantList() << actionNoParams); - params.insert("eventDescriptors", QVariantList() << eventDescriptor); + params.insert("eventDescriptors", eventDescriptors); params.insert("stateEvaluator", stateEvaluator); QVariant response = injectAndWait("Rules.AddRule", params); @@ -765,7 +764,11 @@ void TestJSONRPC::ruleAddedRemovedNotifications() QCOMPARE(notificationRuleMap.value("id").toString(), ruleId.toString()); QCOMPARE(notificationRuleMap.value("actions").toList(), QVariantList() << actionNoParams); QCOMPARE(notificationRuleMap.value("stateEvaluator").toMap().value("stateDescriptor").toMap(), stateDescriptor); - QCOMPARE(notificationRuleMap.value("eventDescriptors").toList(), QVariantList() << eventDescriptor); + QVERIFY2(notificationRuleMap.value("eventDescriptors").toList() == eventDescriptors, + QString("eventDescriptors not matching.\nExpected: %1\nGot %2") + .arg(QString(QJsonDocument::fromVariant(eventDescriptors).toJson())) + .arg(QString(QJsonDocument::fromVariant(notificationRuleMap.value("eventDescriptors").toList()).toJson())) + .toUtf8()); QCOMPARE(notificationRuleMap.value("exitActions").toList(), QVariantList()); // now remove the rule and check the RuleRemoved notification @@ -802,7 +805,6 @@ void TestJSONRPC::ruleActiveChangedNotifications() QVariantMap actionNoParams; actionNoParams.insert("actionTypeId", mockWithoutParamsActionTypeId); actionNoParams.insert("deviceId", m_mockDeviceId); - actionNoParams.insert("ruleActionParams", QVariantList()); params.clear(); response.clear(); params.insert("name", "Test Rule notifications"); diff --git a/tests/scripts/getconfigureddevices.sh b/tests/scripts/getconfigureddevices.sh index cbd8d221..1d6a39dd 100755 --- a/tests/scripts/getconfigureddevices.sh +++ b/tests/scripts/getconfigureddevices.sh @@ -6,14 +6,14 @@ if [ -z $1 ]; then fi if [ -z $2 ]; then -cat < Date: Mon, 4 Nov 2019 10:52:36 +0100 Subject: [PATCH 17/22] Deprecate Actions/Events/States namespaces --- libnymea-core/jsonrpc/actionhandler.cpp | 10 +-- libnymea-core/jsonrpc/devicehandler.cpp | 103 ++++++++++++++++++++++++ libnymea-core/jsonrpc/devicehandler.h | 5 ++ libnymea-core/jsonrpc/eventhandler.cpp | 4 +- libnymea-core/jsonrpc/statehandler.cpp | 2 +- libnymea/jsonrpc/jsonhandler.cpp | 12 ++- libnymea/jsonrpc/jsonhandler.h | 4 +- 7 files changed, 126 insertions(+), 14 deletions(-) diff --git a/libnymea-core/jsonrpc/actionhandler.cpp b/libnymea-core/jsonrpc/actionhandler.cpp index e981dda4..eafe3cff 100644 --- a/libnymea-core/jsonrpc/actionhandler.cpp +++ b/libnymea-core/jsonrpc/actionhandler.cpp @@ -67,21 +67,21 @@ ActionHandler::ActionHandler(QObject *parent) : params.insert("o:params", objectRef()); returns.insert("deviceError", enumRef()); returns.insert("o:displayMessage", enumValueName(String)); - registerMethod("ExecuteAction", description, params, returns); + registerMethod("ExecuteAction", description, params, returns, "Please use Devices.ExecuteAction instead."); params.clear(); returns.clear(); - description = "Get the ActionType for the given ActionTypeId"; + description = "Get the ActionType for the given ActionTypeId."; params.insert("actionTypeId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); returns.insert("o:actionType", objectRef()); - registerMethod("GetActionType", description, params, returns); + registerMethod("GetActionType", description, params, returns, "Please use the Devices namespace instead."); params.clear(); returns.clear(); description = "Execute the item identified by itemId on the given device."; params.insert("deviceId", enumValueName(Uuid)); params.insert("itemId", enumValueName(String)); returns.insert("deviceError", enumRef()); - registerMethod("ExecuteBrowserItem", description, params, returns); + registerMethod("ExecuteBrowserItem", description, params, returns, "Please use Devices.ExecuteBrowserItem instead."); params.clear(); returns.clear(); description = "Execute the action for the browser item identified by actionTypeId and the itemId on the given device."; @@ -90,7 +90,7 @@ ActionHandler::ActionHandler(QObject *parent) : params.insert("actionTypeId", enumValueName(Uuid)); params.insert("o:params", objectRef()); returns.insert("deviceError", enumRef()); - registerMethod("ExecuteBrowserItemAction", description, params, returns); + registerMethod("ExecuteBrowserItemAction", description, params, returns, "Please use Devices.ExecuteBrowserItem instead."); } diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 42e51c11..e4b074fd 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -97,6 +97,8 @@ DeviceHandler::DeviceHandler(QObject *parent) : registerObject(); registerObject(); registerObject(); + registerObject(); + registerObject(); registerObject(); registerUncreatableObject(); @@ -319,6 +321,31 @@ DeviceHandler::DeviceHandler(QObject *parent) : returns.insert("o:item", objectRef("BrowserItem")); registerMethod("GetBrowserItem", description, params, returns); + params.clear(); returns.clear(); + description = "Execute a single action."; + params.insert("actionTypeId", enumValueName(Uuid)); + params.insert("deviceId", enumValueName(Uuid)); + params.insert("o:params", objectRef()); + returns.insert("deviceError", enumRef()); + returns.insert("o:displayMessage", enumValueName(String)); + registerMethod("ExecuteAction", description, params, returns); + + params.clear(); returns.clear(); + description = "Execute the item identified by itemId on the given device."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("itemId", enumValueName(String)); + returns.insert("deviceError", enumRef()); + registerMethod("ExecuteBrowserItem", description, params, returns); + + params.clear(); returns.clear(); + description = "Execute the action for the browser item identified by actionTypeId and the itemId on the given device."; + params.insert("deviceId", enumValueName(Uuid)); + params.insert("itemId", enumValueName(String)); + params.insert("actionTypeId", enumValueName(Uuid)); + params.insert("o:params", objectRef()); + returns.insert("deviceError", enumRef()); + registerMethod("ExecuteBrowserItemAction", description, params, returns); + // Notifications params.clear(); returns.clear(); description = "Emitted whenever a State of a device changes."; @@ -355,6 +382,16 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.insert("configuration", objectRef()); registerNotification("PluginConfigurationChanged", description, params); + params.clear(); returns.clear(); + description = "Emitted whenever an Event is triggered."; + params.insert("event", objectRef()); + registerNotification("EventTriggered", description, params, "Please use Devices.EventTriggered instead."); + connect(NymeaCore::instance(), &NymeaCore::eventTriggered, this, [this](const Event &event){ + QVariantMap params; + params.insert("event", pack(event)); + emit EventTriggered(params); + }); + connect(NymeaCore::instance(), &NymeaCore::pluginConfigChanged, this, &DeviceHandler::pluginConfigChanged); connect(NymeaCore::instance(), &NymeaCore::deviceStateChanged, this, &DeviceHandler::deviceStateChanged); connect(NymeaCore::instance(), &NymeaCore::deviceRemoved, this, &DeviceHandler::deviceRemovedNotification); @@ -801,6 +838,72 @@ JsonReply *DeviceHandler::GetBrowserItem(const QVariantMap ¶ms) const return jsonReply; } +JsonReply *DeviceHandler::ExecuteAction(const QVariantMap ¶ms) +{ + DeviceId deviceId(params.value("deviceId").toString()); + ActionTypeId actionTypeId(params.value("actionTypeId").toString()); + ParamList actionParams = unpack(params.value("params")); + QLocale locale = params.value("locale").toLocale(); + + Action action(actionTypeId, deviceId); + action.setParams(actionParams); + + JsonReply *jsonReply = createAsyncReply("ExecuteAction"); + + DeviceActionInfo *info = NymeaCore::instance()->executeAction(action); + connect(info, &DeviceActionInfo::finished, jsonReply, [info, jsonReply, locale](){ + QVariantMap data; + data.insert("deviceError", enumValueName(info->status())); + if (!info->displayMessage().isEmpty()) { + data.insert("displayMessage", info->translatedDisplayMessage(locale)); + } + jsonReply->setData(data); + jsonReply->finished(); + }); + + return jsonReply; +} + +JsonReply *DeviceHandler::ExecuteBrowserItem(const QVariantMap ¶ms) +{ + DeviceId deviceId = DeviceId(params.value("deviceId").toString()); + QString itemId = params.value("itemId").toString(); + BrowserAction action(deviceId, itemId); + + JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItem"); + + BrowserActionInfo *info = NymeaCore::instance()->executeBrowserItem(action); + connect(info, &BrowserActionInfo::finished, jsonReply, [info, jsonReply](){ + QVariantMap data; + data.insert("deviceError", enumValueName(info->status())); + jsonReply->setData(data); + jsonReply->finished(); + }); + + return jsonReply; +} + +JsonReply *DeviceHandler::ExecuteBrowserItemAction(const QVariantMap ¶ms) +{ + DeviceId deviceId = DeviceId(params.value("deviceId").toString()); + QString itemId = params.value("itemId").toString(); + ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString()); + ParamList paramList = unpack(params.value("params")); + BrowserItemAction browserItemAction(deviceId, itemId, actionTypeId, paramList); + + JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItemAction"); + + BrowserItemActionInfo *info = NymeaCore::instance()->executeBrowserItemAction(browserItemAction); + connect(info, &BrowserItemActionInfo::finished, jsonReply, [info, jsonReply](){ + QVariantMap data; + data.insert("deviceError", enumValueName(info->status())); + jsonReply->setData(data); + jsonReply->finished(); + }); + + return jsonReply; +} + QVariantMap DeviceHandler::packBrowserItem(const BrowserItem &item) { QVariantMap ret; diff --git a/libnymea-core/jsonrpc/devicehandler.h b/libnymea-core/jsonrpc/devicehandler.h index fcde2d3c..d95a0727 100644 --- a/libnymea-core/jsonrpc/devicehandler.h +++ b/libnymea-core/jsonrpc/devicehandler.h @@ -60,6 +60,10 @@ public: Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap ¶ms) const; + Q_INVOKABLE JsonReply *ExecuteAction(const QVariantMap ¶ms); + Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap ¶ms); + Q_INVOKABLE JsonReply *ExecuteBrowserItemAction(const QVariantMap ¶ms); + static QVariantMap packBrowserItem(const BrowserItem &item); signals: @@ -69,6 +73,7 @@ signals: void DeviceAdded(const QVariantMap ¶ms); void DeviceChanged(const QVariantMap ¶ms); void DeviceSettingChanged(const QVariantMap ¶ms); + void EventTriggered(const QVariantMap ¶ms); private slots: void pluginConfigChanged(const PluginId &id, const ParamList &config); diff --git a/libnymea-core/jsonrpc/eventhandler.cpp b/libnymea-core/jsonrpc/eventhandler.cpp index 283fa26d..f1e8a93e 100644 --- a/libnymea-core/jsonrpc/eventhandler.cpp +++ b/libnymea-core/jsonrpc/eventhandler.cpp @@ -61,13 +61,13 @@ EventHandler::EventHandler(QObject *parent) : params.insert("eventTypeId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); returns.insert("o:eventType", objectRef()); - registerMethod("GetEventType", description, params, returns); + registerMethod("GetEventType", description, params, returns, "Please use the Devices namespace instead."); // Notifications params.clear(); returns.clear(); description = "Emitted whenever an Event is triggered."; params.insert("event", objectRef()); - registerNotification("EventTriggered", description, params); + registerNotification("EventTriggered", description, params, "Please use Devices.EventTriggered instead."); connect(NymeaCore::instance(), &NymeaCore::eventTriggered, this, &EventHandler::eventTriggered); } diff --git a/libnymea-core/jsonrpc/statehandler.cpp b/libnymea-core/jsonrpc/statehandler.cpp index 07eb1b88..65281a44 100644 --- a/libnymea-core/jsonrpc/statehandler.cpp +++ b/libnymea-core/jsonrpc/statehandler.cpp @@ -52,7 +52,7 @@ StateHandler::StateHandler(QObject *parent) : params.insert("stateTypeId", enumValueName(Uuid)); returns.insert("deviceError", enumRef()); returns.insert("o:stateType", objectRef()); - registerMethod("GetStateType", description, params, returns, true); + registerMethod("GetStateType", description, params, returns, "Please use the Devices namespace instead."); } /*! Returns the name of the \l{StateHandler}. In this case \b States.*/ diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index fd44089b..f2df0559 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -125,23 +125,27 @@ void JsonHandler::registerObject(const QString &name, const QVariantMap &object) m_objects.insert(name, object); } -void JsonHandler::registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool /*deprecated*/) +void JsonHandler::registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, const QString &deprecationInfo) { QVariantMap methodData; methodData.insert("description", description); methodData.insert("params", params); methodData.insert("returns", returns); -// methodData.insert("deprecated", deprecated); + if (!deprecationInfo.isEmpty()) { + methodData.insert("deprecated", deprecationInfo); + } m_methods.insert(name, methodData); } -void JsonHandler::registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool /*deprecated*/) +void JsonHandler::registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, const QString &deprecationInfo) { QVariantMap notificationData; notificationData.insert("description", description); notificationData.insert("params", params); -// notificationData.insert("deprecated", deprecated); + if (!deprecationInfo.isEmpty()) { + notificationData.insert("deprecated", deprecationInfo); + } m_notifications.insert(name, notificationData); } diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index c477856a..ff4e06b2 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -91,8 +91,8 @@ protected: void registerObject(const QString &name, const QVariantMap &object); - void registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool deprecated = false); - void registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool deprecated = false); + void registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, const QString &deprecationInfo = QString()); + void registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, const QString &deprecationInfo = QString()); JsonReply *createReply(const QVariantMap &data) const; JsonReply *createAsyncReply(const QString &method) const; From fa1cd3605c03ab0a417a5f64e1fe8a15a24f70d0 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 4 Nov 2019 11:47:16 +0100 Subject: [PATCH 18/22] Add deprecation warnings --- libnymea-core/jsonrpc/devicehandler.cpp | 2 +- .../jsonrpc/jsonrpcserverimplementation.cpp | 55 +++++- .../jsonrpc/jsonrpcserverimplementation.h | 2 +- libnymea/jsonrpc/jsonhandler.cpp | 5 - tests/auto/api.json | 49 ++++- tests/auto/devices/testdevices.cpp | 185 ++++++++++++++++++ tests/auto/events/testevents.cpp | 32 +++ 7 files changed, 313 insertions(+), 17 deletions(-) diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index e4b074fd..367b0c88 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -385,7 +385,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Emitted whenever an Event is triggered."; params.insert("event", objectRef()); - registerNotification("EventTriggered", description, params, "Please use Devices.EventTriggered instead."); + registerNotification("EventTriggered", description, params); connect(NymeaCore::instance(), &NymeaCore::eventTriggered, this, [this](const Event &event){ QVariantMap params; params.insert("event", pack(event)); diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp index 69ce0848..8aded8dc 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp @@ -467,13 +467,17 @@ bool JsonRPCServerImplementation::registerExperienceHandler(JsonHandler *handler /*! Send a JSON success response to the client with the given \a clientId, * \a commandId and \a params to the inerted \l{TransportInterface}. */ -void JsonRPCServerImplementation::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms) +void JsonRPCServerImplementation::sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms, const QString &deprecationWarning) { QVariantMap response; response.insert("id", commandId); response.insert("status", "success"); response.insert("params", params); + if (!deprecationWarning.isEmpty()) { + response.insert("deprecationWarning", deprecationWarning); + } + QByteArray data = QJsonDocument::fromVariant(response).toJson(QJsonDocument::Compact); qCDebug(dcJsonRpcTraffic()) << "Sending data:" << data; interface->sendData(clientId, data); @@ -694,7 +698,15 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac Q_ASSERT_X((targetNamespace == "JSONRPC" && method == "Introspect") || validator.validateReturns(reply->data(), targetNamespace + '.' + method, m_api).success(), validator.result().where().toUtf8(), validator.result().errorString().toUtf8() + "\nReturn value:\n" + QJsonDocument::fromVariant(reply->data()).toJson()); - sendResponse(interface, clientId, commandId, reply->data()); + + QString deprecationWarning; + if (m_api.value("methods").toMap().value(targetNamespace + '.' + method).toMap().contains("deprecated")) { + deprecationWarning = m_api.value("methods").toMap().value(targetNamespace + '.' + method).toMap().value("deprecated").toString(); + qCWarning(dcJsonRpc()) << "Client uses deprecated API. Please update client implementation!"; + qCWarning(dcJsonRpc()) << targetNamespace + '.' + method + ':' << deprecationWarning; + } + + sendResponse(interface, clientId, commandId, reply->data(), deprecationWarning); reply->deleteLater(); } } @@ -704,6 +716,16 @@ void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms) JsonHandler *handler = qobject_cast(sender()); QMetaMethod method = handler->metaObject()->method(senderSignalIndex()); + QList clientsToBeNotified; + foreach (const QUuid &clientId, m_clientNotifications.keys()) { + if (m_clientNotifications.value(clientId).contains(handler->name())) { + clientsToBeNotified.append(clientId); + } + } + if (clientsToBeNotified.isEmpty()) { + return; + } + QVariantMap notification; notification.insert("id", m_notificationId++); notification.insert("notification", handler->name() + "." + method.name()); @@ -713,14 +735,20 @@ void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms) Q_ASSERT_X(validator.validateNotificationParams(params, handler->name() + '.' + method.name(), m_api).success(), validator.result().where().toUtf8(), validator.result().errorString().toUtf8()); + + if (m_api.value("notifications").toMap().value(handler->name() + '.' + method.name()).toMap().contains("deprecated")) { + QString deprecationMessage = m_api.value("notifications").toMap().value(handler->name() + '.' + method.name()).toMap().value("deprecated").toString(); + qCWarning(dcJsonRpc()) << "Client uses deprecated API. Please update client implementation!"; + qCWarning(dcJsonRpc()) << handler->name() + '.' + method.name() + ':' << deprecationMessage; + notification.insert("deprecationWarning", deprecationMessage); + } + QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact); - qCDebug(dcJsonRpc()) << "Sending notification:" << handler->name() + "." + method.name(); qCDebug(dcJsonRpcTraffic()) << "Notification content:" << data; - foreach (const QUuid &clientId, m_clientNotifications.keys()) { - if (m_clientNotifications.value(clientId).contains(handler->name())) { - m_clientTransports.value(clientId)->sendData(clientId, data); - } + foreach (const QUuid &clientId, clientsToBeNotified) { + qCDebug(dcJsonRpc()) << "Sending notification:" << handler->name() + "." + method.name(); + m_clientTransports.value(clientId)->sendData(clientId, data); } } @@ -735,10 +763,19 @@ void JsonRPCServerImplementation::asyncReplyFinished() } if (!reply->timedOut()) { JsonValidator validator; - Q_ASSERT_X(validator.validateReturns(reply->data(), reply->handler()->name() + '.' + reply->method(), m_api).success() + QString method = reply->handler()->name() + '.' + reply->method(); + Q_ASSERT_X(validator.validateReturns(reply->data(), method, m_api).success() ,validator.result().where().toUtf8() ,validator.result().errorString().toUtf8() + "\nReturn value:\n" + QJsonDocument::fromVariant(reply->data()).toJson()); - sendResponse(interface, reply->clientId(), reply->commandId(), reply->data()); + + QString deprecationWarning; + if (m_api.value("methods").toMap().value(method).toMap().contains("deprecated")) { + deprecationWarning = m_api.value("methods").toMap().value(method).toMap().value("deprecated").toString(); + qCWarning(dcJsonRpc()) << "Client uses deprecated API. Please update client implementation!"; + qCWarning(dcJsonRpc()) << method + ':' << deprecationWarning; + } + + sendResponse(interface, reply->clientId(), reply->commandId(), reply->data(), deprecationWarning); } else { qCWarning(dcJsonRpc()) << "RPC call timed out:" << reply->handler()->name() << ":" << reply->method(); sendErrorResponse(interface, reply->clientId(), reply->commandId(), "Command timed out"); diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h index 59bcea8e..097066e7 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h @@ -78,7 +78,7 @@ private: bool registerHandler(JsonHandler *handler); QHash handlers() const; - void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms = QVariantMap()); + void sendResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QVariantMap ¶ms = QVariantMap(), const QString &deprecationWarning = QString()); void sendErrorResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error); void sendUnauthorizedResponse(TransportInterface *interface, const QUuid &clientId, int commandId, const QString &error); QVariantMap createWelcomeMessage(TransportInterface *interface, const QUuid &clientId) const; diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index f2df0559..85c22b43 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -307,7 +307,6 @@ QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) con // Manually converting QList... Only QVariantList is known to the meta system if (propertyTypeName.startsWith("QList")) { - qWarning() << "Packing list" << metaProperty.name() << propertyValue.toList(); QVariantList list; foreach (int entry, propertyValue.value>()) { list << entry; @@ -350,7 +349,6 @@ QVariant JsonHandler::unpack(const QMetaObject &metaObject, const QVariant &valu // If it's a list object, loop over count if (m_listMetaObjects.contains(typeName)) { - qWarning() << "** Unpacking" << typeName; if (value.type() != QVariant::List) { qCWarning(dcJsonRpc()) << "Cannot unpack" << typeName << ". Value is not in list format:" << value; return QVariant(); @@ -367,7 +365,6 @@ QVariant JsonHandler::unpack(const QMetaObject &metaObject, const QVariant &valu foreach (const QVariant &variant, list) { QVariant value = unpack(entryMetaObject, variant); - qWarning() << "Putting" << value << putMethod.name() << ptr << typeId; putMethod.invokeOnGadget(ptr, Q_ARG(QVariant, value)); } @@ -378,7 +375,6 @@ QVariant JsonHandler::unpack(const QMetaObject &metaObject, const QVariant &valu // if it's an object, loop over all properties if (m_metaObjects.contains(typeName)) { - qWarning() << "*** Unpacking" << typeName; QVariantMap map = value.toMap(); int typeId = QMetaType::type(metaObject.className()); Q_ASSERT_X(typeId != 0, this->metaObject()->className(), QString("Cannot handle unregistered meta type %1").arg(typeName).toUtf8()); @@ -403,7 +399,6 @@ QVariant JsonHandler::unpack(const QMetaObject &metaObject, const QVariant &valu // recurse into child lists if (m_listMetaObjects.contains(propertyTypeName)) { QMetaObject propertyMetaObject = m_listMetaObjects.value(propertyTypeName); - qWarning() << "Entering list object" << propertyTypeName << propertyMetaObject.className(); metaProperty.writeOnGadget(ptr, unpack(propertyMetaObject, variant)); continue; } diff --git a/tests/auto/api.json b/tests/auto/api.json index 57f5c4e5..95483d3c 100644 --- a/tests/auto/api.json +++ b/tests/auto/api.json @@ -304,6 +304,7 @@ }, "methods": { "Actions.ExecuteAction": { + "deprecated": "Please use Devices.ExecuteAction instead.", "description": "Execute a single action.", "params": { "actionTypeId": "Uuid", @@ -316,6 +317,7 @@ } }, "Actions.ExecuteBrowserItem": { + "deprecated": "Please use Devices.ExecuteBrowserItem instead.", "description": "Execute the item identified by itemId on the given device.", "params": { "deviceId": "Uuid", @@ -326,6 +328,7 @@ } }, "Actions.ExecuteBrowserItemAction": { + "deprecated": "Please use Devices.ExecuteBrowserItem instead.", "description": "Execute the action for the browser item identified by actionTypeId and the itemId on the given device.", "params": { "actionTypeId": "Uuid", @@ -338,7 +341,8 @@ } }, "Actions.GetActionType": { - "description": "Get the ActionType for the given ActionTypeId", + "deprecated": "Please use the Devices namespace instead.", + "description": "Get the ActionType for the given ActionTypeId.", "params": { "actionTypeId": "Uuid" }, @@ -599,6 +603,40 @@ "deviceError": "$ref:DeviceError" } }, + "Devices.ExecuteAction": { + "description": "Execute a single action.", + "params": { + "actionTypeId": "Uuid", + "deviceId": "Uuid", + "o:params": "$ref:ParamList" + }, + "returns": { + "deviceError": "$ref:DeviceError", + "o:displayMessage": "String" + } + }, + "Devices.ExecuteBrowserItem": { + "description": "Execute the item identified by itemId on the given device.", + "params": { + "deviceId": "Uuid", + "itemId": "String" + }, + "returns": { + "deviceError": "$ref:DeviceError" + } + }, + "Devices.ExecuteBrowserItemAction": { + "description": "Execute the action for the browser item identified by actionTypeId and the itemId on the given device.", + "params": { + "actionTypeId": "Uuid", + "deviceId": "Uuid", + "itemId": "String", + "o:params": "$ref:ParamList" + }, + "returns": { + "deviceError": "$ref:DeviceError" + } + }, "Devices.GetActionTypes": { "description": "Get action types for a specified deviceClassId.", "params": { @@ -784,6 +822,7 @@ } }, "Events.GetEventType": { + "deprecated": "Please use the Devices namespace instead.", "description": "Get the EventType for the given eventTypeId.", "params": { "eventTypeId": "Uuid" @@ -1185,6 +1224,7 @@ } }, "States.GetStateType": { + "deprecated": "Please use the Devices namespace instead.", "description": "Get the StateType for the given stateTypeId.", "params": { "stateTypeId": "Uuid" @@ -1441,6 +1481,12 @@ "value": "Variant" } }, + "Devices.EventTriggered": { + "description": "Emitted whenever an Event is triggered.", + "params": { + "event": "$ref:Event" + } + }, "Devices.PluginConfigurationChanged": { "description": "Emitted whenever a plugin's configuration is changed.", "params": { @@ -1457,6 +1503,7 @@ } }, "Events.EventTriggered": { + "deprecated": "Please use Devices.EventTriggered instead.", "description": "Emitted whenever an Event is triggered.", "params": { "event": "$ref:Event" diff --git a/tests/auto/devices/testdevices.cpp b/tests/auto/devices/testdevices.cpp index 02ee3ea8..6a4a771a 100644 --- a/tests/auto/devices/testdevices.cpp +++ b/tests/auto/devices/testdevices.cpp @@ -26,6 +26,8 @@ #include "devices/devicediscoveryinfo.h" #include "devices/devicesetupinfo.h" +#include "servers/mocktcpserver.h" + using namespace nymeaserver; class TestDevices : public NymeaTestBase @@ -117,6 +119,14 @@ private slots: void testExecuteBrowserItemAction_data(); void testExecuteBrowserItemAction(); + void executeAction_data(); + void executeAction(); + + void triggerEvent(); + void triggerStateChangeEvent(); + + void params(); + // Keep those at last as they will remove devices void removeDevice_data(); void removeDevice(); @@ -1777,6 +1787,181 @@ void TestDevices::testExecuteBrowserItemAction() } +void TestDevices::executeAction_data() +{ + QTest::addColumn("deviceId"); + QTest::addColumn("actionTypeId"); + QTest::addColumn("actionParams"); + QTest::addColumn("error"); + + QVariantList params; + QVariantMap param1; + param1.insert("paramTypeId", mockWithParamsActionParam1ParamTypeId); + param1.insert("value", 5); + params.append(param1); + QVariantMap param2; + param2.insert("paramTypeId", mockWithParamsActionParam2ParamTypeId); + param2.insert("value", true); + params.append(param2); + + QTest::newRow("valid action") << m_mockDeviceId << mockWithParamsActionTypeId << params << Device::DeviceErrorNoError; + QTest::newRow("invalid deviceId") << DeviceId::createDeviceId() << mockWithParamsActionTypeId << params << Device::DeviceErrorDeviceNotFound; + QTest::newRow("invalid actionTypeId") << m_mockDeviceId << ActionTypeId::createActionTypeId() << params << Device::DeviceErrorActionTypeNotFound; + QTest::newRow("missing params") << m_mockDeviceId << mockWithParamsActionTypeId << QVariantList() << Device::DeviceErrorMissingParameter; + QTest::newRow("async action") << m_mockDeviceId << mockAsyncActionTypeId << QVariantList() << Device::DeviceErrorNoError; + QTest::newRow("broken action") << m_mockDeviceId << mockFailingActionTypeId << QVariantList() << Device::DeviceErrorSetupFailed; + QTest::newRow("async broken action") << m_mockDeviceId << mockAsyncFailingActionTypeId << QVariantList() << Device::DeviceErrorSetupFailed; +} + +void TestDevices::executeAction() +{ + QFETCH(DeviceId, deviceId); + QFETCH(ActionTypeId, actionTypeId); + QFETCH(QVariantList, actionParams); + QFETCH(Device::DeviceError, error); + + QVariantMap params; + params.insert("actionTypeId", actionTypeId); + params.insert("deviceId", deviceId); + params.insert("params", actionParams); + QVariant response = injectAndWait("Devices.ExecuteAction", params); + qDebug() << "executeActionresponse" << response; + verifyError(response, "deviceError", enumValueName(error)); + + // Fetch action execution history from mock device + QNetworkAccessManager nam; + QSignalSpy spy(&nam, SIGNAL(finished(QNetworkReply*))); + + QNetworkRequest request(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port))); + QNetworkReply *reply = nam.get(request); + spy.wait(); + QCOMPARE(spy.count(), 1); + reply->deleteLater(); + QByteArray data = reply->readAll(); + + if (error == Device::DeviceErrorNoError) { + QVERIFY2(actionTypeId == ActionTypeId(data), QString("ActionTypeId mismatch. Got %1, Expected: %2") + .arg(ActionTypeId(data).toString()).arg(actionTypeId.toString()).toLatin1().data()); + } else { + QVERIFY2(data.length() == 0, QString("Data is %1, should be empty.").arg(QString(data)).toLatin1().data()); + } + + // cleanup for the next run + spy.clear(); + request.setUrl(QUrl(QString("http://localhost:%1/clearactionhistory").arg(m_mockDevice1Port))); + reply = nam.get(request); + spy.wait(); + QCOMPARE(spy.count(), 1); + reply->deleteLater(); + + spy.clear(); + request.setUrl(QUrl(QString("http://localhost:%1/actionhistory").arg(m_mockDevice1Port))); + reply = nam.get(request); + spy.wait(); + QCOMPARE(spy.count(), 1); + reply->deleteLater(); + data = reply->readAll(); + qDebug() << "cleared data:" << data; + +} + +void TestDevices::triggerEvent() +{ + enableNotifications({"Devices"}); + QList devices = NymeaCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceClassId); + QVERIFY2(devices.count() > 0, "There needs to be at least one configured Mock Device for this test"); + Device *device = devices.first(); + + + QSignalSpy spy(NymeaCore::instance(), SIGNAL(eventTriggered(const Event&))); + QSignalSpy notificationSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); + + // Setup connection to mock client + QNetworkAccessManager nam; + + // trigger event in mock device + int port = device->paramValue(mockDeviceHttpportParamTypeId).toInt(); + QNetworkRequest request(QUrl(QString("http://localhost:%1/generateevent?eventtypeid=%2").arg(port).arg(mockEvent1EventTypeId.toString()))); + QNetworkReply *reply = nam.get(request); + connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); + + // Lets wait for the notification + spy.wait(); + QVERIFY(spy.count() > 0); + for (int i = 0; i < spy.count(); i++ ){ + Event event = spy.at(i).at(0).value(); + if (event.deviceId() == device->id()) { + // Make sure the event contains all the stuff we expect + QCOMPARE(event.eventTypeId(), mockEvent1EventTypeId); + } + } + + // Check for the notification on JSON API + QVariantList notifications; + notifications = checkNotifications(notificationSpy, "Devices.EventTriggered"); + QVERIFY2(notifications.count() == 1, "Should get Devices.EventTriggered notification"); + QVariantMap notificationContent = notifications.first().toMap().value("params").toMap(); + + QCOMPARE(notificationContent.value("event").toMap().value("deviceId").toUuid().toString(), device->id().toString()); + QCOMPARE(notificationContent.value("event").toMap().value("eventTypeId").toUuid().toString(), mockEvent1EventTypeId.toString()); +} + +void TestDevices::triggerStateChangeEvent() +{ + enableNotifications({"Devices"}); + + QList devices = NymeaCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceClassId); + QVERIFY2(devices.count() > 0, "There needs to be at least one configured Mock Device for this test"); + Device *device = devices.first(); + + QSignalSpy spy(NymeaCore::instance(), SIGNAL(eventTriggered(const Event&))); + QSignalSpy notificationSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); + + // Setup connection to mock client + QNetworkAccessManager nam; + + // trigger state changed event in mock device + int port = device->paramValue(mockDeviceHttpportParamTypeId).toInt(); + QNetworkRequest request(QUrl(QString("http://localhost:%1/setstate?%2=%3").arg(port).arg(mockIntStateTypeId.toString()).arg(11))); + QNetworkReply *reply = nam.get(request); + connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); + + // Lets wait for the notification + spy.wait(); + QVERIFY(spy.count() > 0); + for (int i = 0; i < spy.count(); i++ ){ + Event event = spy.at(i).at(0).value(); + if (event.deviceId() == device->id()) { + // Make sure the event contains all the stuff we expect + QCOMPARE(event.eventTypeId().toString(), mockIntStateTypeId.toString()); + QCOMPARE(event.param(ParamTypeId(mockIntStateTypeId.toString())).value().toInt(), 11); + } + } + + // Check for the notification on JSON API + QVariantList notifications; + notifications = checkNotifications(notificationSpy, "Devices.EventTriggered"); + QVERIFY2(notifications.count() == 1, "Should get Devices.EventTriggered notification"); + QVariantMap notificationContent = notifications.first().toMap().value("params").toMap(); + + QCOMPARE(notificationContent.value("event").toMap().value("deviceId").toUuid().toString(), device->id().toString()); + QCOMPARE(notificationContent.value("event").toMap().value("eventTypeId").toUuid().toString(), mockIntEventTypeId.toString()); + +} + +void TestDevices::params() +{ + Event event; + ParamList params; + ParamTypeId id = ParamTypeId::createParamTypeId(); + Param p(id, "foo bar"); + params.append(p); + event.setParams(params); + + QVERIFY(event.param(id).value().toString() == "foo bar"); + QVERIFY(!event.param(ParamTypeId::createParamTypeId()).value().isValid()); +} + #include "testdevices.moc" QTEST_MAIN(TestDevices) diff --git a/tests/auto/events/testevents.cpp b/tests/auto/events/testevents.cpp index 63005268..6edf2b86 100644 --- a/tests/auto/events/testevents.cpp +++ b/tests/auto/events/testevents.cpp @@ -22,6 +22,8 @@ #include "nymeatestbase.h" #include "nymeacore.h" +#include "servers/mocktcpserver.h" + using namespace nymeaserver; class TestEvents: public NymeaTestBase @@ -40,11 +42,14 @@ private slots: void TestEvents::triggerEvent() { + enableNotifications({"Events"}); + QList devices = NymeaCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceClassId); QVERIFY2(devices.count() > 0, "There needs to be at least one configured Mock Device for this test"); Device *device = devices.first(); QSignalSpy spy(NymeaCore::instance(), SIGNAL(eventTriggered(const Event&))); + QSignalSpy notificationSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); // Setup connection to mock client QNetworkAccessManager nam; @@ -65,15 +70,28 @@ void TestEvents::triggerEvent() QCOMPARE(event.eventTypeId(), mockEvent1EventTypeId); } } + + // Check for the notification on JSON API + QVariantList notifications; + notifications = checkNotifications(notificationSpy, "Events.EventTriggered"); + QVERIFY2(notifications.count() == 1, "Should get Events.EventTriggered notification"); + QVERIFY2(notifications.first().toMap().contains("deprecationWarning"), "Deprecation warning not included in notification"); + + QVariantMap notificationContent = notifications.first().toMap().value("params").toMap(); + QCOMPARE(notificationContent.value("event").toMap().value("deviceId").toUuid().toString(), device->id().toString()); + QCOMPARE(notificationContent.value("event").toMap().value("eventTypeId").toUuid().toString(), mockEvent1EventTypeId.toString()); } void TestEvents::triggerStateChangeEvent() { + enableNotifications({"Events"}); + QList devices = NymeaCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceClassId); QVERIFY2(devices.count() > 0, "There needs to be at least one configured Mock Device for this test"); Device *device = devices.first(); QSignalSpy spy(NymeaCore::instance(), SIGNAL(eventTriggered(const Event&))); + QSignalSpy notificationSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray))); // Setup connection to mock client QNetworkAccessManager nam; @@ -95,6 +113,17 @@ void TestEvents::triggerStateChangeEvent() QCOMPARE(event.param(ParamTypeId(mockIntStateTypeId.toString())).value().toInt(), 11); } } + + // Check for the notification on JSON API + QVariantList notifications; + notifications = checkNotifications(notificationSpy, "Events.EventTriggered"); + QVERIFY2(notifications.count() == 1, "Should get Devices.EventTriggered notification"); + QVERIFY2(notifications.first().toMap().contains("deprecationWarning"), "Deprecation warning not included in notification!"); + + QVariantMap notificationContent = notifications.first().toMap().value("params").toMap(); + + QCOMPARE(notificationContent.value("event").toMap().value("deviceId").toUuid().toString(), device->id().toString()); + QCOMPARE(notificationContent.value("event").toMap().value("eventTypeId").toUuid().toString(), mockIntEventTypeId.toString()); } void TestEvents::params() @@ -130,6 +159,9 @@ void TestEvents::getEventType() verifyError(response, "deviceError", enumValueName(error)); + qCDebug(dcTests()) << "*content" << response; + QVERIFY2(response.toMap().contains("deprecationWarning"), "Deprecation warning not shown in reply"); + if (error == Device::DeviceErrorNoError) { QVERIFY2(EventTypeId(response.toMap().value("params").toMap().value("eventType").toMap().value("id").toString()) == eventTypeId, "Didn't get a reply for the same actionTypeId as requested."); } From ad32ee86ceffab5e12ebb44be9c68a27a0f18358 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Mon, 4 Nov 2019 14:36:21 +0100 Subject: [PATCH 19/22] silence false positive warning --- libnymea/jsonrpc/jsonhandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 85c22b43..42e6ee86 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -350,7 +350,7 @@ QVariant JsonHandler::unpack(const QMetaObject &metaObject, const QVariant &valu // If it's a list object, loop over count if (m_listMetaObjects.contains(typeName)) { if (value.type() != QVariant::List) { - qCWarning(dcJsonRpc()) << "Cannot unpack" << typeName << ". Value is not in list format:" << value; +// qCWarning(dcJsonRpc()) << "Cannot unpack" << typeName << ". Value is not in list format:" << value; return QVariant(); } From 25152c5e27802232dc5baec6e691d28d2dbc7bfc Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 5 Nov 2019 23:49:01 +0100 Subject: [PATCH 20/22] Add readonly feature to JSONRPC --- libnymea-core/jsonrpc/jsonvalidator.cpp | 40 +++++-- libnymea-core/jsonrpc/jsonvalidator.h | 5 +- libnymea/jsonrpc/jsonhandler.cpp | 39 ++++-- libnymea/time/repeatingoption.cpp | 40 ------- libnymea/time/repeatingoption.h | 24 ---- tests/auto/api.json | 150 ++++++++++++------------ 6 files changed, 136 insertions(+), 162 deletions(-) diff --git a/libnymea-core/jsonrpc/jsonvalidator.cpp b/libnymea-core/jsonrpc/jsonvalidator.cpp index b3691312..6cfe24a3 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.cpp +++ b/libnymea-core/jsonrpc/jsonvalidator.cpp @@ -75,7 +75,7 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &api) JsonValidator::Result JsonValidator::validateParams(const QVariantMap ¶ms, const QString &method, const QVariantMap &api) { QVariantMap paramDefinition = api.value("methods").toMap().value(method).toMap().value("params").toMap(); - m_result = validateMap(params, paramDefinition, api); + m_result = validateMap(params, paramDefinition, api, QIODevice::WriteOnly); m_result.setWhere(method + ", param " + m_result.where()); return m_result; } @@ -83,7 +83,7 @@ JsonValidator::Result JsonValidator::validateParams(const QVariantMap ¶ms, c JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api) { QVariantMap returnsDefinition = api.value("methods").toMap().value(method).toMap().value("returns").toMap(); - m_result = validateMap(returns, returnsDefinition, api); + m_result = validateMap(returns, returnsDefinition, api, QIODevice::ReadOnly); m_result.setWhere(method + ", returns " + m_result.where()); return m_result; } @@ -91,7 +91,7 @@ JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, JsonValidator::Result JsonValidator::validateNotificationParams(const QVariantMap ¶ms, const QString ¬ification, const QVariantMap &api) { QVariantMap paramDefinition = api.value("notifications").toMap().value(notification).toMap().value("params").toMap(); - m_result = validateMap(params, paramDefinition, api); + m_result = validateMap(params, paramDefinition, api, QIODevice::ReadOnly); m_result.setWhere(notification + ", param " + m_result.where()); return m_result; } @@ -101,14 +101,21 @@ JsonValidator::Result JsonValidator::result() const return m_result; } -JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api) +JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api, QIODevice::OpenMode openMode) { // Make sure all required values are available foreach (const QString &key, definition.keys()) { - if (key.startsWith("o:")) { + QRegExp isOptional = QRegExp("^([a-z]:)*o:.*"); + if (isOptional.exactMatch(key)) { continue; } - if (!map.contains(key)) { + QRegExp isReadOnly = QRegExp("^([a-z]:)*r:.*"); + if (isReadOnly.exactMatch(key) && openMode.testFlag(QIODevice::WriteOnly)) { + continue; + } + QString trimmedKey = key; + trimmedKey.remove(QRegExp("^(o:|r:)")); + if (!map.contains(trimmedKey)) { return Result(false, "Missing required key: " + key, key); } } @@ -117,6 +124,15 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q foreach (const QString &key, map.keys()) { // Is the key allowed in here? QVariant expectedValue = definition.value(key); + foreach (const QString &definitionKey, definition.keys()) { + QRegExp regExp = QRegExp("(o:|r:)*" + key); + if (regExp.exactMatch(definitionKey)) { + expectedValue = definition.value(definitionKey); + } + } + if (!expectedValue.isValid()) { + expectedValue = definition.value("o:" + key); + } if (!expectedValue.isValid()) { expectedValue = definition.value("o:" + key); } @@ -127,7 +143,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q // Validate content QVariant value = map.value(key); - Result result = validateEntry(value, expectedValue, api); + Result result = validateEntry(value, expectedValue, api, openMode); if (!result.success()) { result.setWhere(key + '.' + result.where()); result.setErrorString(result.errorString()); @@ -139,7 +155,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q return Result(true); } -JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api) +JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api, QIODevice::OpenMode openMode) { if (definition.type() == QVariant::String) { QString expectedTypeName = definition.toString(); @@ -168,7 +184,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const } QString flagEnum = refDefinition.toList().first().toString(); foreach (const QVariant &flagsEntry, value.toList()) { - Result result = validateEntry(flagsEntry, flagEnum, api); + Result result = validateEntry(flagsEntry, flagEnum, api, openMode); if (!result.success()) { return result; } @@ -178,7 +194,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariantMap types = api.value("types").toMap(); QVariant refDefinition = types.value(refName); - return validateEntry(value, refDefinition, api); + return validateEntry(value, refDefinition, api, openMode); } JsonHandler::BasicType expectedBasicType = JsonHandler::enumNameToValue(expectedTypeName); @@ -240,7 +256,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const if (value.type() != QVariant::Map) { return Result(false, "Invalid value. Expected a map bug received: " + value.toString()); } - return validateMap(value.toMap(), definition.toMap(), api); + return validateMap(value.toMap(), definition.toMap(), api, openMode); } if (definition.type() == QVariant::List) { @@ -250,7 +266,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const return Result(false, "Expected list of " + entryDefinition.toString() + " but got value of type " + value.typeName() + "\n" + QJsonDocument::fromVariant(value).toJson()); } foreach (const QVariant &entry, value.toList()) { - Result result = validateEntry(entry, entryDefinition, api); + Result result = validateEntry(entry, entryDefinition, api, openMode); if (!result.success()) { return result; } diff --git a/libnymea-core/jsonrpc/jsonvalidator.h b/libnymea-core/jsonrpc/jsonvalidator.h index 7b168fec..e59f41b4 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.h +++ b/libnymea-core/jsonrpc/jsonvalidator.h @@ -23,6 +23,7 @@ #include #include +#include namespace nymeaserver { @@ -58,8 +59,8 @@ public: Result result() const; private: - Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api); - Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api); + Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api, QIODevice::OpenMode openMode); + Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api, QIODevice::OpenMode openMode); Result m_result; }; diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 42e6ee86..3ea88515 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -173,6 +173,9 @@ void JsonHandler::registerObject(const QMetaObject &metaObject) if (metaProperty.isUser()) { name.prepend("o:"); } + if (!metaProperty.isWritable()) { + name.prepend("r:"); + } QVariant typeName; if (metaProperty.type() == QVariant::UserType) { if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { @@ -305,12 +308,22 @@ QVariant JsonHandler::pack(const QMetaObject &metaObject, const void *value) con continue; } - // Manually converting QList... Only QVariantList is known to the meta system - if (propertyTypeName.startsWith("QList")) { + // Manually converting QList... Only QVariantList is known to the meta system + if (propertyTypeName.startsWith("QList<")) { QVariantList list; - foreach (int entry, propertyValue.value>()) { - list << entry; + if (propertyTypeName == "QList") { + foreach (int entry, propertyValue.value>()) { + list << entry; + } + } else if (propertyTypeName == "QList") { + foreach (const QUuid &entry, propertyValue.value>()) { + list << entry; + } + } else { + Q_ASSERT_X(false, this->metaObject()->className(), QString("Unhandled list type: %1").arg(propertyTypeName).toUtf8()); + qCWarning(dcJsonRpc()) << "Cannot pack property of unhandled list type" << propertyTypeName; } + if (!list.isEmpty() || !metaProperty.isUser()) { ret.insert(metaProperty.name(), list); } @@ -410,12 +423,20 @@ QVariant JsonHandler::unpack(const QMetaObject &metaObject, const QVariant &valu continue; } - if (metaProperty.typeName() == QStringLiteral("QList")) { - QList intList; - foreach (const QVariant &val, variant.toList()) { - intList.append(val.toInt()); + if (QString(metaProperty.typeName()).startsWith("QList<")) { + if (metaProperty.typeName() == QStringLiteral("QList")) { + QList intList; + foreach (const QVariant &val, variant.toList()) { + intList.append(val.toInt()); + } + metaProperty.writeOnGadget(ptr, QVariant::fromValue(intList)); + } else if (metaProperty.typeName() == QStringLiteral("QList")) { + QList uuidList; + foreach (const QVariant &val, variant.toList()) { + uuidList.append(val.toUuid()); + } + metaProperty.writeOnGadget(ptr, QVariant::fromValue(uuidList)); } - metaProperty.writeOnGadget(ptr, QVariant::fromValue(intList)); continue; } diff --git a/libnymea/time/repeatingoption.cpp b/libnymea/time/repeatingoption.cpp index 159be676..6dea237f 100644 --- a/libnymea/time/repeatingoption.cpp +++ b/libnymea/time/repeatingoption.cpp @@ -210,43 +210,3 @@ QDebug operator<<(QDebug dbg, const RepeatingOption &repeatingOption) dbg.nospace() << "RepeatingOption(Mode:" << repeatingOption.mode() << ", Monthdays:" << repeatingOption.monthDays() << "Weekdays:" << repeatingOption.weekDays() << ")"; return dbg; } - -WeekDays::WeekDays() -{ - -} - -WeekDays::WeekDays(const QList &other): QList(other) -{ - -} - -QVariant WeekDays::get(int index) const -{ - return at(index); -} - -void WeekDays::put(const QVariant &value) -{ - append(value.toInt()); -} - -MonthDays::MonthDays() -{ - -} - -MonthDays::MonthDays(const QList &other): QList(other) -{ - -} - -QVariant MonthDays::get(int index) const -{ - return at(index); -} - -void MonthDays::put(const QVariant &value) -{ - append(value.toInt()); -} diff --git a/libnymea/time/repeatingoption.h b/libnymea/time/repeatingoption.h index 4015b5a7..071d1fcb 100644 --- a/libnymea/time/repeatingoption.h +++ b/libnymea/time/repeatingoption.h @@ -27,30 +27,6 @@ class QDateTime; -class WeekDays: public QList -{ - Q_GADGET - Q_PROPERTY(int count READ count) -public: - WeekDays(); - WeekDays(const QList &other); - Q_INVOKABLE QVariant get(int index) const; - Q_INVOKABLE void put(const QVariant &value); -}; -Q_DECLARE_METATYPE(WeekDays) - -class MonthDays: public QList -{ - Q_GADGET - Q_PROPERTY(int count READ count) -public: - MonthDays(); - MonthDays(const QList &other); - Q_INVOKABLE QVariant get(int index) const; - Q_INVOKABLE void put(const QVariant &value); -}; -Q_DECLARE_METATYPE(MonthDays) - class RepeatingOption { Q_GADGET diff --git a/tests/auto/api.json b/tests/auto/api.json index 95483d3c..f78a8b5a 100644 --- a/tests/auto/api.json +++ b/tests/auto/api.json @@ -1683,10 +1683,10 @@ }, "ActionType": { "displayName": "String", - "id": "Uuid", "index": "Int", "name": "String", - "paramTypes": "$ref:ParamTypes" + "paramTypes": "$ref:ParamTypes", + "r:id": "Uuid" }, "ActionTypes": [ "$ref:ActionType" @@ -1715,51 +1715,51 @@ "$ref:CalendarItem" ], "Device": { - "deviceClassId": "Uuid", - "id": "Uuid", "name": "String", "o:parentId": "Uuid", "params": "$ref:ParamList", + "r:deviceClassId": "Uuid", + "r:id": "Uuid", "settings": "$ref:ParamList", "setupComplete": "Bool", "states": "$ref:States" }, "DeviceClass": { - "actionTypes": "$ref:ActionTypes", - "browsable": "Bool", - "browserItemActionTypes": "$ref:ActionTypes", - "createMethods": "$ref:CreateMethods", - "discoveryParamTypes": "$ref:ParamTypes", - "displayName": "String", - "eventTypes": "$ref:EventTypes", - "id": "Uuid", - "interfaces": "StringList", - "name": "String", - "paramTypes": "$ref:ParamTypes", - "pluginId": "Uuid", - "settingsTypes": "$ref:ParamTypes", - "setupMethod": "$ref:SetupMethod", - "stateTypes": "$ref:StateTypes", - "vendorId": "Uuid" + "r:actionTypes": "$ref:ActionTypes", + "r:browsable": "Bool", + "r:browserItemActionTypes": "$ref:ActionTypes", + "r:createMethods": "$ref:CreateMethods", + "r:discoveryParamTypes": "$ref:ParamTypes", + "r:displayName": "String", + "r:eventTypes": "$ref:EventTypes", + "r:id": "Uuid", + "r:interfaces": "StringList", + "r:name": "String", + "r:paramTypes": "$ref:ParamTypes", + "r:pluginId": "Uuid", + "r:settingsTypes": "$ref:ParamTypes", + "r:setupMethod": "$ref:SetupMethod", + "r:stateTypes": "$ref:StateTypes", + "r:vendorId": "Uuid" }, "DeviceClasses": [ "$ref:DeviceClass" ], "DeviceDescriptor": { - "description": "String", - "deviceParams": "$ref:ParamList", - "id": "Uuid", - "o:deviceId": "Uuid", - "title": "String" + "r:description": "String", + "r:deviceParams": "$ref:ParamList", + "r:id": "Uuid", + "r:o:deviceId": "Uuid", + "r:title": "String" }, "DeviceDescriptors": [ "$ref:DeviceDescriptor" ], "DevicePlugin": { - "displayName": "String", - "id": "Uuid", - "name": "String", - "paramTypes": "$ref:ParamTypes" + "r:displayName": "String", + "r:id": "Uuid", + "r:name": "String", + "r:paramTypes": "$ref:ParamTypes" }, "DevicePlugins": [ "$ref:DevicePlugin" @@ -1768,9 +1768,9 @@ "$ref:Device" ], "Event": { - "deviceId": "Uuid", - "eventTypeId": "Uuid", - "params": "$ref:ParamList" + "r:deviceId": "Uuid", + "r:eventTypeId": "Uuid", + "r:params": "$ref:ParamList" }, "EventDescriptor": { "o:deviceId": "Uuid", @@ -1784,10 +1784,10 @@ ], "EventType": { "displayName": "String", - "id": "Uuid", - "index": "Int", "name": "String", - "paramTypes": "$ref:ParamTypes" + "paramTypes": "$ref:ParamTypes", + "r:id": "Uuid", + "r:index": "Int" }, "EventTypes": [ "$ref:EventType" @@ -1800,15 +1800,15 @@ "$ref:LogEntry" ], "LogEntry": { - "loggingLevel": "$ref:LoggingLevel", - "o:active": "Bool", - "o:deviceId": "Uuid", - "o:errorCode": "String", - "o:eventType": "$ref:LoggingEventType", - "o:typeId": "Uuid", - "o:value": "Variant", - "source": "$ref:LoggingSource", - "timestamp": "Uint" + "r:loggingLevel": "$ref:LoggingLevel", + "r:o:active": "Bool", + "r:o:deviceId": "Uuid", + "r:o:errorCode": "String", + "r:o:eventType": "$ref:LoggingEventType", + "r:o:typeId": "Uuid", + "r:o:value": "Variant", + "r:source": "$ref:LoggingSource", + "r:timestamp": "Uint" }, "MqttPolicy": { "allowedPublishTopicFilters": "StringList", @@ -1818,15 +1818,15 @@ "username": "String" }, "Package": { - "canRemove": "Bool", - "candidateVersion": "String", - "changelog": "String", - "displayName": "String", - "id": "String", - "installedVersion": "String", - "rollbackAvailable": "Bool", - "summary": "String", - "updateAvailable": "Bool" + "r:canRemove": "Bool", + "r:candidateVersion": "String", + "r:changelog": "String", + "r:displayName": "String", + "r:id": "String", + "r:installedVersion": "String", + "r:rollbackAvailable": "Bool", + "r:summary": "String", + "r:updateAvailable": "Bool" }, "Packages": [ "$ref:Package" @@ -1849,7 +1849,6 @@ ], "ParamType": { "displayName": "String", - "id": "Uuid", "index": "Int", "name": "String", "o:allowedValues": [ @@ -1861,6 +1860,7 @@ "o:minValue": "Variant", "o:readOnly": "Bool", "o:unit": "$ref:Unit", + "r:id": "Uuid", "type": "$ref:BasicType" }, "ParamTypes": [ @@ -1879,21 +1879,21 @@ "$ref:Repository" ], "Repository": { - "displayName": "String", "enabled": "Bool", - "id": "String" + "r:displayName": "String", + "r:id": "String" }, "Rule": { "actions": "$ref:RuleActions", "name": "String", - "o:active": "Bool", "o:enabled": "Bool", "o:eventDescriptors": "$ref:EventDescriptors", "o:executable": "Bool", "o:exitActions": "$ref:RuleActions", "o:id": "Uuid", "o:stateEvaluator": "$ref:StateEvaluator", - "o:timeDescriptor": "$ref:TimeDescriptor" + "o:timeDescriptor": "$ref:TimeDescriptor", + "r:o:active": "Bool" }, "RuleAction": { "o:actionTypeId": "Uuid", @@ -1936,8 +1936,8 @@ "sslEnabled": "Bool" }, "State": { - "stateTypeId": "Uuid", - "value": "Variant" + "r:stateTypeId": "Uuid", + "r:value": "Variant" }, "StateDescriptor": { "o:deviceId": "Uuid", @@ -1958,7 +1958,6 @@ "StateType": { "defaultValue": "Variant", "displayName": "String", - "id": "Uuid", "index": "Int", "name": "String", "o:maxValue": "Variant", @@ -1967,6 +1966,7 @@ "Variant" ], "o:unit": "$ref:Unit", + "r:id": "Uuid", "type": "$ref:BasicType" }, "StateTypes": [ @@ -1998,10 +1998,10 @@ "$ref:TimeEventItem" ], "TokenInfo": { - "creationTime": "Uint", - "deviveName": "String", - "id": "Uuid", - "username": "String" + "r:creationTime": "Uint", + "r:deviveName": "String", + "r:id": "Uuid", + "r:username": "String" }, "Vendor": { "displayName": "String", @@ -2020,18 +2020,18 @@ "sslEnabled": "Bool" }, "WiredNetworkDevice": { - "bitRate": "String", - "interface": "String", - "macAddress": "String", - "pluggedIn": "Bool", - "state": "$ref:NetworkDeviceState" + "r:bitRate": "String", + "r:interface": "String", + "r:macAddress": "String", + "r:pluggedIn": "Bool", + "r:state": "$ref:NetworkDeviceState" }, "WirelessAccessPoint": { - "frequency": "Double", - "macAddress": "String", - "protected": "Bool", - "signalStrength": "Int", - "ssid": "String" + "r:frequency": "Double", + "r:macAddress": "String", + "r:protected": "Bool", + "r:signalStrength": "Int", + "r:ssid": "String" }, "WirelessNetworkDevice": { "bitRate": "String", From ec15e664e17e50a1ab0797839f345d658c34f270 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 6 Nov 2019 13:38:22 +0100 Subject: [PATCH 21/22] cleanup warnings and allow setting "unknown" debug categories --- libnymea-core/jsonrpc/jsonvalidator.cpp | 2 -- libnymea-core/jsonrpc/ruleshandler.cpp | 1 - libnymea-core/nymeacore.cpp | 2 +- libnymea-core/nymeacore.h | 2 ++ libnymea-core/ruleengine/stateevaluator.cpp | 2 -- libnymea/time/calendaritem.cpp | 1 - server/main.cpp | 10 +++++----- tests/auto/rules/testrules.cpp | 1 - tests/auto/timemanager/testtimemanager.cpp | 3 --- 9 files changed, 8 insertions(+), 16 deletions(-) diff --git a/libnymea-core/jsonrpc/jsonvalidator.cpp b/libnymea-core/jsonrpc/jsonvalidator.cpp index 6cfe24a3..9846e834 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.cpp +++ b/libnymea-core/jsonrpc/jsonvalidator.cpp @@ -34,9 +34,7 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &api) QVariantMap enums = api.value("enums").toMap(); QVariantMap flags = api.value("flags").toMap(); QVariantMap types = api.value("types").toMap(); -// qWarning() << "checkrefs enums" << enums.keys(); foreach (const QString &key, map.keys()) { -// qWarning() << "checking prop" << key << types.keys(); if (map.value(key).toString().startsWith("$ref:")) { QString refName = map.value(key).toString().remove("$ref:"); if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) { diff --git a/libnymea-core/jsonrpc/ruleshandler.cpp b/libnymea-core/jsonrpc/ruleshandler.cpp index 12345a65..2141f198 100644 --- a/libnymea-core/jsonrpc/ruleshandler.cpp +++ b/libnymea-core/jsonrpc/ruleshandler.cpp @@ -253,7 +253,6 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap ¶ms) JsonReply* RulesHandler::AddRule(const QVariantMap ¶ms) { Rule rule = unpack(params); - qWarning() << "Unpacked rule" << rule; rule.setId(RuleId::createRuleId()); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->addRule(rule); diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index 7397cd74..44574b64 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -173,7 +173,7 @@ void NymeaCore::init() { m_cloudManager = new CloudManager(m_configuration, m_networkManager, this); qCDebug(dcApplication()) << "Loading experiences"; - new ExperienceManager(m_deviceManager, m_serverManager->jsonServer(), this); + m_experienceManager = new ExperienceManager(m_deviceManager, m_serverManager->jsonServer(), this); CloudNotifications *cloudNotifications = m_cloudManager->createNotificationsPlugin(); diff --git a/libnymea-core/nymeacore.h b/libnymea-core/nymeacore.h index 06c7c2f0..9a80434e 100644 --- a/libnymea-core/nymeacore.h +++ b/libnymea-core/nymeacore.h @@ -54,6 +54,7 @@ class TagsStorage; class UserManager; class Platform; class System; +class ExperienceManager; class NymeaCore : public QObject { @@ -134,6 +135,7 @@ private: NetworkManager *m_networkManager; UserManager *m_userManager; System *m_system; + ExperienceManager *m_experienceManager; QList m_executingRules; diff --git a/libnymea-core/ruleengine/stateevaluator.cpp b/libnymea-core/ruleengine/stateevaluator.cpp index 677c122d..8cb99110 100644 --- a/libnymea-core/ruleengine/stateevaluator.cpp +++ b/libnymea-core/ruleengine/stateevaluator.cpp @@ -389,8 +389,6 @@ StateEvaluators::StateEvaluators(const QList &other): QList()); } diff --git a/server/main.cpp b/server/main.cpp index ce69a08d..d9f1a39e 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -208,11 +208,11 @@ int main(int argc, char *argv[]) bool isWarning = debugArea.endsWith("Warnings"); debugArea.remove(QRegExp("^No")); debugArea.remove(QRegExp("Warnings$")); - if (loggingFilters.contains(debugArea) || loggingFiltersPlugins.contains(debugArea)) { - loggingRules.append(QString("%1.%2=%3").arg(debugArea).arg(isWarning ? "warning" : "debug").arg(enable ? "true": "false")); - } else { - qCWarning(dcApplication) << QCoreApplication::translate("nymea", "No such debug category:") << debugArea; - } + loggingRules.append(QString("%1.%2=%3").arg(debugArea).arg(isWarning ? "warning" : "debug").arg(enable ? "true": "false")); +// if (loggingFilters.contains(debugArea) || loggingFiltersPlugins.contains(debugArea)) { +// } else { +// qCWarning(dcApplication) << QCoreApplication::translate("nymea", "No such debug category:") << debugArea; +// } } // Finally set the rules for the logging diff --git a/tests/auto/rules/testrules.cpp b/tests/auto/rules/testrules.cpp index 82fb41b8..113664c9 100644 --- a/tests/auto/rules/testrules.cpp +++ b/tests/auto/rules/testrules.cpp @@ -3010,7 +3010,6 @@ void TestRules::testLoopingRules() addRuleParams.insert("eventDescriptors", QVariantList() << offEvent); addRuleParams.insert("actions", QVariantList() << onAction); QVariant response = injectAndWait("Rules.AddRule", addRuleParams); - qWarning() << response; verifyRuleError(response); // Add rule 1 diff --git a/tests/auto/timemanager/testtimemanager.cpp b/tests/auto/timemanager/testtimemanager.cpp index a3585600..e15336f4 100644 --- a/tests/auto/timemanager/testtimemanager.cpp +++ b/tests/auto/timemanager/testtimemanager.cpp @@ -259,8 +259,6 @@ void TestTimeManager::loadSaveTimeDescriptor() .arg(QString(QJsonDocument::fromVariant(timeDescriptorMapLoaded).toJson())) .toUtf8()); -// qWarning() << "+++" << QString(QJsonDocument::fromVariant(timeDescriptorMap).toJson()); -// qWarning() << "---" << QString(QJsonDocument::fromVariant(timeDescriptorMapLoaded).toJson()); // REMOVE rule QVariantMap removeParams; removeParams.insert("ruleId", ruleId); @@ -2087,7 +2085,6 @@ void TestTimeManager::verifyRuleNotExecuted() QCOMPARE(spy.count(), 1); QByteArray actionHistory = reply->readAll(); - qWarning() << "actionHistory" << actionHistory; QVERIFY2(actionHistory.isEmpty(), "Actfdsfadsion is triggered while it should not have been."); reply->deleteLater(); } From 2b63b59261113865688c1677181a4fba58ac9bef Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sat, 30 Nov 2019 23:58:26 +0100 Subject: [PATCH 22/22] drop whitespace --- libnymea-core/experiences/experiencemanager.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libnymea-core/experiences/experiencemanager.h b/libnymea-core/experiences/experiencemanager.h index fe3db4d4..d5b7a373 100644 --- a/libnymea-core/experiences/experiencemanager.h +++ b/libnymea-core/experiences/experiencemanager.h @@ -29,7 +29,6 @@ class DeviceManager; namespace nymeaserver { - class ExperienceManager : public QObject { Q_OBJECT