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) {