Drop JsonTypes class by distributing logic to json handlers

This is required in order to be able to be more flexible in registering
new types/methods.
This commit is contained in:
Michael Zanetti 2019-10-20 00:34:21 +02:00
parent 3451fdf407
commit 5e3bc2acbd
53 changed files with 3444 additions and 4317 deletions

View File

@ -33,6 +33,7 @@
*/ */
#include "actionhandler.h" #include "actionhandler.h"
#include "devicehandler.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "devices/devicemanager.h" #include "devices/devicemanager.h"
@ -48,41 +49,45 @@ namespace nymeaserver {
ActionHandler::ActionHandler(QObject *parent) : ActionHandler::ActionHandler(QObject *parent) :
JsonHandler(parent) JsonHandler(parent)
{ {
QVariantMap params; // Objects
QVariantMap returns; 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<Device::DeviceError>());
returns.insert("o:displayMessage", enumValueName(String));
registerMethod("ExecuteAction", description, params, returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ExecuteAction", "Execute a single action."); description = "Get the ActionType for the given ActionTypeId";
setParams("ExecuteAction", JsonTypes::actionDescription()); params.insert("actionTypeId", enumValueName(Uuid));
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", enumRef<Device::DeviceError>());
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("o:actionType", objectRef("ActionType"));
setReturns("ExecuteAction", returns); registerMethod("GetActionType", description, params, returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetActionType", "Get the ActionType for the given ActionTypeId"); description = "Execute the item identified by itemId on the given device.";
params.insert("actionTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("deviceId", enumValueName(Uuid));
setParams("GetActionType", params); params.insert("itemId", enumValueName(String));
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", enumRef<Device::DeviceError>());
returns.insert("o:actionType", JsonTypes::actionTypeDescription()); registerMethod("ExecuteBrowserItem", description, params, returns);
setReturns("GetActionType", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ExecuteBrowserItem", "Execute the item identified by itemId on the given device."); description = "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("deviceId", enumValueName(Uuid));
params.insert("itemId", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("itemId", enumValueName(String));
setParams("ExecuteBrowserItem", params); params.insert("actionTypeId", enumValueName(Uuid));
returns.insert("deviceError", JsonTypes::deviceErrorRef()); params.insert("o:params", QVariantList() << objectRef("Param"));
setReturns("ExecuteBrowserItem", returns); returns.insert("deviceError", enumRef<Device::DeviceError>());
registerMethod("ExecuteBrowserItemAction", description, params, 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);
} }
@ -96,7 +101,7 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap &params)
{ {
DeviceId deviceId(params.value("deviceId").toString()); DeviceId deviceId(params.value("deviceId").toString());
ActionTypeId actionTypeId(params.value("actionTypeId").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(); QLocale locale = params.value("locale").toLocale();
Action action(actionTypeId, deviceId); Action action(actionTypeId, deviceId);
@ -105,8 +110,9 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap &params)
JsonReply *jsonReply = createAsyncReply("ExecuteAction"); JsonReply *jsonReply = createAsyncReply("ExecuteAction");
DeviceActionInfo *info = NymeaCore::instance()->executeAction(action); DeviceActionInfo *info = NymeaCore::instance()->executeAction(action);
connect(info, &DeviceActionInfo::finished, jsonReply, [this, info, jsonReply, locale](){ connect(info, &DeviceActionInfo::finished, jsonReply, [info, jsonReply, locale](){
QVariantMap data = statusToReply(info->status()); QVariantMap data;
data.insert("deviceError", enumValueName(info->status()));
if (!info->displayMessage().isEmpty()) { if (!info->displayMessage().isEmpty()) {
data.insert("displayMessage", info->translatedDisplayMessage(locale)); data.insert("displayMessage", info->translatedDisplayMessage(locale));
} }
@ -124,13 +130,16 @@ JsonReply *ActionHandler::GetActionType(const QVariantMap &params) const
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) {
foreach (const ActionType &actionType, deviceClass.actionTypes()) { foreach (const ActionType &actionType, deviceClass.actionTypes()) {
if (actionType.id() == actionTypeId) { if (actionType.id() == actionTypeId) {
QVariantMap data = statusToReply(Device::DeviceErrorNoError); QVariantMap data;
data.insert("actionType", JsonTypes::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorNoError));
data.insert("actionType", DeviceHandler::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale()));
return createReply(data); return createReply(data);
} }
} }
} }
return createReply(statusToReply(Device::DeviceErrorActionTypeNotFound)); QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorActionTypeNotFound));
return createReply(data);
} }
JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap &params) JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap &params)
@ -142,8 +151,10 @@ JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap &params)
JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItem"); JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItem");
BrowserActionInfo *info = NymeaCore::instance()->executeBrowserItem(action); BrowserActionInfo *info = NymeaCore::instance()->executeBrowserItem(action);
connect(info, &BrowserActionInfo::finished, jsonReply, [this, info, jsonReply](){ connect(info, &BrowserActionInfo::finished, jsonReply, [info, jsonReply](){
jsonReply->setData(statusToReply(info->status())); QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(info->status()));
jsonReply->setData(data);
jsonReply->finished(); jsonReply->finished();
}); });
@ -155,14 +166,16 @@ JsonReply *ActionHandler::ExecuteBrowserItemAction(const QVariantMap &params)
DeviceId deviceId = DeviceId(params.value("deviceId").toString()); DeviceId deviceId = DeviceId(params.value("deviceId").toString());
QString itemId = params.value("itemId").toString(); QString itemId = params.value("itemId").toString();
ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").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); BrowserItemAction browserItemAction(deviceId, itemId, actionTypeId, paramList);
JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItemAction"); JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItemAction");
BrowserItemActionInfo *info = NymeaCore::instance()->executeBrowserItemAction(browserItemAction); BrowserItemActionInfo *info = NymeaCore::instance()->executeBrowserItemAction(browserItemAction);
connect(info, &BrowserItemActionInfo::finished, jsonReply, [this, info, jsonReply](){ connect(info, &BrowserItemActionInfo::finished, jsonReply, [info, jsonReply](){
jsonReply->setData(statusToReply(info->status())); QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(info->status()));
jsonReply->setData(data);
jsonReply->finished(); jsonReply->finished();
}); });

View File

@ -22,7 +22,7 @@
#ifndef ACTIONHANDLER_H #ifndef ACTIONHANDLER_H
#define ACTIONHANDLER_H #define ACTIONHANDLER_H
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "devices/devicemanager.h" #include "devices/devicemanager.h"
namespace nymeaserver { namespace nymeaserver {

View File

@ -60,6 +60,7 @@
#include "configurationhandler.h" #include "configurationhandler.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "nymeaconfiguration.h"
namespace nymeaserver { namespace nymeaserver {
@ -67,229 +68,233 @@ namespace nymeaserver {
ConfigurationHandler::ConfigurationHandler(QObject *parent): ConfigurationHandler::ConfigurationHandler(QObject *parent):
JsonHandler(parent) JsonHandler(parent)
{ {
// Enums
registerEnum<NymeaConfiguration::ConfigurationError>();
// 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 // Methods
QVariantMap params; QVariantMap returns; QString description; QVariantMap params; QVariantMap returns;
setDescription("GetTimeZones", "Get the list of available timezones."); description = "Get the list of available timezones.";
setParams("GetTimeZones", params); returns.insert("timeZones", QVariantList() << enumValueName(String));
returns.insert("timeZones", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); registerMethod("GetTimeZones", description, params, returns);
setReturns("GetTimeZones", returns);
params.clear(); returns.clear(); 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"); 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";
setParams("GetAvailableLanguages", params); returns.insert("languages", QVariantList() << enumValueName(String));
returns.insert("languages", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); registerMethod("GetAvailableLanguages", description, params, returns);
setReturns("GetAvailableLanguages", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetConfigurations", "Get all configuration parameters of the server."); description = "Get all configuration parameters of the server.";
setParams("GetConfigurations", params);
QVariantMap basicConfiguration; QVariantMap basicConfiguration;
basicConfiguration.insert("serverName", JsonTypes::basicTypeToString(JsonTypes::String)); basicConfiguration.insert("serverName", enumValueName(String));
basicConfiguration.insert("serverUuid", JsonTypes::basicTypeToString(JsonTypes::Uuid)); basicConfiguration.insert("serverUuid", enumValueName(Uuid));
basicConfiguration.insert("serverTime", JsonTypes::basicTypeToString(JsonTypes::Uint)); basicConfiguration.insert("serverTime", enumValueName(Uint));
basicConfiguration.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String)); basicConfiguration.insert("timeZone", enumValueName(String));
basicConfiguration.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); basicConfiguration.insert("language", enumValueName(String));
basicConfiguration.insert("debugServerEnabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); basicConfiguration.insert("debugServerEnabled", enumValueName(Bool));
returns.insert("basicConfiguration", basicConfiguration); returns.insert("basicConfiguration", basicConfiguration);
QVariantList tcpServerConfigurations; QVariantList tcpServerConfigurations;
tcpServerConfigurations.append(JsonTypes::serverConfigurationRef()); tcpServerConfigurations.append(objectRef("ServerConfiguration"));
returns.insert("tcpServerConfigurations", tcpServerConfigurations); returns.insert("tcpServerConfigurations", tcpServerConfigurations);
QVariantList webServerConfigurations; QVariantList webServerConfigurations;
webServerConfigurations.append(JsonTypes::webServerConfigurationRef()); webServerConfigurations.append(objectRef("WebServerConfiguration"));
returns.insert("webServerConfigurations", webServerConfigurations); returns.insert("webServerConfigurations", webServerConfigurations);
QVariantList webSocketServerConfigurations; QVariantList webSocketServerConfigurations;
webSocketServerConfigurations.append(JsonTypes::serverConfigurationRef()); webSocketServerConfigurations.append(objectRef("ServerConfiguration"));
returns.insert("webSocketServerConfigurations", webSocketServerConfigurations); returns.insert("webSocketServerConfigurations", webSocketServerConfigurations);
QVariantList mqttServerConfigurations; QVariantList mqttServerConfigurations;
mqttServerConfigurations.append(JsonTypes::serverConfigurationRef()); mqttServerConfigurations.append(objectRef("ServerConfiguration"));
QVariantMap cloudConfiguration; QVariantMap cloudConfiguration;
cloudConfiguration.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); cloudConfiguration.insert("enabled", enumValueName(Bool));
returns.insert("cloud", cloudConfiguration); returns.insert("cloud", cloudConfiguration);
setReturns("GetConfigurations", returns); registerMethod("GetConfigurations", description, params, returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetServerName", "Set the name of the server. Default is nymea."); description = "Set the name of the server. Default is nymea.";
params.insert("serverName", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("serverName", enumValueName(String));
setParams("SetServerName", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetServerName", description, params, returns);
setReturns("SetServerName", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetTimeZone", "Set the time zone of the server. See also: \"GetTimeZones\""); description = "Set the time zone of the server. See also: \"GetTimeZones\"";
params.insert("timeZone", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("timeZone", enumValueName(String));
setParams("SetTimeZone", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetTimeZone", description, params, returns);
setReturns("SetTimeZone", returns);
params.clear(); returns.clear(); 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\""); 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", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("language", enumValueName(String));
setParams("SetLanguage", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetLanguage", description, params, returns);
setReturns("SetLanguage", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetDebugServerEnabled", "Enable or disable the debug server."); description = "Enable or disable the debug server.";
params.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("enabled", enumValueName(String));
setParams("SetDebugServerEnabled", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetDebugServerEnabled", description, params, returns);
setReturns("SetDebugServerEnabled", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::serverConfigurationRef()); params.insert("configuration", objectRef("ServerConfiguration"));
setParams("SetTcpServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetTcpServerConfiguration", description, params, returns);
setReturns("SetTcpServerConfiguration", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("DeleteTcpServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("DeleteTcpServerConfiguration", description, params, returns);
setReturns("DeleteTcpServerConfiguration", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::serverConfigurationRef()); params.insert("configuration", objectRef("ServerConfiguration"));
setParams("SetWebSocketServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetWebSocketServerConfiguration", description, params, returns);
setReturns("SetWebSocketServerConfiguration", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("DeleteWebSocketServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("DeleteWebSocketServerConfiguration", description, params, returns);
setReturns("DeleteWebSocketServerConfiguration", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::webServerConfigurationRef()); params.insert("configuration", objectRef("WebServerConfiguration"));
setParams("SetWebServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetWebServerConfiguration", description, params, returns);
setReturns("SetWebServerConfiguration", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("DeleteWebServerConfiguration", "Delete a WebServer interface of the server."); description = "Delete a WebServer interface of the server.";
params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("DeleteWebServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("DeleteWebServerConfiguration", description, params, returns);
setReturns("DeleteWebServerConfiguration", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetCloudEnabled", "Sets whether the cloud connection is enabled or disabled in the settings."); description = "Sets whether the cloud connection is enabled or disabled in the settings.";
params.insert("enabled", JsonTypes::basicTypeToString(QVariant::Bool)); params.insert("enabled", enumValueName(Bool));
setParams("SetCloudEnabled", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetCloudEnabled", description, params, returns);
setReturns("SetCloudEnabled", returns);
// MQTT // MQTT
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetMqttServerConfigurations", "Get all MQTT Server configurations."); description = "Get all MQTT Server configurations.";
setParams("GetMqttServerConfigurations", params); returns.insert("mqttServerConfigurations", QVariantList() << objectRef("ServerConfiguration"));
returns.insert("mqttServerConfigurations", QVariantList() << JsonTypes::serverConfigurationRef()); registerMethod("GetMqttServerConfigurations", description, params, returns);
setReturns("GetMqttServerConfigurations", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::serverConfigurationRef()); params.insert("configuration", objectRef("ServerConfiguration"));
setParams("SetMqttServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetMqttServerConfiguration", description, params, returns);
setReturns("SetMqttServerConfiguration", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("DeleteMqttServerConfiguration", "Delete a MQTT Server interface of the server."); description = "Delete a MQTT Server interface of the server.";
params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("DeleteMqttServerConfiguration", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("DeleteMqttServerConfiguration", description, params, returns);
setReturns("DeleteMqttServerConfiguration", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetMqttPolicies", "Get all MQTT broker policies."); description = "Get all MQTT broker policies.";
setParams("GetMqttPolicies", params); returns.insert("mqttPolicies", QVariantList() << objectRef("MqttPolicy"));
returns.insert("mqttPolicies", QVariantList() << JsonTypes::mqttPolicyRef()); registerMethod("GetMqttPolicies", description, params, returns);
setReturns("GetMqttPolicies", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::mqttPolicyRef()); params.insert("policy", objectRef("MqttPolicy"));
setParams("SetMqttPolicy", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("SetMqttPolicy", description, params, returns);
setReturns("SetMqttPolicy", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("DeleteMqttPolicy", "Delete a MQTT policy from the broker."); description = "Delete a MQTT policy from the broker.";
params.insert("clientId", JsonTypes::basicTypeToString(QVariant::String)); params.insert("clientId", enumValueName(String));
setParams("DeleteMqttPolicy", params); returns.insert("configurationError", enumRef<NymeaConfiguration::ConfigurationError>());
returns.insert("configurationError", JsonTypes::configurationErrorRef()); registerMethod("DeleteMqttPolicy", description, params, returns);
setReturns("DeleteMqttPolicy", returns);
// Notifications // Notifications
params.clear(); returns.clear(); 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); params.insert("basicConfiguration", basicConfiguration);
setParams("BasicConfigurationChanged", params); registerNotification("BasicConfigurationChanged", description, params);
params.clear(); returns.clear(); 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."); 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", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("language", enumValueName(String));
setParams("LanguageChanged", params); registerNotification("LanguageChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("TcpServerConfigurationChanged", "Emitted whenever the TCP server configuration changes."); description = "Emitted whenever the TCP server configuration changes.";
params.insert("tcpServerConfiguration", JsonTypes::serverConfigurationRef()); params.insert("tcpServerConfiguration", objectRef("ServerConfiguration"));
setParams("TcpServerConfigurationChanged", params); registerNotification("TcpServerConfigurationChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("TcpServerConfigurationRemoved", "Emitted whenever a TCP server configuration is removed."); description = "Emitted whenever a TCP server configuration is removed.";
params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("TcpServerConfigurationRemoved", params); registerNotification("TcpServerConfigurationRemoved", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WebSocketServerConfigurationChanged", "Emitted whenever the web socket server configuration changes."); description = "Emitted whenever the web socket server configuration changes.";
params.insert("webSocketServerConfiguration", JsonTypes::serverConfigurationRef()); params.insert("webSocketServerConfiguration", objectRef("ServerConfiguration"));
setParams("WebSocketServerConfigurationChanged", params); registerNotification("WebSocketServerConfigurationChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WebSocketServerConfigurationRemoved", "Emitted whenever a WebSocket server configuration is removed."); description = "Emitted whenever a WebSocket server configuration is removed.";
params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("WebSocketServerConfigurationRemoved", params); registerNotification("WebSocketServerConfigurationRemoved", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("MqttServerConfigurationChanged", "Emitted whenever the MQTT broker configuration is changed."); description = "Emitted whenever the MQTT broker configuration is changed.";
params.insert("mqttServerConfiguration", JsonTypes::serverConfigurationRef()); params.insert("mqttServerConfiguration", objectRef("ServerConfiguration"));
setParams("MqttServerConfigurationChanged", params); registerNotification("MqttServerConfigurationChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("MqttServerConfigurationRemoved", "Emitted whenever a MQTT server configuration is removed."); description = "Emitted whenever a MQTT server configuration is removed.";
params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("MqttServerConfigurationRemoved", params); registerNotification("MqttServerConfigurationRemoved", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WebServerConfigurationChanged", "Emitted whenever the web server configuration changes."); description = "Emitted whenever the web server configuration changes.";
params.insert("webServerConfiguration", JsonTypes::webServerConfigurationRef()); params.insert("webServerConfiguration", objectRef("WebServerConfiguration"));
setParams("WebServerConfigurationChanged", params); registerNotification("WebServerConfigurationChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WebServerConfigurationRemoved", "Emitted whenever a Web server configuration is removed."); description = "Emitted whenever a Web server configuration is removed.";
params.insert("id", JsonTypes::basicTypeToString(QVariant::String)); params.insert("id", enumValueName(String));
setParams("WebServerConfigurationRemoved", params); registerNotification("WebServerConfigurationRemoved", description, params);
params.clear(); returns.clear(); 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); params.insert("cloudConfiguration", cloudConfiguration);
setParams("CloudConfigurationChanged", params); registerNotification("CloudConfigurationChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("MqttPolicyChanged", "Emitted whenever a MQTT broker policy is changed."); description = "Emitted whenever a MQTT broker policy is changed.";
params.insert("policy", JsonTypes::mqttPolicyRef()); params.insert("policy", objectRef("MqttPolicy"));
setParams("MqttPolicyChanged", params); registerNotification("MqttPolicyChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("MqttPolicyRemoved", "Emitted whenever a MQTT broker policy is removed."); description = "Emitted whenever a MQTT broker policy is removed.";
params.insert("clientId", JsonTypes::basicTypeToString(QVariant::String)); params.insert("clientId", enumValueName(String));
setParams("MqttPolicyRemoved", params); registerNotification("MqttPolicyRemoved", description, params);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::serverNameChanged, this, &ConfigurationHandler::onBasicConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::serverNameChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::timeZoneChanged, this, &ConfigurationHandler::onBasicConfigurationChanged); connect(NymeaCore::instance()->configuration(), &NymeaConfiguration::timeZoneChanged, this, &ConfigurationHandler::onBasicConfigurationChanged);
@ -319,23 +324,23 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap &params) co
{ {
Q_UNUSED(params) Q_UNUSED(params)
QVariantMap returns; QVariantMap returns;
returns.insert("basicConfiguration", JsonTypes::packBasicConfiguration()); returns.insert("basicConfiguration", packBasicConfiguration());
QVariantList tcpServerConfigs; QVariantList tcpServerConfigs;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) { foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) {
tcpServerConfigs.append(JsonTypes::packServerConfiguration(config)); tcpServerConfigs.append(packServerConfiguration(config));
} }
returns.insert("tcpServerConfigurations", tcpServerConfigs); returns.insert("tcpServerConfigurations", tcpServerConfigs);
QVariantList webServerConfigs; QVariantList webServerConfigs;
foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) {
webServerConfigs.append(JsonTypes::packWebServerConfiguration(config)); webServerConfigs.append(packWebServerConfiguration(config));
} }
returns.insert("webServerConfigurations", webServerConfigs); returns.insert("webServerConfigurations", webServerConfigs);
QVariantList webSocketServerConfigs; QVariantList webSocketServerConfigs;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) { foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) {
webSocketServerConfigs.append(JsonTypes::packServerConfiguration(config)); webSocketServerConfigs.append(packServerConfiguration(config));
} }
returns.insert("webSocketServerConfigurations", webSocketServerConfigs); returns.insert("webSocketServerConfigurations", webSocketServerConfigs);
@ -402,7 +407,7 @@ JsonReply *ConfigurationHandler::SetLanguage(const QVariantMap &params) const
JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetTcpServerConfiguration(const QVariantMap &params) const
{ {
ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap()); ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap());
if (config.id.isEmpty()) { if (config.id.isEmpty()) {
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId));
} }
@ -432,7 +437,7 @@ JsonReply *ConfigurationHandler::DeleteTcpServerConfiguration(const QVariantMap
JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetWebServerConfiguration(const QVariantMap &params) const
{ {
WebServerConfiguration config = JsonTypes::unpackWebServerConfiguration(params.value("configuration").toMap()); WebServerConfiguration config = unpackWebServerConfiguration(params.value("configuration").toMap());
if (config.id.isEmpty()) { if (config.id.isEmpty()) {
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId));
@ -463,7 +468,7 @@ JsonReply *ConfigurationHandler::DeleteWebServerConfiguration(const QVariantMap
JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetWebSocketServerConfiguration(const QVariantMap &params) const
{ {
ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap()); ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap());
if (config.id.isEmpty()) { if (config.id.isEmpty()) {
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId));
} }
@ -498,7 +503,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap &
QVariantMap ret; QVariantMap ret;
QVariantList mqttServerConfigs; QVariantList mqttServerConfigs;
foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->mqttServerConfigurations()) { foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->mqttServerConfigurations()) {
mqttServerConfigs << JsonTypes::packServerConfiguration(config); mqttServerConfigs << packServerConfiguration(config);
} }
ret.insert("mqttServerConfigurations", mqttServerConfigs); ret.insert("mqttServerConfigurations", mqttServerConfigs);
return createReply(ret); return createReply(ret);
@ -506,7 +511,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap &
JsonReply *ConfigurationHandler::SetMqttServerConfiguration(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetMqttServerConfiguration(const QVariantMap &params) const
{ {
ServerConfiguration config = JsonTypes::unpackServerConfiguration(params.value("configuration").toMap()); ServerConfiguration config = unpackServerConfiguration(params.value("configuration").toMap());
if (config.id.isEmpty()) { if (config.id.isEmpty()) {
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorInvalidId));
} }
@ -540,7 +545,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap &params) cons
Q_UNUSED(params) Q_UNUSED(params)
QVariantList mqttPolicies; QVariantList mqttPolicies;
foreach (const MqttPolicy &policy, NymeaCore::instance()->configuration()->mqttPolicies()) { foreach (const MqttPolicy &policy, NymeaCore::instance()->configuration()->mqttPolicies()) {
mqttPolicies << JsonTypes::packMqttPolicy(policy); mqttPolicies << packMqttPolicy(policy);
} }
QVariantMap ret; QVariantMap ret;
ret.insert("mqttPolicies", mqttPolicies); ret.insert("mqttPolicies", mqttPolicies);
@ -549,7 +554,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap &params) cons
JsonReply *ConfigurationHandler::SetMqttPolicy(const QVariantMap &params) const JsonReply *ConfigurationHandler::SetMqttPolicy(const QVariantMap &params) const
{ {
MqttPolicy policy = JsonTypes::unpackMqttPolicy(params.value("policy").toMap()); MqttPolicy policy = unpackMqttPolicy(params.value("policy").toMap());
NymeaCore::instance()->configuration()->updateMqttPolicy(policy); NymeaCore::instance()->configuration()->updateMqttPolicy(policy);
return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError)); return createReply(statusToReply(NymeaConfiguration::ConfigurationErrorNoError));
} }
@ -579,7 +584,7 @@ void ConfigurationHandler::onBasicConfigurationChanged()
{ {
qCDebug(dcJsonRpc()) << "Notification: Basic configuration changed"; qCDebug(dcJsonRpc()) << "Notification: Basic configuration changed";
QVariantMap params; QVariantMap params;
params.insert("basicConfiguration", JsonTypes::packBasicConfiguration()); params.insert("basicConfiguration", packBasicConfiguration());
emit BasicConfigurationChanged(params); emit BasicConfigurationChanged(params);
} }
@ -587,7 +592,7 @@ void ConfigurationHandler::onTcpServerConfigurationChanged(const QString &id)
{ {
qCDebug(dcJsonRpc()) << "Notification: TCP server configuration changed"; qCDebug(dcJsonRpc()) << "Notification: TCP server configuration changed";
QVariantMap params; 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); emit TcpServerConfigurationChanged(params);
} }
@ -603,7 +608,7 @@ void ConfigurationHandler::onWebServerConfigurationChanged(const QString &id)
{ {
qCDebug(dcJsonRpc()) << "Notification: web server configuration changed"; qCDebug(dcJsonRpc()) << "Notification: web server configuration changed";
QVariantMap params; 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); emit WebServerConfigurationChanged(params);
} }
@ -619,7 +624,7 @@ void ConfigurationHandler::onWebSocketServerConfigurationChanged(const QString &
{ {
qCDebug(dcJsonRpc()) << "Notification: web socket server configuration changed"; qCDebug(dcJsonRpc()) << "Notification: web socket server configuration changed";
QVariantMap params; 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); emit WebSocketServerConfigurationChanged(params);
} }
@ -635,7 +640,7 @@ void ConfigurationHandler::onMqttServerConfigurationChanged(const QString &id)
{ {
qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed"; qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed";
QVariantMap params; 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); emit MqttServerConfigurationChanged(params);
} }
@ -651,7 +656,7 @@ void ConfigurationHandler::onMqttPolicyChanged(const QString &clientId)
{ {
qCDebug(dcJsonRpc()) << "Notification: MQTT policy changed"; qCDebug(dcJsonRpc()) << "Notification: MQTT policy changed";
QVariantMap params; 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); emit MqttPolicyChanged(params);
} }
@ -663,6 +668,89 @@ void ConfigurationHandler::onMqttPolicyRemoved(const QString &clientId)
emit MqttPolicyRemoved(params); 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<NymeaConfiguration::ConfigurationError>(status));
return returns;
}
void ConfigurationHandler::onCloudConfigurationChanged(bool enabled) void ConfigurationHandler::onCloudConfigurationChanged(bool enabled)
{ {
qCDebug(dcJsonRpc()) << "Notification: cloud configuration changed"; qCDebug(dcJsonRpc()) << "Notification: cloud configuration changed";

View File

@ -23,7 +23,8 @@
#include <QObject> #include <QObject>
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "nymeaconfiguration.h"
namespace nymeaserver { namespace nymeaserver {
@ -88,6 +89,19 @@ private slots:
void onMqttServerConfigurationRemoved(const QString &id); void onMqttServerConfigurationRemoved(const QString &id);
void onMqttPolicyChanged(const QString &clientId); void onMqttPolicyChanged(const QString &clientId);
void onMqttPolicyRemoved(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;
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@ -22,7 +22,7 @@
#ifndef DEVICEHANDLER_H #ifndef DEVICEHANDLER_H
#define DEVICEHANDLER_H #define DEVICEHANDLER_H
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "devices/devicemanager.h" #include "devices/devicemanager.h"
namespace nymeaserver { namespace nymeaserver {
@ -60,6 +60,28 @@ public:
Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap &params) const; Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap &params) const; Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap &params) const;
static QVariantMap packParamType(const ParamType &paramType, 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 &param);
static QVariantList packParams(const ParamList &paramList);
static QVariantMap packDevice(Device *device);
static QVariantList packDeviceStates(Device *device);
static QVariantMap packBrowserItem(const BrowserItem &item);
static Param unpackParam(const QVariantMap &param);
static ParamList unpackParams(const QVariantList &params);
signals: signals:
void PluginConfigurationChanged(const QVariantMap &params); void PluginConfigurationChanged(const QVariantMap &params);
void StateChanged(const QVariantMap &params); void StateChanged(const QVariantMap &params);
@ -80,6 +102,9 @@ private slots:
void deviceChangedNotification(Device *device); void deviceChangedNotification(Device *device);
void deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId &paramTypeId, const QVariant &value); void deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId &paramTypeId, const QVariant &value);
private:
QVariantMap statusToReply(Device::DeviceError status) const;
}; };
} }

View File

@ -38,6 +38,7 @@
*/ */
#include "eventhandler.h" #include "eventhandler.h"
#include "devicehandler.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "loggingcategories.h" #include "loggingcategories.h"
@ -47,23 +48,26 @@ namespace nymeaserver {
EventHandler::EventHandler(QObject *parent) : EventHandler::EventHandler(QObject *parent) :
JsonHandler(parent) JsonHandler(parent)
{ {
QVariantMap params; // Objects
QVariantMap returns; 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<Device::DeviceError>());
returns.insert("o:eventType", objectRef("EventType"));
registerMethod("GetEventType", description, params, returns);
// Notifications // Notifications
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("EventTriggered", "Emitted whenever an Event is triggered."); description = "Emitted whenever an Event is triggered.";
params.insert("event", JsonTypes::eventRef()); params.insert("event", objectRef("Event"));
setParams("EventTriggered", params); registerNotification("EventTriggered", description, 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);
connect(NymeaCore::instance(), &NymeaCore::eventTriggered, this, &EventHandler::eventTriggered); connect(NymeaCore::instance(), &NymeaCore::eventTriggered, this, &EventHandler::eventTriggered);
} }
@ -76,7 +80,17 @@ QString EventHandler::name() const
void EventHandler::eventTriggered(const Event &event) void EventHandler::eventTriggered(const Event &event)
{ {
QVariantMap params; 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 &param, event.params()) {
eventParams.append(DeviceHandler::packParam(param));
}
variant.insert("params", eventParams);
params.insert("event", variant);
emit EventTriggered(params); emit EventTriggered(params);
} }
@ -87,13 +101,16 @@ JsonReply* EventHandler::GetEventType(const QVariantMap &params) const
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) {
foreach (const EventType &eventType, deviceClass.eventTypes()) { foreach (const EventType &eventType, deviceClass.eventTypes()) {
if (eventType.id() == eventTypeId) { if (eventType.id() == eventTypeId) {
QVariantMap data = statusToReply(Device::DeviceErrorNoError); QVariantMap data;
data.insert("eventType", JsonTypes::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorNoError));
data.insert("eventType", DeviceHandler::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale()));
return createReply(data); return createReply(data);
} }
} }
} }
return createReply(statusToReply(Device::DeviceErrorEventTypeNotFound)); QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorEventTypeNotFound));
return createReply(data);
} }
} }

View File

@ -22,7 +22,9 @@
#ifndef EVENTHANDLER_H #ifndef EVENTHANDLER_H
#define EVENTHANDLER_H #define EVENTHANDLER_H
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "types/event.h"
namespace nymeaserver { namespace nymeaserver {
@ -30,7 +32,7 @@ class EventHandler : public JsonHandler
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit EventHandler(QObject *parent = 0); explicit EventHandler(QObject *parent = nullptr);
QString name() const override; QString name() const override;
Q_INVOKABLE JsonReply *GetEventType(const QVariantMap &params) const; Q_INVOKABLE JsonReply *GetEventType(const QVariantMap &params) const;

View File

@ -1,354 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\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 &params);
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 <QMetaMethod>
#include <QDebug>
#include <QRegExp>
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<bool, QString> JsonHandler::validateParams(const QString &methodName, const QVariantMap &params)
{
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<bool, QString> 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 &params)
{
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<JsonHandler*>(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<JsonHandler*>(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;
}
}

View File

@ -1,126 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef JSONHANDLER_H
#define JSONHANDLER_H
#include "jsontypes.h"
#include <QObject>
#include <QVariantMap>
#include <QMetaMethod>
#include <QTimer>
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<bool, QString> validateParams(const QString &methodName, const QVariantMap &params);
QPair<bool, QString> validateReturns(const QString &methodName, const QVariantMap &returns);
signals:
void asyncReply(int id, const QVariantMap &params);
protected:
void setDescription(const QString &methodName, const QString &description);
void setParams(const QString &methodName, const QVariantMap &params);
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<QString, QString> m_descriptions;
QHash<QString, QVariantMap> m_params;
QHash<QString, QVariantMap> m_returns;
};
}
#endif // JSONHANDLER_H

View File

@ -37,8 +37,8 @@
#include "jsonrpcserver.h" #include "jsonrpcserver.h"
#include "jsontypes.h" #include "jsonrpc/jsonhandler.h"
#include "jsonhandler.h" #include "jsonvalidator.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "devices/devicemanager.h" #include "devices/devicemanager.h"
#include "devices/deviceplugin.h" #include "devices/deviceplugin.h"
@ -72,12 +72,24 @@ JsonRPCServer::JsonRPCServer(const QSslConfiguration &sslConfiguration, QObject
m_notificationId(0) m_notificationId(0)
{ {
Q_UNUSED(sslConfiguration) Q_UNUSED(sslConfiguration)
// First, define our own JSONRPC methods // First, define our own JSONRPC API
QVariantMap returns;
QVariantMap params;
params.clear(); returns.clear(); // Enums
setDescription("Hello", "Initiates a connection. Use this method to perform an initial handshake of the " registerEnum<BasicType>();
registerEnum<UserManager::UserError>();
registerEnum<CloudManager::CloudConnectionState>();
// 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 " "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 " "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 " "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" "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 " "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, " "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."); "like initialSetupRequired might change if the setup has been performed in the meantime.";
params.insert("o:locale", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("o:locale", enumValueName(String));
setParams("Hello", params); returns.insert("server", enumValueName(String));
returns.insert("server", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("name", enumValueName(String));
returns.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("version", enumValueName(String));
returns.insert("version", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("uuid", enumValueName(Uuid));
returns.insert("uuid", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("language", enumValueName(String));
returns.insert("language", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("locale", enumValueName(String));
returns.insert("locale", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("protocol version", enumValueName(String));
returns.insert("protocol version", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("initialSetupRequired", enumValueName(Bool));
returns.insert("initialSetupRequired", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("authenticationRequired", enumValueName(Bool));
returns.insert("authenticationRequired", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("pushButtonAuthAvailable", enumValueName(Bool));
returns.insert("pushButtonAuthAvailable", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("Hello", description, params, returns);
setReturns("Hello", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("Introspect", "Introspect this API."); description = "Introspect this API.";
setParams("Introspect", params); returns.insert("methods", enumValueName(Object));
returns.insert("methods", JsonTypes::basicTypeToString(JsonTypes::Object)); returns.insert("notifications", enumValueName(Object));
returns.insert("notifications", JsonTypes::basicTypeToString(JsonTypes::Object)); returns.insert("types", enumValueName(Object));
returns.insert("types", JsonTypes::basicTypeToString(JsonTypes::Object)); registerMethod("Introspect", description, params, returns);
setReturns("Introspect", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("Version", "Version of this nymea/JSONRPC interface."); description = "Version of this nymea/JSONRPC interface.";
setParams("Version", params); returns.insert("version", enumValueName(String));
returns.insert("version", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("protocol version", enumValueName(String));
returns.insert("protocol version", JsonTypes::basicTypeToString(JsonTypes::String)); registerMethod("Version", description, params, returns);
setReturns("Version", returns);
params.clear(); returns.clear(); 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 " "\"namespaces\" needs to be given but not both of them. The boolean based "
"\"enabled\" parameter will enable/disable all notifications at once. If " "\"enabled\" parameter will enable/disable all notifications at once. If "
"instead the list-based \"namespaces\" parameter is provided, all given namespaces" "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 " "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 " "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 " "deprecated and used for legacy compatibilty only. It will be set to true if at least "
"one namespace has been enabled."); "one namespace has been enabled.";
params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("o:namespaces", enumValueName(StringList));
params.insert("o:namespaces", QVariantList() << QStringLiteral("$ref:Namespace")); params.insert("o:enabled", enumValueName(Bool));
setParams("SetNotificationStatus", params); returns.insert("namespaces", enumValueName(StringList));
returns.insert("namespaces", QVariantList() << QStringLiteral("$ref:Namespace")); returns.insert("enabled", enumValueName(Bool));
returns.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("SetNotificationStatus", description, params, returns);
setReturns("SetNotificationStatus", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("username", enumValueName(String));
params.insert("password", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("password", enumValueName(String));
setParams("CreateUser", params); returns.insert("error", enumRef<UserManager::UserError>());
returns.insert("error", JsonTypes::userErrorRef()); registerMethod("CreateUser", description, params, returns);
setReturns("CreateUser", returns);
params.clear(); returns.clear(); 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 " "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 " "the device is lost or stolen. This will return a new token to be used to authorize a "
"client at the API."); "client at the API.";
params.insert("username", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("username", enumValueName(String));
params.insert("password", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("password", enumValueName(String));
params.insert("deviceName", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("deviceName", enumValueName(String));
setParams("Authenticate", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("o:token", enumValueName(String));
returns.insert("o:token", JsonTypes::basicTypeToString(JsonTypes::String)); registerMethod("Authenticate", description, params, returns);
setReturns("Authenticate", returns);
params.clear(); returns.clear(); 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 " "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, " "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 " "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 " "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 " "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 " "active user should press the button or b) it might indicate an attacker trying to take "
"over and snooping in for tokens."); "over and snooping in for tokens.";
params.insert("deviceName", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("deviceName", enumValueName(String));
setParams("RequestPushButtonAuth", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("transactionId", enumValueName(Int));
returns.insert("transactionId", JsonTypes::basicTypeToString(JsonTypes::Int)); registerMethod("RequestPushButtonAuth", description, params, returns);
setReturns("RequestPushButtonAuth", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("Tokens", "Return a list of TokenInfo objects of all the tokens for the current user."); description = "Return a list of TokenInfo objects of all the tokens for the current user.";
setParams("Tokens", params); returns.insert("tokenInfoList", QVariantList() << objectRef("TokenInfo"));
returns.insert("tokenInfoList", QVariantList() << JsonTypes::tokenInfoRef()); registerMethod("Tokens", description, params, returns);
setReturns("Tokens", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RemoveToken", "Revoke access for a given token."); description = "Revoke access for a given token.";
params.insert("tokenId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("tokenId", enumValueName(Uuid));
setParams("RemoveToken", params); returns.insert("error", enumRef<UserManager::UserError>());
returns.insert("error", JsonTypes::userErrorRef()); registerMethod("RemoveToken", description, params, returns);
setReturns("RemoveToken", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetupCloudConnection", "Sets up the cloud connection by deploying a certificate and its configuration."); description = "Sets up the cloud connection by deploying a certificate and its configuration.";
params.insert("rootCA", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("rootCA", enumValueName(String));
params.insert("certificatePEM", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("certificatePEM", enumValueName(String));
params.insert("publicKey", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("publicKey", enumValueName(String));
params.insert("privateKey", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("privateKey", enumValueName(String));
params.insert("endpoint", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("endpoint", enumValueName(String));
setParams("SetupCloudConnection", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("SetupCloudConnection", description, params, returns);
setReturns("SetupCloudConnection", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("SetupRemoteAccess", "Setup the remote connection by providing AWS token information. This requires the cloud to be connected."); description = "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("idToken", enumValueName(String));
params.insert("userId", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("userId", enumValueName(String));
setParams("SetupRemoteAccess", params); returns.insert("status", enumValueName(Int));
returns.insert("status", JsonTypes::basicTypeToString(JsonTypes::Int)); returns.insert("message", enumValueName(String));
returns.insert("message", JsonTypes::basicTypeToString(JsonTypes::String)); registerMethod("SetupRemoteAccess", description, params, returns);
setReturns("SetupRemoteAccess", returns);
params.clear(); returns.clear(); 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."); 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.";
setParams("IsCloudConnected", params); returns.insert("connected", enumValueName(Bool));
returns.insert("connected", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("connectionState", enumRef<CloudManager::CloudConnectionState>());
returns.insert("connectionState", JsonTypes::cloudConnectionStateRef()); registerMethod("IsCloudConnected", description, params, returns);
setReturns("IsCloudConnected", returns);
params.clear(); returns.clear(); 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."); 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", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("sessionId", enumValueName(String));
setParams("KeepAlive", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("sessionId", enumValueName(String));
returns.insert("sessionId", JsonTypes::basicTypeToString(JsonTypes::String)); registerMethod("KeepAlive", description, params, returns);
setReturns("KeepAlive", returns);
// Notifications // Notifications
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("CloudConnectedChanged", "Emitted whenever the cloud connection status changes."); description = "Emitted whenever the cloud connection status changes.";
params.insert("connected", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("connected", enumValueName(Bool));
params.insert("connectionState", JsonTypes::cloudConnectionStateRef()); params.insert("connectionState", enumRef<CloudManager::CloudConnectionState>());
setParams("CloudConnectedChanged", params); registerNotification("CloudConnectedChanged", description, params);
params.clear(); 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. "); 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", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("success", enumValueName(Bool));
params.insert("transactionId", JsonTypes::basicTypeToString(JsonTypes::Int)); params.insert("transactionId", enumValueName(Int));
params.insert("o:token", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("o:token", enumValueName(String));
setParams("PushButtonAuthFinished", params); registerNotification("PushButtonAuthFinished", description, params);
QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "setup", Qt::QueuedConnection);
@ -247,7 +246,6 @@ QString JsonRPCServer::name() const
JsonReply *JsonRPCServer::Hello(const QVariantMap &params) JsonReply *JsonRPCServer::Hello(const QVariantMap &params)
{ {
Q_UNUSED(params);
TransportInterface *interface = reinterpret_cast<TransportInterface*>(property("transportInterface").toLongLong()); TransportInterface *interface = reinterpret_cast<TransportInterface*>(property("transportInterface").toLongLong());
qCDebug(dcJsonRpc()) << params; qCDebug(dcJsonRpc()) << params;
@ -269,32 +267,7 @@ JsonReply *JsonRPCServer::Hello(const QVariantMap &params)
JsonReply* JsonRPCServer::Introspect(const QVariantMap &params) const JsonReply* JsonRPCServer::Introspect(const QVariantMap &params) const
{ {
Q_UNUSED(params) Q_UNUSED(params)
return createReply(m_api);
// 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);
} }
JsonReply* JsonRPCServer::Version(const QVariantMap &params) const JsonReply* JsonRPCServer::Version(const QVariantMap &params) const
@ -342,7 +315,7 @@ JsonReply *JsonRPCServer::CreateUser(const QVariantMap &params)
UserManager::UserError status = NymeaCore::instance()->userManager()->createUser(username, password); UserManager::UserError status = NymeaCore::instance()->userManager()->createUser(username, password);
QVariantMap returns; QVariantMap returns;
returns.insert("error", JsonTypes::userErrorToString(status)); returns.insert("error", enumValueName<UserManager::UserError>(status));
return createReply(returns); return createReply(returns);
} }
@ -389,7 +362,7 @@ JsonReply *JsonRPCServer::Tokens(const QVariantMap &params) const
QList<TokenInfo> tokens = NymeaCore::instance()->userManager()->tokens(username); QList<TokenInfo> tokens = NymeaCore::instance()->userManager()->tokens(username);
QVariantList retList; QVariantList retList;
foreach (const TokenInfo &tokenInfo, tokens) { foreach (const TokenInfo &tokenInfo, tokens) {
retList << JsonTypes::packTokenInfo(tokenInfo); retList << packTokenInfo(tokenInfo);
} }
QVariantMap retMap; QVariantMap retMap;
retMap.insert("tokenInfoList", retList); retMap.insert("tokenInfoList", retList);
@ -401,7 +374,7 @@ JsonReply *JsonRPCServer::RemoveToken(const QVariantMap &params)
QUuid tokenId = params.value("tokenId").toUuid(); QUuid tokenId = params.value("tokenId").toUuid();
UserManager::UserError error = NymeaCore::instance()->userManager()->removeToken(tokenId); UserManager::UserError error = NymeaCore::instance()->userManager()->removeToken(tokenId);
QVariantMap ret; QVariantMap ret;
ret.insert("error", JsonTypes::userErrorToString(error)); ret.insert("error", enumValueName<UserManager::UserError>(error));
return createReply(ret); return createReply(ret);
} }
@ -443,7 +416,7 @@ JsonReply *JsonRPCServer::IsCloudConnected(const QVariantMap &params)
bool connected = NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected; bool connected = NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected;
QVariantMap data; QVariantMap data;
data.insert("connected", connected); data.insert("connected", connected);
data.insert("connectionState", JsonTypes::cloudConnectionStateToString(NymeaCore::instance()->cloudManager()->connectionState())); data.insert("connectionState", enumValueName<CloudManager::CloudConnectionState>(NymeaCore::instance()->cloudManager()->connectionState()));
return createReply(data); return createReply(data);
} }
@ -646,19 +619,25 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid
JsonHandler *handler = m_handlers.value(targetNamespace); JsonHandler *handler = m_handlers.value(targetNamespace);
if (!handler) { if (!handler) {
qCWarning(dcJsonRpc()) << "JSON RPC method called for invalid namespace:" << targetNamespace;
sendErrorResponse(interface, clientId, commandId, "No such namespace"); sendErrorResponse(interface, clientId, commandId, "No such namespace");
return; 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"); sendErrorResponse(interface, clientId, commandId, "No such method");
return; return;
} }
QVariantMap params = message.value("params").toMap(); QVariantMap params = message.value("params").toMap();
QPair<bool, QString> validationResult = handler->validateParams(method, params); QVariantMap definition = handler->jsonMethods().value(method).toMap().value("params").toMap();
if (!validationResult.first) { JsonValidator validator;
sendErrorResponse(interface, clientId, commandId, "Invalid params: " + validationResult.second); 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; return;
} }
@ -694,21 +673,23 @@ void JsonRPCServer::processJsonPacket(TransportInterface *interface, const QUuid
connect(reply, &JsonReply::finished, this, &JsonRPCServer::asyncReplyFinished); connect(reply, &JsonReply::finished, this, &JsonRPCServer::asyncReplyFinished);
reply->startWait(); reply->startWait();
} else { } else {
Q_ASSERT_X((targetNamespace == "JSONRPC" && method == "Introspect") || handler->validateReturns(method, reply->data()).first JsonValidator validator;
,"validating return value", formatAssertion(targetNamespace, method, QMetaMethod::Method, handler, reply->data()).toLatin1().data()); 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()); sendResponse(interface, clientId, commandId, reply->data());
reply->deleteLater(); 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)); QVariantMap ret;
QJsonDocument doc2 = QJsonDocument::fromVariant(data); ret.insert("id", tokenInfo.id().toString());
return QString("\nMethod: %1\nTemplate: %2\nValue: %3") ret.insert("userName", tokenInfo.username());
.arg(targetNamespace + "." + method) ret.insert("deviceName", tokenInfo.deviceName());
.arg(QString(doc.toJson(QJsonDocument::Indented))) ret.insert("creationTime", tokenInfo.creationTime().toTime_t());
.arg(QString(doc2.toJson(QJsonDocument::Indented))); return ret;
} }
void JsonRPCServer::sendNotification(const QVariantMap &params) void JsonRPCServer::sendNotification(const QVariantMap &params)
@ -721,7 +702,10 @@ void JsonRPCServer::sendNotification(const QVariantMap &params)
notification.insert("notification", handler->name() + "." + method.name()); notification.insert("notification", handler->name() + "." + method.name());
notification.insert("params", params); 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); QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact);
qCDebug(dcJsonRpc()) << "Sending notification:" << handler->name() + "." + method.name(); qCDebug(dcJsonRpc()) << "Sending notification:" << handler->name() + "." + method.name();
qCDebug(dcJsonRpcTraffic()) << "Notification content:" << data; qCDebug(dcJsonRpcTraffic()) << "Notification content:" << data;
@ -743,8 +727,10 @@ void JsonRPCServer::asyncReplyFinished()
return; return;
} }
if (!reply->timedOut()) { if (!reply->timedOut()) {
Q_ASSERT_X(reply->handler()->validateReturns(reply->method(), reply->data()).first JsonValidator validator;
,"validating return value", formatAssertion(reply->handler()->name(), reply->method(), QMetaMethod::Method, reply->handler(), reply->data()).toLatin1().data()); 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()); sendResponse(interface, reply->clientId(), reply->commandId(), reply->data());
} else { } else {
qCWarning(dcJsonRpc()) << "RPC call timed out:" << reply->handler()->name() << ":" << reply->method(); qCWarning(dcJsonRpc()) << "RPC call timed out:" << reply->handler()->name() << ":" << reply->method();
@ -771,7 +757,7 @@ void JsonRPCServer::onCloudConnectionStateChanged()
{ {
QVariantMap params; QVariantMap params;
params.insert("connected", NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected); params.insert("connected", NymeaCore::instance()->cloudManager()->connectionState() == CloudManager::CloudConnectionStateConnected);
params.insert("connectionState", JsonTypes::cloudConnectionStateToString(NymeaCore::instance()->cloudManager()->connectionState())); params.insert("connectionState", enumValueName<CloudManager::CloudConnectionState>(NymeaCore::instance()->cloudManager()->connectionState()));
emit CloudConnectedChanged(params); emit CloudConnectedChanged(params);
} }
@ -806,6 +792,79 @@ void JsonRPCServer::onPushButtonAuthFinished(int transactionId, bool success, co
void JsonRPCServer::registerHandler(JsonHandler *handler) 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 &notificationName, 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); m_handlers.insert(handler->name(), handler);
for (int i = 0; i < handler->metaObject()->methodCount(); ++i) { for (int i = 0; i < handler->metaObject()->methodCount(); ++i) {
QMetaMethod method = handler->metaObject()->method(i); QMetaMethod method = handler->metaObject()->method(i);

View File

@ -22,7 +22,7 @@
#ifndef JSONRPCSERVER_H #ifndef JSONRPCSERVER_H
#define JSONRPCSERVER_H #define JSONRPCSERVER_H
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "transportinterface.h" #include "transportinterface.h"
#include "usermanager/usermanager.h" #include "usermanager/usermanager.h"
@ -81,6 +81,9 @@ private:
void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data); void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data);
static QVariantMap packTokenInfo(const TokenInfo &tokenInfo);
private slots: private slots:
void setup(); void setup();
@ -98,6 +101,7 @@ private slots:
void onPushButtonAuthFinished(int transactionId, bool success, const QByteArray &token); void onPushButtonAuthFinished(int transactionId, bool success, const QByteArray &token);
private: private:
QVariantMap m_api;
QMap<TransportInterface*, bool> m_interfaces; // Interface, authenticationRequired QMap<TransportInterface*, bool> m_interfaces; // Interface, authenticationRequired
QHash<QString, JsonHandler *> m_handlers; QHash<QString, JsonHandler *> m_handlers;
QHash<JsonReply *, TransportInterface *> m_asyncReplies; QHash<JsonReply *, TransportInterface *> m_asyncReplies;
@ -114,6 +118,7 @@ private:
int m_notificationId; int m_notificationId;
void registerHandler(JsonHandler *handler); void registerHandler(JsonHandler *handler);
QString formatAssertion(const QString &targetNamespace, const QString &method, QMetaMethod::MethodType methodType, JsonHandler *handler, const QVariantMap &data) const; QString formatAssertion(const QString &targetNamespace, const QString &method, QMetaMethod::MethodType methodType, JsonHandler *handler, const QVariantMap &data) const;
}; };

File diff suppressed because it is too large Load Diff

View File

@ -1,292 +0,0 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2015 Simon Stürz <simon.stuerz@guh.io> *
* Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> *
* Copyright (C) 2017 Michael Zanetti <michael.zanetti@guh.io> *
* *
* 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 <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#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 <QObject>
#include <QVariantMap>
#include <QString>
#include <QMetaEnum>
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<className::enumName>(); \
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 &param);
static QVariantMap packBrowserItem(const BrowserItem &item);
static QVariantMap packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packParamDescriptor(const ParamDescriptor &paramDescriptor);
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 &paramList);
static QVariantList packBrowserItems(const BrowserItems &items);
static QVariantList packRules(const QList<Rule> 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<DeviceDescriptor> 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<Rule> &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 &paramMap);
static ParamList unpackParams(const QVariantList &paramList);
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 &paramDescriptorMap);
static QList<ParamDescriptor> unpackParamDescriptors(const QVariantList &paramDescriptorList);
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<bool, QString> validateMap(const QVariantMap &templateMap, const QVariantMap &map);
static QPair<bool, QString> validateProperty(const QVariant &templateValue, const QVariant &value);
static QPair<bool, QString> validateList(const QVariantList &templateList, const QVariantList &list);
static QPair<bool, QString> validateVariant(const QVariant &templateVariant, const QVariant &variant);
static QPair<bool, QString> validateEnum(const QVariantList &enumList, const QVariant &value);
static QPair<bool, QString> validateBasicType(const QVariant &variant);
private:
static bool s_initialized;
static void init();
static QPair<bool, QString> report(bool status, const QString &message);
static QVariantList enumToStrings(const QMetaObject &metaObject, const QString &enumName);
static QString s_lastError;
};
}
#endif // JSONTYPES_H

View File

@ -0,0 +1,223 @@
#include "jsonvalidator.h"
#include "jsonrpc/jsonhandler.h"
#include "loggingcategories.h"
#include <QJsonDocument>
#include <QColor>
#include <QDateTime>
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 &params, 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 &params, const QString &notification, 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<JsonHandler::BasicType>(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<QColor>();
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);
}
}

View File

@ -0,0 +1,49 @@
#ifndef JSONVALIDATOR_H
#define JSONVALIDATOR_H
#include <QPair>
#include <QVariant>
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 &params, const QString &method, const QVariantMap &api);
Result validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api);
Result validateNotificationParams(const QVariantMap &params, const QString &notification, 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

View File

@ -45,6 +45,7 @@
#include "logginghandler.h" #include "logginghandler.h"
#include "logging/logengine.h" #include "logging/logengine.h"
#include "logging/logfilter.h" #include "logging/logfilter.h"
#include "logging/logvaluetool.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "nymeacore.h" #include "nymeacore.h"
@ -54,12 +55,29 @@ namespace nymeaserver {
LoggingHandler::LoggingHandler(QObject *parent) : LoggingHandler::LoggingHandler(QObject *parent) :
JsonHandler(parent) JsonHandler(parent)
{ {
QVariantMap params; // Enums
QVariantMap returns; registerEnum<Logging::LoggingSource>();
registerEnum<Logging::LoggingLevel>();
registerEnum<Logging::LoggingEventType>();
registerEnum<Logging::LoggingError>();
QVariantMap timeFilter; // Objects
params.clear(); returns.clear(); QVariantMap logEntry;
setDescription("GetLogEntries", "Get the LogEntries matching the given filter. " logEntry.insert("timestamp", enumValueName(Int));
logEntry.insert("loggingLevel", enumRef<Logging::LoggingLevel>());
logEntry.insert("source", enumRef<Logging::LoggingSource>());
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<Logging::LoggingEventType>());
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. " "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 " "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 " "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" "1) offset 0, maxCount 1000: Entries 0 to 9999\n"
"2) offset 10000, maxCount 1000: Entries 10000 - 19999\n" "2) offset 10000, maxCount 1000: Entries 10000 - 19999\n"
"3) offset 20000, maxCount 1000: Entries 20000 - 29999\n" "3) offset 20000, maxCount 1000: Entries 20000 - 29999\n"
"..."); "...";
timeFilter.insert("o:startDate", JsonTypes::basicTypeToString(JsonTypes::Int)); QVariantMap timeFilter;
timeFilter.insert("o:endDate", JsonTypes::basicTypeToString(JsonTypes::Int)); timeFilter.insert("o:startDate", enumValueName(Int));
timeFilter.insert("o:endDate", enumValueName(Int));
params.insert("o:timeFilters", QVariantList() << timeFilter); params.insert("o:timeFilters", QVariantList() << timeFilter);
params.insert("o:loggingSources", QVariantList() << JsonTypes::loggingSourceRef()); params.insert("o:loggingSources", QVariantList() << enumRef<Logging::LoggingSource>());
params.insert("o:loggingLevels", QVariantList() << JsonTypes::loggingLevelRef()); params.insert("o:loggingLevels", QVariantList() << enumRef<Logging::LoggingLevel>());
params.insert("o:eventTypes", QVariantList() << JsonTypes::loggingEventTypeRef()); params.insert("o:eventTypes", QVariantList() << enumRef<Logging::LoggingEventType>());
params.insert("o:typeIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("o:typeIds", QVariantList() << enumValueName(Uuid));
params.insert("o:deviceIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("o:deviceIds", QVariantList() << enumValueName(Uuid));
params.insert("o:values", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Variant)); params.insert("o:values", QVariantList() << enumValueName(Variant));
params.insert("o:limit", JsonTypes::basicTypeToString(JsonTypes::Int)); params.insert("o:limit", enumValueName(Int));
params.insert("o:offset", JsonTypes::basicTypeToString(JsonTypes::Int)); params.insert("o:offset", enumValueName(Int));
setParams("GetLogEntries", params); returns.insert("loggingError", enumRef<Logging::LoggingError>());
returns.insert("loggingError", JsonTypes::loggingErrorRef()); returns.insert("o:logEntries", QVariantList() << objectRef("LogEntry"));
returns.insert("o:logEntries", QVariantList() << JsonTypes::logEntryRef()); returns.insert("count", enumValueName(Int));
returns.insert("count", JsonTypes::basicTypeToString(JsonTypes::Int)); returns.insert("offset", enumValueName(Int));
returns.insert("offset", JsonTypes::basicTypeToString(JsonTypes::Int)); registerMethod("GetLogEntries", description, params, returns);
setReturns("GetLogEntries", returns);
// Notifications // Notifications
params.clear(); params.clear();
setDescription("LogEntryAdded", "Emitted whenever an entry is appended to the logging system. "); description = "Emitted whenever an entry is appended to the logging system. ";
params.insert("logEntry", JsonTypes::logEntryRef()); params.insert("logEntry", objectRef("LogEntry"));
setParams("LogEntryAdded", params); registerNotification("LogEntryAdded", description, params);
params.clear(); 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 " "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 " "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 " "be removed, or when the oldest entry of the database was deleted to "
"keep to database in the size limits."); "keep to database in the size limits.";
setParams("LogDatabaseUpdated", params); registerNotification("LogDatabaseUpdated", description, params);
connect(NymeaCore::instance()->logEngine(), &LogEngine::logEntryAdded, this, &LoggingHandler::logEntryAdded); connect(NymeaCore::instance()->logEngine(), &LogEngine::logEntryAdded, this, &LoggingHandler::logEntryAdded);
connect(NymeaCore::instance()->logEngine(), &LogEngine::logDatabaseUpdated, this, &LoggingHandler::logDatabaseUpdated); connect(NymeaCore::instance()->logEngine(), &LogEngine::logDatabaseUpdated, this, &LoggingHandler::logDatabaseUpdated);
@ -119,7 +137,7 @@ QString LoggingHandler::name() const
void LoggingHandler::logEntryAdded(const LogEntry &logEntry) void LoggingHandler::logEntryAdded(const LogEntry &logEntry)
{ {
QVariantMap params; QVariantMap params;
params.insert("logEntry", JsonTypes::packLogEntry(logEntry)); params.insert("logEntry", packLogEntry(logEntry));
emit LogEntryAdded(params); emit LogEntryAdded(params);
} }
@ -130,18 +148,136 @@ void LoggingHandler::logDatabaseUpdated()
JsonReply* LoggingHandler::GetLogEntries(const QVariantMap &params) const JsonReply* LoggingHandler::GetLogEntries(const QVariantMap &params) const
{ {
LogFilter filter = JsonTypes::unpackLogFilter(params); LogFilter filter = unpackLogFilter(params);
QVariantList entries; QVariantList entries;
foreach (const LogEntry &entry, NymeaCore::instance()->logEngine()->logEntries(filter)) { 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::LoggingError>(Logging::LoggingErrorNoError));
returns.insert("logEntries", entries); returns.insert("logEntries", entries);
returns.insert("offset", filter.offset()); returns.insert("offset", filter.offset());
returns.insert("count", entries.count()); returns.insert("count", entries.count());
return createReply(returns); return createReply(returns);
} }
QVariantMap LoggingHandler::packLogEntry(const LogEntry &logEntry)
{
QVariantMap logEntryMap;
logEntryMap.insert("timestamp", logEntry.timestamp().toMSecsSinceEpoch());
logEntryMap.insert("loggingLevel", enumValueName<Logging::LoggingLevel>(logEntry.level()));
logEntryMap.insert("source", enumValueName<Logging::LoggingSource>(logEntry.source()));
logEntryMap.insert("eventType", enumValueName<Logging::LoggingEventType>(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<RuleEngine::RuleError>(static_cast<RuleEngine::RuleError>(logEntry.errorCode())));
break;
case Logging::LoggingSourceActions:
case Logging::LoggingSourceEvents:
case Logging::LoggingSourceStates:
case Logging::LoggingSourceBrowserActions:
logEntryMap.insert("errorCode", enumValueName<Device::DeviceError>(static_cast<Device::DeviceError>(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<Logging::LoggingSource>(source.toString()));
}
}
if (logFilterMap.contains("loggingLevels")) {
QVariantList loggingLevels = logFilterMap.value("loggingLevels").toList();
foreach (const QVariant &level, loggingLevels) {
filter.addLoggingLevel(enumNameToValue<Logging::LoggingLevel>(level.toString()));
}
}
if (logFilterMap.contains("eventTypes")) {
QVariantList eventTypes = logFilterMap.value("eventTypes").toList();
foreach (const QVariant &eventType, eventTypes) {
filter.addLoggingEventType(enumNameToValue<Logging::LoggingEventType>(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;
}
} }

View File

@ -22,8 +22,9 @@
#ifndef LOGGINGHANDLER_H #ifndef LOGGINGHANDLER_H
#define LOGGINGHANDLER_H #define LOGGINGHANDLER_H
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "logging/logentry.h" #include "logging/logentry.h"
#include "logging/logfilter.h"
namespace nymeaserver { namespace nymeaserver {
@ -40,6 +41,11 @@ signals:
void LogEntryAdded(const QVariantMap &params); void LogEntryAdded(const QVariantMap &params);
void LogDatabaseUpdated(const QVariantMap &params); void LogDatabaseUpdated(const QVariantMap &params);
private:
static QVariantMap packLogEntry(const LogEntry &logEntry);
static LogFilter unpackLogFilter(const QVariantMap &logFilterMap);
private slots: private slots:
void logEntryAdded(const LogEntry &entry); void logEntryAdded(const LogEntry &entry);
void logDatabaseUpdated(); void logDatabaseUpdated();

View File

@ -68,7 +68,6 @@
#include "nymeacore.h" #include "nymeacore.h"
#include "jsontypes.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "networkmanagerhandler.h" #include "networkmanagerhandler.h"
#include "networkmanager/networkmanager.h" #include "networkmanager/networkmanager.h"
@ -80,107 +79,128 @@ namespace nymeaserver {
NetworkManagerHandler::NetworkManagerHandler(QObject *parent) : NetworkManagerHandler::NetworkManagerHandler(QObject *parent) :
JsonHandler(parent) JsonHandler(parent)
{ {
QVariantMap params; QVariantMap returns; // Enums
registerEnum<NetworkManager::NetworkManagerError>();
registerEnum<NetworkManager::NetworkManagerState>();
registerEnum<NetworkDevice::NetworkDeviceState>();
params.clear(); returns.clear(); // Objects
setDescription("GetNetworkStatus", "Get the current network manager status."); QVariantMap wirelessAccessPoint;
setParams("GetNetworkStatus", params); 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<NetworkDevice::NetworkDeviceState>());
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<NetworkDevice::NetworkDeviceState>());
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; QVariantMap status;
status.insert("networkingEnabled", JsonTypes::basicTypeToString(QVariant::Bool)); status.insert("networkingEnabled", enumValueName(Bool));
status.insert("wirelessNetworkingEnabled", JsonTypes::basicTypeToString(QVariant::Bool)); status.insert("wirelessNetworkingEnabled", enumValueName(Bool));
status.insert("state", JsonTypes::networkManagerStateRef()); status.insert("state", enumRef<NetworkManager::NetworkManagerState>());
returns.insert("o:status", status); returns.insert("o:status", status);
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
setReturns("GetNetworkStatus", returns); registerMethod("GetNetworkStatus", description, params, returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("EnableNetworking", "Enable or disable networking in the NetworkManager."); description = "Enable or disable networking in the NetworkManager.";
params.insert("enable", JsonTypes::basicTypeToString(QVariant::Bool)); params.insert("enable", enumValueName(Bool));
setParams("EnableNetworking", params); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); registerMethod("EnableNetworking", description, params, returns);
setReturns("EnableNetworking", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("EnableWirelessNetworking", "Enable or disable wireless networking in the NetworkManager."); description = "Enable or disable wireless networking in the NetworkManager.";
params.insert("enable", JsonTypes::basicTypeToString(QVariant::Bool)); params.insert("enable", enumValueName(Bool));
setParams("EnableWirelessNetworking", params); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); registerMethod("EnableWirelessNetworking", description, params, returns);
setReturns("EnableWirelessNetworking", returns);
params.clear(); returns.clear(); 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."); description = "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)); params.insert("interface", enumValueName(String));
setParams("GetWirelessAccessPoints", params); returns.insert("o:wirelessAccessPoints", QVariantList() << objectRef("WirelessAccessPoint"));
returns.insert("o:wirelessAccessPoints", QVariantList() << JsonTypes::wirelessAccessPointRef()); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); registerMethod("GetWirelessAccessPoints", description, params, returns);
setReturns("GetWirelessAccessPoints", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("DisconnectInterface", "Disconnect the given network interface. The interface will remain disconnected until the user connect it again."); description = "Disconnect the given network interface. The interface will remain disconnected until the user connect it again.";
params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); params.insert("interface", enumValueName(String));
setParams("DisconnectInterface", params); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); registerMethod("DisconnectInterface", description, params, returns);
setReturns("DisconnectInterface", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetNetworkDevices", "Get the list of current network devices."); description = "Get the list of current network devices.";
setParams("GetNetworkDevices", params); returns.insert("wiredNetworkDevices", QVariantList() << objectRef("WiredNetworkDevice"));
returns.insert("wiredNetworkDevices", QVariantList() << JsonTypes::wiredNetworkDeviceRef()); returns.insert("wirelessNetworkDevices", QVariantList() << objectRef("WirelessNetworkDevice"));
returns.insert("wirelessNetworkDevices", QVariantList() << JsonTypes::wirelessNetworkDeviceRef()); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); registerMethod("GetNetworkDevices", description, params, returns);
setReturns("GetNetworkDevices", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ScanWifiNetworks", "Start a wifi scan for searching new networks."); description = "Start a wifi scan for searching new networks.";
params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); params.insert("interface", enumValueName(String));
setParams("ScanWifiNetworks", params); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); registerMethod("ScanWifiNetworks", description, params, returns);
setReturns("ScanWifiNetworks", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ConnectWifiNetwork", "Connect to the wifi network with the given ssid and password."); description = "Connect to the wifi network with the given ssid and password.";
params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); params.insert("interface", enumValueName(String));
params.insert("ssid", JsonTypes::basicTypeToString(QVariant::String)); params.insert("ssid", enumValueName(String));
params.insert("o:password", JsonTypes::basicTypeToString(QVariant::String)); params.insert("o:password", enumValueName(String));
setParams("ConnectWifiNetwork", params); returns.insert("networkManagerError", enumRef<NetworkManager::NetworkManagerError>());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorRef()); registerMethod("ConnectWifiNetwork", description, params, returns);
setReturns("ConnectWifiNetwork", returns);
// Notifications // Notifications
params.clear(); returns.clear(); 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); params.insert("status", status);
setParams("NetworkStatusChanged", params); registerNotification("NetworkStatusChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WirelessNetworkDeviceAdded", "Emitted whenever a new WirelessNetworkDevice was added."); description = "Emitted whenever a new WirelessNetworkDevice was added.";
params.insert("wirelessNetworkDevice", JsonTypes::wirelessNetworkDeviceRef()); params.insert("wirelessNetworkDevice", objectRef("WirelessNetworkDevice"));
setParams("WirelessNetworkDeviceAdded", params); registerNotification("WirelessNetworkDeviceAdded", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WirelessNetworkDeviceRemoved", "Emitted whenever a WirelessNetworkDevice was removed."); description = "Emitted whenever a WirelessNetworkDevice was removed.";
params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); params.insert("interface", enumValueName(String));
setParams("WirelessNetworkDeviceRemoved", params); registerNotification("WirelessNetworkDeviceRemoved", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WirelessNetworkDeviceChanged", "Emitted whenever the given WirelessNetworkDevice has changed."); description = "Emitted whenever the given WirelessNetworkDevice has changed.";
params.insert("wirelessNetworkDevice", JsonTypes::wirelessNetworkDeviceRef()); params.insert("wirelessNetworkDevice", objectRef("WirelessNetworkDevice"));
setParams("WirelessNetworkDeviceChanged", params); registerNotification("WirelessNetworkDeviceChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WiredNetworkDeviceAdded", "Emitted whenever a new WiredNetworkDevice was added."); description = "Emitted whenever a new WiredNetworkDevice was added.";
params.insert("wiredNetworkDevice", JsonTypes::wiredNetworkDeviceRef()); params.insert("wiredNetworkDevice", objectRef("WiredNetworkDevice"));
setParams("WiredNetworkDeviceAdded", params); registerNotification("WiredNetworkDeviceAdded", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WiredNetworkDeviceRemoved", "Emitted whenever a WiredNetworkDevice was removed."); description = "Emitted whenever a WiredNetworkDevice was removed.";
params.insert("interface", JsonTypes::basicTypeToString(QVariant::String)); params.insert("interface", enumValueName(String));
setParams("WiredNetworkDeviceRemoved", params); registerNotification("WiredNetworkDeviceRemoved", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("WiredNetworkDeviceChanged", "Emitted whenever the given WiredNetworkDevice has changed."); description = "Emitted whenever the given WiredNetworkDevice has changed.";
params.insert("wiredNetworkDevice", JsonTypes::wiredNetworkDeviceRef()); params.insert("wiredNetworkDevice", objectRef("WiredNetworkDevice"));
setParams("WiredNetworkDeviceChanged", params); registerNotification("WiredNetworkDeviceChanged", description, params);
connect(NymeaCore::instance()->networkManager(), &NetworkManager::stateChanged, this, &NetworkManagerHandler::onNetworkManagerStatusChanged); connect(NymeaCore::instance()->networkManager(), &NetworkManager::stateChanged, this, &NetworkManagerHandler::onNetworkManagerStatusChanged);
connect(NymeaCore::instance()->networkManager(), &NetworkManager::networkingEnabledChanged, 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 &params) JsonReply *NetworkManagerHandler::GetNetworkStatus(const QVariantMap &params)
{ {
Q_UNUSED(params); Q_UNUSED(params)
// Check available // Check available
if (!NymeaCore::instance()->networkManager()->available()) if (!NymeaCore::instance()->networkManager()->available())
return createReply(statusToReply(NetworkManager::NetworkManagerErrorNetworkManagerNotAvailable)); return createReply(statusToReply(NetworkManager::NetworkManagerErrorNetworkManagerNotAvailable));
// Pack network manager status // Pack network manager status
QVariantMap returns; QVariantMap returns = statusToReply(NetworkManager::NetworkManagerErrorNoError);
returns.insert("status", packNetworkManagerStatus()); returns.insert("status", packNetworkManagerStatus());
returns.insert("networkManagerError", JsonTypes::networkManagerErrorToString(NetworkManager::NetworkManagerErrorNoError));
return createReply(returns); return createReply(returns);
} }
@ -266,11 +285,10 @@ JsonReply *NetworkManagerHandler::GetWirelessAccessPoints(const QVariantMap &par
if (networkDevice->interface() == interface) { if (networkDevice->interface() == interface) {
QVariantList wirelessAccessPoints; QVariantList wirelessAccessPoints;
foreach (WirelessAccessPoint *wirelessAccessPoint, networkDevice->accessPoints()) 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("wirelessAccessPoints", wirelessAccessPoints);
returns.insert("networkManagerError", JsonTypes::networkManagerErrorToString(NetworkManager::NetworkManagerErrorNoError));
return createReply(returns); return createReply(returns);
} }
@ -288,22 +306,21 @@ JsonReply *NetworkManagerHandler::GetNetworkDevices(const QVariantMap &params)
QVariantList wirelessNetworkDevices; QVariantList wirelessNetworkDevices;
foreach (WirelessNetworkDevice *networkDevice, NymeaCore::instance()->networkManager()->wirelessNetworkDevices()) foreach (WirelessNetworkDevice *networkDevice, NymeaCore::instance()->networkManager()->wirelessNetworkDevices())
wirelessNetworkDevices.append(JsonTypes::packWirelessNetworkDevice(networkDevice)); wirelessNetworkDevices.append(packWirelessNetworkDevice(networkDevice));
QVariantList wiredNetworkDevices; QVariantList wiredNetworkDevices;
foreach (WiredNetworkDevice *networkDevice, NymeaCore::instance()->networkManager()->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("wirelessNetworkDevices", wirelessNetworkDevices);
returns.insert("wiredNetworkDevices", wiredNetworkDevices); returns.insert("wiredNetworkDevices", wiredNetworkDevices);
returns.insert("networkManagerError", JsonTypes::networkManagerErrorToString(NetworkManager::NetworkManagerErrorNoError));
return createReply(returns); return createReply(returns);
} }
JsonReply *NetworkManagerHandler::ScanWifiNetworks(const QVariantMap &params) JsonReply *NetworkManagerHandler::ScanWifiNetworks(const QVariantMap &params)
{ {
Q_UNUSED(params); Q_UNUSED(params)
if (!NymeaCore::instance()->networkManager()->available()) if (!NymeaCore::instance()->networkManager()->available())
return createReply(statusToReply(NetworkManager::NetworkManagerErrorNetworkManagerNotAvailable)); return createReply(statusToReply(NetworkManager::NetworkManagerErrorNetworkManagerNotAvailable));
@ -388,7 +405,7 @@ void NetworkManagerHandler::onNetworkManagerStatusChanged()
void NetworkManagerHandler::onWirelessNetworkDeviceAdded(WirelessNetworkDevice *networkDevice) void NetworkManagerHandler::onWirelessNetworkDeviceAdded(WirelessNetworkDevice *networkDevice)
{ {
QVariantMap notification; QVariantMap notification;
notification.insert("wirelessNetworkDevice", JsonTypes::packWirelessNetworkDevice(networkDevice)); notification.insert("wirelessNetworkDevice", packWirelessNetworkDevice(networkDevice));
emit WirelessNetworkDeviceAdded(notification); emit WirelessNetworkDeviceAdded(notification);
} }
@ -402,14 +419,14 @@ void NetworkManagerHandler::onWirelessNetworkDeviceRemoved(const QString &interf
void NetworkManagerHandler::onWirelessNetworkDeviceChanged(WirelessNetworkDevice *networkDevice) void NetworkManagerHandler::onWirelessNetworkDeviceChanged(WirelessNetworkDevice *networkDevice)
{ {
QVariantMap notification; QVariantMap notification;
notification.insert("wirelessNetworkDevice", JsonTypes::packWirelessNetworkDevice(networkDevice)); notification.insert("wirelessNetworkDevice", packWirelessNetworkDevice(networkDevice));
emit WirelessNetworkDeviceChanged(notification); emit WirelessNetworkDeviceChanged(notification);
} }
void NetworkManagerHandler::onWiredNetworkDeviceAdded(WiredNetworkDevice *networkDevice) void NetworkManagerHandler::onWiredNetworkDeviceAdded(WiredNetworkDevice *networkDevice)
{ {
QVariantMap notification; QVariantMap notification;
notification.insert("wiredNetworkDevice", JsonTypes::packWiredNetworkDevice(networkDevice)); notification.insert("wiredNetworkDevice", packWiredNetworkDevice(networkDevice));
emit WiredNetworkDeviceAdded(notification); emit WiredNetworkDeviceAdded(notification);
} }
@ -423,8 +440,50 @@ void NetworkManagerHandler::onWiredNetworkDeviceRemoved(const QString &interface
void NetworkManagerHandler::onWiredNetworkDeviceChanged(WiredNetworkDevice *networkDevice) void NetworkManagerHandler::onWiredNetworkDeviceChanged(WiredNetworkDevice *networkDevice)
{ {
QVariantMap notification; QVariantMap notification;
notification.insert("wiredNetworkDevice", JsonTypes::packWiredNetworkDevice(networkDevice)); notification.insert("wiredNetworkDevice", packWiredNetworkDevice(networkDevice));
emit WiredNetworkDeviceChanged(notification); 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<NetworkManager::NetworkManagerError>(status));
return returns;
}
} }

View File

@ -23,7 +23,8 @@
#include <QObject> #include <QObject>
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "networkmanager/networkmanager.h"
namespace nymeaserver { namespace nymeaserver {
@ -73,6 +74,13 @@ private slots:
void onWiredNetworkDeviceRemoved(const QString &interface); void onWiredNetworkDeviceRemoved(const QString &interface);
void onWiredNetworkDeviceChanged(WiredNetworkDevice *networkDevice); 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;
}; };
} }

View File

@ -65,26 +65,123 @@ namespace nymeaserver {
RulesHandler::RulesHandler(QObject *parent) : RulesHandler::RulesHandler(QObject *parent) :
JsonHandler(parent) JsonHandler(parent)
{ {
QVariantMap params; // Enums
QVariantMap returns; registerEnum<RuleEngine::RuleError>();
registerEnum<Types::ValueOperator>();
registerEnum<Types::StateOperator>();
registerEnum<RepeatingOption::RepeatingMode>();
// 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<Types::ValueOperator>());
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<Types::ValueOperator>());
registerObject("StateDescriptor", stateDescriptor);
QVariantMap stateEvaluator;
stateEvaluator.insert("o:stateDescriptor", objectRef("StateDescriptor"));
stateEvaluator.insert("o:childEvaluators", QVariantList() << objectRef("StateEvaluator"));
stateEvaluator.insert("o:operator", enumRef<Types::StateOperator>());
registerObject("StateEvaluator", stateEvaluator);
QVariantMap repeatingOption;
repeatingOption.insert("mode", enumRef<RepeatingOption::RepeatingMode>());
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(); params.clear(); returns.clear();
setDescription("GetRules", "Get the descriptions of all configured rules. If you need more information about a specific rule use the " description = "Get details for the rule identified by ruleId";
"method Rules.GetRuleDetails."); params.insert("ruleId", enumValueName(Uuid));
setParams("GetRules", params); returns.insert("o:rule", objectRef("Rule"));
returns.insert("ruleDescriptions", QVariantList() << JsonTypes::ruleDescriptionRef()); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
setReturns("GetRules", returns); registerMethod("GetRuleDetails", description, params, returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetRuleDetails", "Get details for the rule identified by ruleId"); description = "Add a rule. You can describe rules by one or many EventDesciptors and a StateEvaluator. "
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. "
"Note that only one of either eventDescriptor or eventDescriptorList may be passed at a time. " "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. " "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. " "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 " "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. " "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 " "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."); "actions will be executed regardless of the eventDescriptor and stateEvaluators.";
params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("name", enumValueName(String));
params.insert("actions", QVariantList() << JsonTypes::ruleActionRef()); params.insert("actions", QVariantList() << objectRef("RuleAction"));
params.insert("o:timeDescriptor", JsonTypes::timeDescriptorRef()); params.insert("o:timeDescriptor", objectRef("TimeDescriptor"));
params.insert("o:stateEvaluator", JsonTypes::stateEvaluatorRef()); params.insert("o:stateEvaluator", objectRef("StateEvaluator"));
params.insert("o:eventDescriptors", QVariantList() << JsonTypes::eventDescriptorRef()); params.insert("o:eventDescriptors", QVariantList() << objectRef("EventDescriptor"));
params.insert("o:exitActions", QVariantList() << JsonTypes::ruleActionRef()); params.insert("o:exitActions", QVariantList() << objectRef("RuleAction"));
params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("o:enabled", enumValueName(Bool));
params.insert("o:executable", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("o:executable", enumValueName(Bool));
setParams("AddRule", params); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
returns.insert("ruleError", JsonTypes::ruleErrorRef()); returns.insert("o:ruleId", enumValueName(Uuid));
returns.insert("o:ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); registerMethod("AddRule", description, params, returns);
setReturns("AddRule", returns);
params.clear(); returns.clear(); 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 " "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\" " "methods \"Rules.EnableRule\" and \"Rules.DisableRule\". If successful, the notification \"Rule.RuleConfigurationChanged\" "
"will be emitted."); "will be emitted.";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("name", enumValueName(String));
params.insert("actions", QVariantList() << JsonTypes::ruleActionRef()); params.insert("actions", QVariantList() << objectRef("RuleAction"));
params.insert("o:timeDescriptor", JsonTypes::timeDescriptorRef()); params.insert("o:timeDescriptor", objectRef("TimeDescriptor"));
params.insert("o:stateEvaluator", JsonTypes::stateEvaluatorRef()); params.insert("o:stateEvaluator", objectRef("StateEvaluator"));
params.insert("o:eventDescriptors", QVariantList() << JsonTypes::eventDescriptorRef()); params.insert("o:eventDescriptors", QVariantList() << objectRef("EventDescriptor"));
params.insert("o:exitActions", QVariantList() << JsonTypes::ruleActionRef()); params.insert("o:exitActions", QVariantList() << objectRef("RuleAction"));
params.insert("o:enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("o:enabled", enumValueName(Bool));
params.insert("o:executable", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("o:executable", enumValueName(Bool));
setParams("EditRule", params); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
returns.insert("ruleError", JsonTypes::ruleErrorRef()); returns.insert("o:rule", objectRef("Rule"));
returns.insert("o:rule", JsonTypes::ruleRef()); registerMethod("EditRule", description, params, returns);
setReturns("EditRule", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RemoveRule", "Remove a rule"); description = "Remove a rule";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
setParams("RemoveRule", params); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
returns.insert("ruleError", JsonTypes::ruleErrorRef()); registerMethod("RemoveRule", description, params, returns);
setReturns("RemoveRule", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("FindRules", "Find a list of rules containing any of the given parameters."); description = "Find a list of rules containing any of the given parameters.";
params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("deviceId", enumValueName(Uuid));
setParams("FindRules", params); returns.insert("ruleIds", QVariantList() << enumValueName(Uuid));
returns.insert("ruleIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::Uuid)); registerMethod("FindRules", description, params, returns);
setReturns("FindRules", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("EnableRule", "Enabled a rule that has previously been disabled." description = "Enabled a rule that has previously been disabled."
"If successful, the notification \"Rule.RuleConfigurationChanged\" will be emitted."); "If successful, the notification \"Rule.RuleConfigurationChanged\" will be emitted.";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
setParams("EnableRule", params); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
returns.insert("ruleError", JsonTypes::ruleErrorRef()); registerMethod("EnableRule", description, params, returns);
setReturns("EnableRule", returns);
params.clear(); returns.clear(); 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. " 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."); "If successful, the notification \"Rule.RuleConfigurationChanged\" will be emitted.";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
setParams("DisableRule", params); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
returns.insert("ruleError", JsonTypes::ruleErrorRef()); registerMethod("DisableRule", description, params, returns);
setReturns("DisableRule", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ExecuteActions", "Execute the action list of the rule with the given ruleId."); description = "Execute the action list of the rule with the given ruleId.";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
setParams("ExecuteActions", params); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
returns.insert("ruleError", JsonTypes::ruleErrorRef()); registerMethod("ExecuteActions", description, params, returns);
setReturns("ExecuteActions", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ExecuteExitActions", "Execute the exit action list of the rule with the given ruleId."); description = "Execute the exit action list of the rule with the given ruleId.";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
setParams("ExecuteExitActions", params); returns.insert("ruleError", enumRef<RuleEngine::RuleError>());
returns.insert("ruleError", JsonTypes::ruleErrorRef()); registerMethod("ExecuteExitActions", description, params, returns);
setReturns("ExecuteExitActions", returns);
// Notifications // Notifications
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RuleRemoved", "Emitted whenever a Rule was removed."); description = "Emitted whenever a Rule was removed.";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
setParams("RuleRemoved", params); registerNotification("RuleRemoved", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RuleAdded", "Emitted whenever a Rule was added."); description = "Emitted whenever a Rule was added.";
params.insert("rule", JsonTypes::ruleRef()); params.insert("rule", objectRef("Rule"));
setParams("RuleAdded", params); registerNotification("RuleAdded", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RuleActiveChanged", "Emitted whenever the active state of a Rule changed."); description = "Emitted whenever the active state of a Rule changed.";
params.insert("ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("ruleId", enumValueName(Uuid));
params.insert("active", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("active", enumValueName(Bool));
setParams("RuleActiveChanged", params); registerNotification("RuleActiveChanged", description, params);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RuleConfigurationChanged", "Emitted whenever the configuration of a Rule changed."); description = "Emitted whenever the configuration of a Rule changed.";
params.insert("rule", JsonTypes::ruleRef()); params.insert("rule", objectRef("Rule"));
setParams("RuleConfigurationChanged", params); registerNotification("RuleConfigurationChanged", description, params);
connect(NymeaCore::instance(), &NymeaCore::ruleAdded, this, &RulesHandler::ruleAddedNotification); connect(NymeaCore::instance(), &NymeaCore::ruleAdded, this, &RulesHandler::ruleAddedNotification);
connect(NymeaCore::instance(), &NymeaCore::ruleRemoved, this, &RulesHandler::ruleRemovedNotification); connect(NymeaCore::instance(), &NymeaCore::ruleRemoved, this, &RulesHandler::ruleRemovedNotification);
@ -209,9 +298,13 @@ JsonReply* RulesHandler::GetRules(const QVariantMap &params)
{ {
Q_UNUSED(params) Q_UNUSED(params)
QVariantMap returns; QVariantList rulesList;
returns.insert("ruleDescriptions", JsonTypes::packRuleDescriptions()); foreach (const Rule &rule, NymeaCore::instance()->ruleEngine()->rules()) {
rulesList.append(packRuleDescription(rule));
}
QVariantMap returns;
returns.insert("ruleDescriptions", rulesList);
return createReply(returns); return createReply(returns);
} }
@ -220,16 +313,19 @@ JsonReply *RulesHandler::GetRuleDetails(const QVariantMap &params)
RuleId ruleId = RuleId(params.value("ruleId").toString()); RuleId ruleId = RuleId(params.value("ruleId").toString());
Rule rule = NymeaCore::instance()->ruleEngine()->findRule(ruleId); Rule rule = NymeaCore::instance()->ruleEngine()->findRule(ruleId);
if (rule.id().isNull()) { if (rule.id().isNull()) {
return createReply(statusToReply(RuleEngine::RuleErrorRuleNotFound)); QVariantMap data;
data.insert("ruleError", enumValueName<RuleEngine::RuleError>(RuleEngine::RuleErrorRuleNotFound));
return createReply(data);
} }
QVariantMap returns = statusToReply(RuleEngine::RuleErrorNoError); QVariantMap returns;
returns.insert("rule", JsonTypes::packRule(rule)); returns.insert("ruleError", enumValueName<RuleEngine::RuleError>(RuleEngine::RuleErrorNoError));
returns.insert("rule", packRule(rule));
return createReply(returns); return createReply(returns);
} }
JsonReply* RulesHandler::AddRule(const QVariantMap &params) JsonReply* RulesHandler::AddRule(const QVariantMap &params)
{ {
Rule rule = JsonTypes::unpackRule(params); Rule rule = unpackRule(params);
rule.setId(RuleId::createRuleId()); rule.setId(RuleId::createRuleId());
RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->addRule(rule); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->addRule(rule);
@ -237,19 +333,19 @@ JsonReply* RulesHandler::AddRule(const QVariantMap &params)
if (status == RuleEngine::RuleErrorNoError) { if (status == RuleEngine::RuleErrorNoError) {
returns.insert("ruleId", rule.id().toString()); returns.insert("ruleId", rule.id().toString());
} }
returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); returns.insert("ruleError", enumValueName<RuleEngine::RuleError>(status));
return createReply(returns); return createReply(returns);
} }
JsonReply *RulesHandler::EditRule(const QVariantMap &params) JsonReply *RulesHandler::EditRule(const QVariantMap &params)
{ {
Rule rule = JsonTypes::unpackRule(params); Rule rule = unpackRule(params);
RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->editRule(rule); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->editRule(rule);
QVariantMap returns; QVariantMap returns;
if (status == RuleEngine::RuleErrorNoError) { 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<RuleEngine::RuleError>(status));
return createReply(returns); return createReply(returns);
} }
@ -258,7 +354,7 @@ JsonReply* RulesHandler::RemoveRule(const QVariantMap &params)
QVariantMap returns; QVariantMap returns;
RuleId ruleId(params.value("ruleId").toString()); RuleId ruleId(params.value("ruleId").toString());
RuleEngine::RuleError status = NymeaCore::instance()->removeRule(ruleId); RuleEngine::RuleError status = NymeaCore::instance()->removeRule(ruleId);
returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); returns.insert("ruleError", enumValueName<RuleEngine::RuleError>(status));
return createReply(returns); return createReply(returns);
} }
@ -279,12 +375,18 @@ JsonReply *RulesHandler::FindRules(const QVariantMap &params)
JsonReply *RulesHandler::EnableRule(const QVariantMap &params) JsonReply *RulesHandler::EnableRule(const QVariantMap &params)
{ {
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<RuleEngine::RuleError>(status));
return createReply(ret);
} }
JsonReply *RulesHandler::DisableRule(const QVariantMap &params) JsonReply *RulesHandler::DisableRule(const QVariantMap &params)
{ {
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<RuleEngine::RuleError>(status));
return createReply(ret);
} }
JsonReply *RulesHandler::ExecuteActions(const QVariantMap &params) JsonReply *RulesHandler::ExecuteActions(const QVariantMap &params)
@ -292,7 +394,7 @@ JsonReply *RulesHandler::ExecuteActions(const QVariantMap &params)
QVariantMap returns; QVariantMap returns;
RuleId ruleId(params.value("ruleId").toString()); RuleId ruleId(params.value("ruleId").toString());
RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeActions(ruleId); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeActions(ruleId);
returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); returns.insert("ruleError", enumValueName<RuleEngine::RuleError>(status));
return createReply(returns); return createReply(returns);
} }
@ -301,7 +403,7 @@ JsonReply *RulesHandler::ExecuteExitActions(const QVariantMap &params)
QVariantMap returns; QVariantMap returns;
RuleId ruleId(params.value("ruleId").toString()); RuleId ruleId(params.value("ruleId").toString());
RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeExitActions(ruleId); RuleEngine::RuleError status = NymeaCore::instance()->ruleEngine()->executeExitActions(ruleId);
returns.insert("ruleError", JsonTypes::ruleErrorToString(status)); returns.insert("ruleError", enumValueName<RuleEngine::RuleError>(status));
return createReply(returns); return createReply(returns);
} }
@ -316,7 +418,7 @@ void RulesHandler::ruleRemovedNotification(const RuleId &ruleId)
void RulesHandler::ruleAddedNotification(const Rule &rule) void RulesHandler::ruleAddedNotification(const Rule &rule)
{ {
QVariantMap params; QVariantMap params;
params.insert("rule", JsonTypes::packRule(rule)); params.insert("rule", packRule(rule));
emit RuleAdded(params); emit RuleAdded(params);
} }
@ -333,9 +435,484 @@ void RulesHandler::ruleActiveChangedNotification(const Rule &rule)
void RulesHandler::ruleConfigurationChangedNotification(const Rule &rule) void RulesHandler::ruleConfigurationChangedNotification(const Rule &rule)
{ {
QVariantMap params; QVariantMap params;
params.insert("rule", JsonTypes::packRule(rule)); params.insert("rule", packRule(rule));
emit RuleConfigurationChanged(params); 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 &paramDescriptor)
{
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<Types::ValueOperator>(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 &paramDescriptor, 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<Types::StateOperator>(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<Types::ValueOperator>(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<RepeatingOption::RepeatingMode>(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<ParamDescriptor> RulesHandler::unpackParamDescriptors(const QVariantList &paramList)
{
QList<ParamDescriptor> params;
foreach (const QVariant &paramVariant, paramList)
params.append(unpackParamDescriptor(paramVariant.toMap()));
return params;
}
ParamDescriptor RulesHandler::unpackParamDescriptor(const QVariantMap &paramMap)
{
QString operatorString = paramMap.value("operator").toString();
Types::ValueOperator valueOperator = enumNameToValue<Types::ValueOperator>(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<ParamDescriptor> 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<RepeatingOption::RepeatingMode>(repeatingOptionMap.value("mode").toString());
QList<int> weekDays;
if (repeatingOptionMap.contains("weekDays")) {
foreach (const QVariant weekDayVariant, repeatingOptionMap.value("weekDays").toList()) {
weekDays.append(weekDayVariant.toInt());
}
}
QList<int> 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<CalendarItem> calendarItems;
foreach (const QVariant &calendarItemValiant, timeDescriptorMap.value("calendarItems").toList()) {
calendarItems.append(unpackCalendarItem(calendarItemValiant.toMap()));
}
timeDescriptor.setCalendarItems(calendarItems);
}
if (timeDescriptorMap.contains("timeEventItems")) {
QList<TimeEventItem> 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<Types::ValueOperator>(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<Types::StateOperator>(stateEvaluatorMap.value("operator").toString()));
} else {
ret.setOperatorType(Types::StateOperatorAnd);
}
QList<StateEvaluator> 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 &paramVariant, 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<EventDescriptor> eventDescriptors;
if (ruleMap.contains("eventDescriptors")) {
QVariantList eventDescriptorVariantList = ruleMap.value("eventDescriptors").toList();
foreach (const QVariant &eventDescriptorVariant, eventDescriptorVariantList) {
eventDescriptors.append(unpackEventDescriptor(eventDescriptorVariant.toMap()));
}
}
QList<RuleAction> actions;
if (ruleMap.contains("actions")) {
QVariantList actionsVariantList = ruleMap.value("actions").toList();
foreach (const QVariant &actionVariant, actionsVariantList) {
actions.append(unpackRuleAction(actionVariant.toMap()));
}
}
QList<RuleAction> 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;
}
} }

View File

@ -22,7 +22,9 @@
#ifndef RULESHANDLER_H #ifndef RULESHANDLER_H
#define RULESHANDLER_H #define RULESHANDLER_H
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "ruleengine/rule.h"
namespace nymeaserver { namespace nymeaserver {
@ -30,7 +32,7 @@ class RulesHandler : public JsonHandler
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit RulesHandler(QObject *parent = 0); explicit RulesHandler(QObject *parent = nullptr);
QString name() const override; QString name() const override;
@ -60,6 +62,37 @@ private slots:
void ruleActiveChangedNotification(const Rule &rule); void ruleActiveChangedNotification(const Rule &rule);
void ruleConfigurationChangedNotification(const Rule &rule); void ruleConfigurationChangedNotification(const Rule &rule);
private:
static QVariantMap packRuleDescription(const Rule &rule);
static QVariantMap packParamDescriptor(const ParamDescriptor &paramDescriptor);
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<ParamDescriptor> unpackParamDescriptors(const QVariantList &paramList);
static ParamDescriptor unpackParamDescriptor(const QVariantMap &paramMap);
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);
}; };
} }

View File

@ -33,6 +33,7 @@
*/ */
#include "statehandler.h" #include "statehandler.h"
#include "devicehandler.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "loggingcategories.h" #include "loggingcategories.h"
@ -42,16 +43,19 @@ namespace nymeaserver {
StateHandler::StateHandler(QObject *parent) : StateHandler::StateHandler(QObject *parent) :
JsonHandler(parent) JsonHandler(parent)
{ {
QVariantMap params; QVariantMap state;
QVariantMap returns; state.insert("stateTypeId", enumValueName(Uuid));
state.insert("deviceId", enumValueName(Uuid));
state.insert("value", enumValueName(Variant));
registerObject("State", state);
params.clear(); returns.clear(); // Methods
setDescription("GetStateType", "Get the StateType for the given stateTypeId."); QString description; QVariantMap params; QVariantMap returns;
params.insert("stateTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); description = "Get the StateType for the given stateTypeId.";
setParams("GetStateType", params); params.insert("stateTypeId", enumValueName(Uuid));
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", enumRef<Device::DeviceError>());
returns.insert("o:stateType", JsonTypes::stateTypeRef()); returns.insert("o:stateType", objectRef("StateType"));
setReturns("GetStateType", returns); registerMethod("GetStateType", description, params, returns, true);
} }
/*! Returns the name of the \l{StateHandler}. In this case \b States.*/ /*! Returns the name of the \l{StateHandler}. In this case \b States.*/
@ -67,13 +71,16 @@ JsonReply* StateHandler::GetStateType(const QVariantMap &params) const
foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) {
foreach (const StateType &stateType, deviceClass.stateTypes()) { foreach (const StateType &stateType, deviceClass.stateTypes()) {
if (stateType.id() == stateTypeId) { if (stateType.id() == stateTypeId) {
QVariantMap data = statusToReply(Device::DeviceErrorNoError); QVariantMap data;
data.insert("stateType", JsonTypes::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorNoError));
data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale()));
return createReply(data); return createReply(data);
} }
} }
} }
return createReply(statusToReply(Device::DeviceErrorStateTypeNotFound)); QVariantMap data;
data.insert("deviceError", enumValueName<Device::DeviceError>(Device::DeviceErrorStateTypeNotFound));
return createReply(data);
} }
} }

View File

@ -22,7 +22,7 @@
#ifndef STATEHANDLER_H #ifndef STATEHANDLER_H
#define STATEHANDLER_H #define STATEHANDLER_H
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
namespace nymeaserver { namespace nymeaserver {
@ -30,7 +30,7 @@ class StateHandler : public JsonHandler
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit StateHandler(QObject *parent = 0); explicit StateHandler(QObject *parent = nullptr);
QString name() const override; QString name() const override;
Q_INVOKABLE JsonReply *GetStateType(const QVariantMap &params) const; Q_INVOKABLE JsonReply *GetStateType(const QVariantMap &params) const;

View File

@ -32,146 +32,148 @@ SystemHandler::SystemHandler(Platform *platform, QObject *parent):
JsonHandler(parent), JsonHandler(parent),
m_platform(platform) 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 // Methods
QVariantMap params; QVariantMap returns; QString description; 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."); 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.";
setParams("GetCapabilities", params); returns.insert("powerManagement", enumValueName(Bool));
returns.insert("powerManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("updateManagement", enumValueName(Bool));
returns.insert("updateManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("GetCapabilities", description, params, returns);
setReturns("GetCapabilities", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("Reboot", "Initiate a reboot of the system. The return value will indicate whether the procedure has been initiated successfully."); description = "Initiate a reboot of the system. The return value will indicate whether the procedure has been initiated successfully.";
setParams("Reboot", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("Reboot", description, params, returns);
setReturns("Reboot", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("Shutdown", "Initiate a shutdown of the system. The return value will indicate whether the procedure has been initiated successfully."); description = "Initiate a shutdown of the system. The return value will indicate whether the procedure has been initiated successfully.";
setParams("Shutdown", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("Shutdown", description, params, returns);
setReturns("Shutdown", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetUpdateStatus", description = "Get the current status of the update system. \"busy\" indicates that the system is current busy with "
"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 " "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 " "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 " "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 " "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 " "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."); "might restart at any point while an update is running.";
setParams("GetUpdateStatus", params); returns.insert("busy", enumValueName(Bool));
returns.insert("busy", JsonTypes::basicTypeToString(JsonTypes::Bool)); returns.insert("updateRunning", enumValueName(Bool));
returns.insert("updateRunning", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("GetUpdateStatus", description, params, returns);
setReturns("GetUpdateStatus", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("CheckForUpdates", description = "Instruct the system to poll the server for updates. Normally the system should automatically do this "
"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 " "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 " "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 " "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 " "the list of packages retrieved from GetPackages and check whether there are packages with the updateAvailable "
"flag set to true."); "flag set to true.";
setParams("CheckForUpdates", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("CheckForUpdates", description, params, returns);
setReturns("CheckForUpdates", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetPackages", description = "Get the list of packages currently available to the system. This might include installed available but "
"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.";
"not installed packages. Installed packages will have the installedVersion set to a non-empty value."); returns.insert("packages", QVariantList() << objectRef("Package"));
setParams("GetPackages", params); registerMethod("GetPackages", description, params, returns);
returns.insert("packages", QVariantList() << JsonTypes::packageRef());
setReturns("GetPackages", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("UpdatePackages", description = "Starts updating/installing packages with the given ids. Returns true if the upgrade has been started "
"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 " "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 " "check the packages whether they are in a state where they can either be installed (no installedVersion "
"set) or upgraded (updateAvailable set to true)."); "set) or upgraded (updateAvailable set to true).";
params.insert("o:packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("o:packageIds", QVariantList() << enumValueName(String));
setParams("UpdatePackages", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("UpdatePackages", description, params, returns);
setReturns("UpdatePackages", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RollbackPackages", description = "Starts a rollback. Returns true if the rollback has been started successfully. Before calling this "
"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).";
"method, clients should check whether the package can be rolled back (canRollback set to true)."); params.insert("packageIds", QVariantList() << enumValueName(String));
params.insert("packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("success", enumValueName(Bool));
setParams("RollbackPackages", params); registerMethod("RollbackPackages", description, params, returns);
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool));
setReturns("RollbackPackages", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("RemovePackages", description = "Starts removing a package. Returns true if the removal has been started successfully. Before calling "
"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).";
"this method, clients should check whether the package can be removed (canRemove set to true)."); params.insert("packageIds", QVariantList() << enumValueName(String));
params.insert("packageIds", QVariantList() << JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("success", enumValueName(Bool));
setParams("RemovePackages", params); registerMethod("RemovePackages", description, params, returns);
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool));
setReturns("RemovePackages", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("GetRepositories", "Get the list of repositories currently available to the system."); description = "Get the list of repositories currently available to the system.";
setParams("GetRepositories", params); returns.insert("repositories", QVariantList() << objectRef("Repository"));
returns.insert("repositories", QVariantList() << JsonTypes::repositoryRef()); registerMethod("GetRepositories", description, params, returns);
setReturns("GetRepositories", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("EnableRepository", "Enable or disable a repository."); description = "Enable or disable a repository.";
params.insert("repositoryId", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("repositoryId", enumValueName(String));
params.insert("enabled", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("enabled", enumValueName(Bool));
setParams("EnableRepository", params); returns.insert("success", enumValueName(Bool));
returns.insert("success", JsonTypes::basicTypeToString(JsonTypes::Bool)); registerMethod("EnableRepository", description, params, returns);
setReturns("EnableRepository", returns);
// Notifications // Notifications
params.clear(); params.clear();
setDescription("CapabilitiesChanged", "Emitted whenever the system capabilities change."); description = "Emitted whenever the system capabilities change.";
params.insert("powerManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("powerManagement", enumValueName(Bool));
params.insert("updateManagement", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("updateManagement", enumValueName(Bool));
setParams("CapabilitiesChanged", params); registerNotification("CapabilitiesChanged", description, params);
params.clear(); params.clear();
setDescription("UpdateStatusChanged", "Emitted whenever the update status changes."); description = "Emitted whenever the update status changes.";
params.insert("busy", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("busy", enumValueName(Bool));
params.insert("updateRunning", JsonTypes::basicTypeToString(JsonTypes::Bool)); params.insert("updateRunning", enumValueName(Bool));
setParams("UpdateStatusChanged", params); registerNotification("UpdateStatusChanged", description, params);
params.clear(); params.clear();
setDescription("PackageAdded", "Emitted whenever a package is added to the list of packages."); description = "Emitted whenever a package is added to the list of packages.";
params.insert("package", JsonTypes::packageRef()); params.insert("package", objectRef("Package"));
setParams("PackageAdded", params); registerNotification("PackageAdded", description, params);
params.clear(); params.clear();
setDescription("PackageChanged", "Emitted whenever a package in the list of packages changes."); description = "Emitted whenever a package in the list of packages changes.";
params.insert("package", JsonTypes::packageRef()); params.insert("package", objectRef("Package"));
setParams("PackageChanged", params); registerNotification("PackageChanged", description, params);
params.clear(); params.clear();
setDescription("PackageRemoved", "Emitted whenever a package is removed from the list of packages."); description = "Emitted whenever a package is removed from the list of packages.";
params.insert("packageId", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("packageId", enumValueName(String));
setParams("PackageRemoved", params); registerNotification("PackageRemoved", description, params);
params.clear(); params.clear();
setDescription("RepositoryAdded", "Emitted whenever a repository is added to the list of repositories."); description = "Emitted whenever a repository is added to the list of repositories.";
params.insert("repository", JsonTypes::repositoryRef()); params.insert("repository", objectRef("Repository"));
setParams("RepositoryAdded", params); registerNotification("RepositoryAdded", description, params);
params.clear(); params.clear();
setDescription("RepositoryChanged", "Emitted whenever a repository in the list of repositories changes."); description = "Emitted whenever a repository in the list of repositories changes.";
params.insert("repository", JsonTypes::repositoryRef()); params.insert("repository", objectRef("Repository"));
setParams("RepositoryChanged", params); registerNotification("RepositoryChanged", description, params);
params.clear(); params.clear();
setDescription("RepositoryRemoved", "Emitted whenever a repository is removed from the list of repositories."); description = "Emitted whenever a repository is removed from the list of repositories.";
params.insert("repositoryId", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("repositoryId", enumValueName(String));
setParams("RepositoryRemoved", params); registerNotification("RepositoryRemoved", description, params);
connect(m_platform->systemController(), &PlatformSystemController::availableChanged, this, &SystemHandler::onCapabilitiesChanged); 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){ connect(m_platform->updateController(), &PlatformUpdateController::packageAdded, this, [this](const Package &package){
QVariantMap params; QVariantMap params;
params.insert("package", JsonTypes::packPackage(package)); params.insert("package", packPackage(package));
emit PackageAdded(params); emit PackageAdded(params);
}); });
connect(m_platform->updateController(), &PlatformUpdateController::packageChanged, this, [this](const Package &package){ connect(m_platform->updateController(), &PlatformUpdateController::packageChanged, this, [this](const Package &package){
QVariantMap params; QVariantMap params;
params.insert("package", JsonTypes::packPackage(package)); params.insert("package", packPackage(package));
emit PackageChanged(params); emit PackageChanged(params);
}); });
connect(m_platform->updateController(), &PlatformUpdateController::packageRemoved, this, [this](const QString &packageId){ 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){ connect(m_platform->updateController(), &PlatformUpdateController::repositoryAdded, this, [this](const Repository &repository){
QVariantMap params; QVariantMap params;
params.insert("repository", JsonTypes::packRepository(repository)); params.insert("repository", packRepository(repository));
emit RepositoryAdded(params); emit RepositoryAdded(params);
}); });
connect(m_platform->updateController(), &PlatformUpdateController::repositoryChanged, this, [this](const Repository &repository){ connect(m_platform->updateController(), &PlatformUpdateController::repositoryChanged, this, [this](const Repository &repository){
QVariantMap params; QVariantMap params;
params.insert("repository", JsonTypes::packRepository(repository)); params.insert("repository", packRepository(repository));
emit RepositoryChanged(params); emit RepositoryChanged(params);
}); });
connect(m_platform->updateController(), &PlatformUpdateController::repositoryRemoved, this, [this](const QString &repositoryId){ connect(m_platform->updateController(), &PlatformUpdateController::repositoryRemoved, this, [this](const QString &repositoryId){
@ -236,7 +238,7 @@ JsonReply *SystemHandler::GetCapabilities(const QVariantMap &params)
JsonReply *SystemHandler::Reboot(const QVariantMap &params) const JsonReply *SystemHandler::Reboot(const QVariantMap &params) const
{ {
Q_UNUSED(params); Q_UNUSED(params)
bool status = m_platform->systemController()->reboot(); bool status = m_platform->systemController()->reboot();
QVariantMap returns; QVariantMap returns;
returns.insert("success", status); returns.insert("success", status);
@ -245,7 +247,7 @@ JsonReply *SystemHandler::Reboot(const QVariantMap &params) const
JsonReply *SystemHandler::Shutdown(const QVariantMap &params) const JsonReply *SystemHandler::Shutdown(const QVariantMap &params) const
{ {
Q_UNUSED(params); Q_UNUSED(params)
bool status = m_platform->systemController()->shutdown(); bool status = m_platform->systemController()->shutdown();
QVariantMap returns; QVariantMap returns;
returns.insert("success", status); returns.insert("success", status);
@ -275,7 +277,7 @@ JsonReply *SystemHandler::GetPackages(const QVariantMap &params) const
Q_UNUSED(params) Q_UNUSED(params)
QVariantList packagelist; QVariantList packagelist;
foreach (const Package &package, m_platform->updateController()->packages()) { foreach (const Package &package, m_platform->updateController()->packages()) {
packagelist.append(JsonTypes::packPackage(package)); packagelist.append(packPackage(package));
} }
QVariantMap returns; QVariantMap returns;
returns.insert("packages", packagelist); returns.insert("packages", packagelist);
@ -308,10 +310,10 @@ JsonReply *SystemHandler::RemovePackages(const QVariantMap &params) const
JsonReply *SystemHandler::GetRepositories(const QVariantMap &params) const JsonReply *SystemHandler::GetRepositories(const QVariantMap &params) const
{ {
Q_UNUSED(params); Q_UNUSED(params)
QVariantList repos; QVariantList repos;
foreach (const Repository &repository, m_platform->updateController()->repositories()) { foreach (const Repository &repository, m_platform->updateController()->repositories()) {
repos.append(JsonTypes::packRepository(repository)); repos.append(packRepository(repository));
} }
QVariantMap returns; QVariantMap returns;
returns.insert("repositories", repos); returns.insert("repositories", repos);
@ -335,4 +337,28 @@ void SystemHandler::onCapabilitiesChanged()
emit CapabilitiesChanged(caps); 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;
}
} }

View File

@ -23,9 +23,11 @@
#include <QObject> #include <QObject>
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "platform/platform.h" #include "platform/platform.h"
#include "platform/package.h"
#include "platform/repository.h"
namespace nymeaserver { namespace nymeaserver {
@ -64,6 +66,10 @@ signals:
private slots: private slots:
void onCapabilitiesChanged(); void onCapabilitiesChanged();
private:
static QVariantMap packPackage(const Package &package);
static QVariantMap packRepository(const Repository &repository);
private: private:
Platform *m_platform = nullptr; Platform *m_platform = nullptr;
}; };

View File

@ -27,51 +27,58 @@ namespace nymeaserver {
TagsHandler::TagsHandler(QObject *parent) : JsonHandler(parent) TagsHandler::TagsHandler(QObject *parent) : JsonHandler(parent)
{ {
QVariantMap params; // Enums
QVariantMap returns; registerEnum<TagsStorage::TagError>();
// 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<TagsStorage::TagError>());
returns.insert("o:tags", QVariantList() << objectRef("Tag"));
registerMethod("GetTags", description, params, returns);
params.clear(); returns.clear(); 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)."); 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("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("tag", objectRef("Tag"));
params.insert("o:ruleId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("tagError", enumRef<TagsStorage::TagError>());
params.insert("o:appId", JsonTypes::basicTypeToString(JsonTypes::String)); registerMethod("AddTag", description, params, returns);
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);
params.clear(); returns.clear(); 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."); 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", JsonTypes::tagRef()); params.insert("tag", objectRef("Tag"));
setParams("AddTag", params); returns.insert("tagError", enumRef<TagsStorage::TagError>());
returns.insert("tagError", JsonTypes::tagErrorRef()); registerMethod("RemoveTag", description, params, returns);
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);
// Notifications // Notifications
params.clear(); params.clear();
setDescription("TagAdded", "Emitted whenever a tag is added to the system. "); description = "Emitted whenever a tag is added to the system. ";
params.insert("tag", JsonTypes::tagRef()); params.insert("tag", objectRef("Tag"));
setParams("TagAdded", params); registerNotification("TagAdded", description, params);
connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagAdded, this, &TagsHandler::onTagAdded); connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagAdded, this, &TagsHandler::onTagAdded);
params.clear(); params.clear();
setDescription("TagRemoved", "Emitted whenever a tag is removed from the system. "); description = "Emitted whenever a tag is removed from the system. ";
params.insert("tag", JsonTypes::tagRef()); params.insert("tag", objectRef("Tag"));
setParams("TagRemoved", params); registerNotification("TagRemoved", description, params);
connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagRemoved, this, &TagsHandler::onTagRemoved); connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagRemoved, this, &TagsHandler::onTagRemoved);
params.clear(); params.clear();
setDescription("TagValueChanged", "Emitted whenever a tag's value is changed in the system. "); description = "Emitted whenever a tag's value is changed in the system. ";
params.insert("tag", JsonTypes::tagRef()); params.insert("tag", objectRef("Tag"));
setParams("TagValueChanged", params); registerNotification("TagValueChanged", description, params);
connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagValueChanged, this, &TagsHandler::onTagValueChanged); connect(NymeaCore::instance()->tagsStorage(), &TagsStorage::tagValueChanged, this, &TagsHandler::onTagValueChanged);
} }
@ -96,7 +103,7 @@ JsonReply *TagsHandler::GetTags(const QVariantMap &params) const
if (params.contains("tagId") && params.value("tagId").toString() != tag.tagId()) { if (params.contains("tagId") && params.value("tagId").toString() != tag.tagId()) {
continue; continue;
} }
ret.append(JsonTypes::packTag(tag)); ret.append(packTag(tag));
} }
QVariantMap returns = statusToReply(TagsStorage::TagErrorNoError); QVariantMap returns = statusToReply(TagsStorage::TagErrorNoError);
returns.insert("tags", ret); returns.insert("tags", ret);
@ -106,7 +113,7 @@ JsonReply *TagsHandler::GetTags(const QVariantMap &params) const
JsonReply *TagsHandler::AddTag(const QVariantMap &params) const JsonReply *TagsHandler::AddTag(const QVariantMap &params) const
{ {
Tag tag = JsonTypes::unpackTag(params.value("tag").toMap()); Tag tag = unpackTag(params.value("tag").toMap());
TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->addTag(tag); TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->addTag(tag);
QVariantMap returns = statusToReply(error); QVariantMap returns = statusToReply(error);
return createReply(returns); return createReply(returns);
@ -114,7 +121,7 @@ JsonReply *TagsHandler::AddTag(const QVariantMap &params) const
JsonReply *TagsHandler::RemoveTag(const QVariantMap &params) const JsonReply *TagsHandler::RemoveTag(const QVariantMap &params) const
{ {
Tag tag = JsonTypes::unpackTag(params.value("tag").toMap()); Tag tag = unpackTag(params.value("tag").toMap());
TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->removeTag(tag); TagsStorage::TagError error = NymeaCore::instance()->tagsStorage()->removeTag(tag);
QVariantMap returns = statusToReply(error); QVariantMap returns = statusToReply(error);
return createReply(returns); return createReply(returns);
@ -124,7 +131,7 @@ void TagsHandler::onTagAdded(const Tag &tag)
{ {
qCDebug(dcJsonRpc) << "Notify \"Tags.TagAdded\""; qCDebug(dcJsonRpc) << "Notify \"Tags.TagAdded\"";
QVariantMap params; QVariantMap params;
params.insert("tag", JsonTypes::packTag(tag)); params.insert("tag", packTag(tag));
emit TagAdded(params); emit TagAdded(params);
} }
@ -132,7 +139,7 @@ void TagsHandler::onTagRemoved(const Tag &tag)
{ {
qCDebug(dcJsonRpc) << "Notify \"Tags.TagRemoved\""; qCDebug(dcJsonRpc) << "Notify \"Tags.TagRemoved\"";
QVariantMap params; QVariantMap params;
params.insert("tag", JsonTypes::packTag(tag)); params.insert("tag", packTag(tag));
emit TagRemoved(params); emit TagRemoved(params);
} }
@ -140,8 +147,42 @@ void TagsHandler::onTagValueChanged(const Tag &tag)
{ {
qCDebug(dcJsonRpc) << "Notify \"Tags.TagValueChanged\""; qCDebug(dcJsonRpc) << "Notify \"Tags.TagValueChanged\"";
QVariantMap params; QVariantMap params;
params.insert("tag", JsonTypes::packTag(tag)); params.insert("tag", packTag(tag));
emit TagValueChanged(params); 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<TagsStorage::TagError>(status));
return returns;
}
} }

View File

@ -23,7 +23,8 @@
#include <QObject> #include <QObject>
#include "jsonhandler.h" #include "jsonrpc/jsonhandler.h"
#include "tagging/tagsstorage.h"
namespace nymeaserver { namespace nymeaserver {
@ -47,6 +48,13 @@ private slots:
void onTagAdded(const Tag &tag); void onTagAdded(const Tag &tag);
void onTagRemoved(const Tag &tag); void onTagRemoved(const Tag &tag);
void onTagValueChanged(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;
}; };
} }

View File

@ -35,9 +35,8 @@ HEADERS += nymeacore.h \
servers/websocketserver.h \ servers/websocketserver.h \
servers/mqttbroker.h \ servers/mqttbroker.h \
jsonrpc/jsonrpcserver.h \ jsonrpc/jsonrpcserver.h \
jsonrpc/jsonhandler.h \ jsonrpc/jsonvalidator.h \
jsonrpc/devicehandler.h \ jsonrpc/devicehandler.h \
jsonrpc/jsontypes.h \
jsonrpc/ruleshandler.h \ jsonrpc/ruleshandler.h \
jsonrpc/actionhandler.h \ jsonrpc/actionhandler.h \
jsonrpc/eventhandler.h \ jsonrpc/eventhandler.h \
@ -113,9 +112,8 @@ SOURCES += nymeacore.cpp \
servers/bluetoothserver.cpp \ servers/bluetoothserver.cpp \
servers/mqttbroker.cpp \ servers/mqttbroker.cpp \
jsonrpc/jsonrpcserver.cpp \ jsonrpc/jsonrpcserver.cpp \
jsonrpc/jsonhandler.cpp \ jsonrpc/jsonvalidator.cpp \
jsonrpc/devicehandler.cpp \ jsonrpc/devicehandler.cpp \
jsonrpc/jsontypes.cpp \
jsonrpc/ruleshandler.cpp \ jsonrpc/ruleshandler.cpp \
jsonrpc/actionhandler.cpp \ jsonrpc/actionhandler.cpp \
jsonrpc/eventhandler.cpp \ jsonrpc/eventhandler.cpp \

View File

@ -38,9 +38,9 @@
#include "logentry.h" #include "logentry.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "jsonrpc/jsontypes.h"
#include <QDebug> #include <QDebug>
#include <QMetaEnum>
namespace nymeaserver { namespace nymeaserver {
@ -156,13 +156,17 @@ int LogEntry::errorCode() const
QDebug operator<<(QDebug dbg, const LogEntry &entry) QDebug operator<<(QDebug dbg, const LogEntry &entry)
{ {
QMetaEnum metaEnum;
dbg.nospace() << "LogEntry (" << entry.timestamp().toString() << ")" << endl; dbg.nospace() << "LogEntry (" << entry.timestamp().toString() << ")" << endl;
dbg.nospace() << " time stamp: " << entry.timestamp().toTime_t() << endl; dbg.nospace() << " time stamp: " << entry.timestamp().toTime_t() << endl;
dbg.nospace() << " DeviceId: " << entry.deviceId().toString() << endl; dbg.nospace() << " DeviceId: " << entry.deviceId().toString() << endl;
dbg.nospace() << " type id: " << entry.typeId().toString() << endl; dbg.nospace() << " type id: " << entry.typeId().toString() << endl;
dbg.nospace() << " source: " << JsonTypes::loggingSourceToString(entry.source()) << endl; metaEnum = QMetaEnum::fromType<Logging::LoggingSource>();
dbg.nospace() << " level: " << JsonTypes::loggingLevelToString(entry.level()) << endl; dbg.nospace() << " source: " << metaEnum.valueToKey(entry.source()) << endl;
dbg.nospace() << " eventType: " << JsonTypes::loggingEventTypeToString(entry.eventType()) << endl; metaEnum = QMetaEnum::fromType<Logging::LoggingLevel>();
dbg.nospace() << " level: " << metaEnum.valueToKey(entry.level()) << endl;
metaEnum = QMetaEnum::fromType<Logging::LoggingEventType>();
dbg.nospace() << " eventType: " << metaEnum.valueToKey(entry.eventType()) << endl;
dbg.nospace() << " error code: " << entry.errorCode() << endl; dbg.nospace() << " error code: " << entry.errorCode() << endl;
dbg.nospace() << " active: " << entry.active() << endl; dbg.nospace() << " active: " << entry.active() << endl;
dbg.nospace() << " value: " << entry.value() << endl; dbg.nospace() << " value: " << entry.value() << endl;

View File

@ -112,6 +112,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
hasError = true; 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)) { if (!verifyDuplicateUuid(m_pluginId)) {
m_validationErrors.append("Plugin \"" + m_pluginName + "\" has duplicate UUID: " + m_pluginId.toString()); m_validationErrors.append("Plugin \"" + m_pluginName + "\" has duplicate UUID: " + m_pluginId.toString());
hasError = true; hasError = true;
@ -153,6 +157,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
hasError = true; hasError = true;
} }
if (vendorId.isNull()) {
m_validationErrors.append("Vendor \"" + vendorName + "\" has invalid UUID: " + vendorObject.value("id").toString());
hasError = true;
}
if (!verifyDuplicateUuid(vendorId)) { if (!verifyDuplicateUuid(vendorId)) {
m_validationErrors.append("Vendor \"" + vendorName + "\" has duplicate UUID: " + vendorId.toString()); m_validationErrors.append("Vendor \"" + vendorName + "\" has duplicate UUID: " + vendorId.toString());
hasError = true; hasError = true;
@ -193,6 +201,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
hasError = true; hasError = true;
} }
if (deviceClassId.isNull()) {
m_validationErrors.append("Device class \"" + deviceClassName + "\" has invalid UUID: " + deviceClassObject.value("id").toString());
hasError = true;
}
if (!verifyDuplicateUuid(deviceClassId)) { if (!verifyDuplicateUuid(deviceClassId)) {
m_validationErrors.append("Device class \"" + deviceClassName + "\" has duplicate UUID: " + deviceClassName); m_validationErrors.append("Device class \"" + deviceClassName + "\" has duplicate UUID: " + deviceClassName);
hasError = true; hasError = true;
@ -316,6 +328,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
hasError = true; 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)) { if (!verifyDuplicateUuid(stateTypeId)) {
m_validationErrors.append("Device class \"" + deviceClass.name() + "\" state type \"" + stateTypeName + "\" has duplicate UUID: " + stateTypeId.toString()); m_validationErrors.append("Device class \"" + deviceClass.name() + "\" state type \"" + stateTypeName + "\" has duplicate UUID: " + stateTypeId.toString());
hasError = true; hasError = true;
@ -408,6 +424,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
hasError = true; 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)) { if (!verifyDuplicateUuid(actionTypeId)) {
m_validationErrors.append("Device class \"" + deviceClass.name() + "\" action type \"" + actionTypeName + "\" has duplicate UUID: " + actionTypeId.toString()); m_validationErrors.append("Device class \"" + deviceClass.name() + "\" action type \"" + actionTypeName + "\" has duplicate UUID: " + actionTypeId.toString());
hasError = true; hasError = true;
@ -452,6 +472,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
hasError = true; 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)) { if (!verifyDuplicateUuid(eventTypeId)) {
m_validationErrors.append("Device class \"" + deviceClass.name() + "\" event type \"" + eventTypeName + "\" has duplicate UUID: " + eventTypeId.toString()); m_validationErrors.append("Device class \"" + deviceClass.name() + "\" event type \"" + eventTypeName + "\" has duplicate UUID: " + eventTypeId.toString());
hasError = true; hasError = true;
@ -493,6 +517,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
hasError = true; 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)) { if (!verifyDuplicateUuid(actionTypeId)) {
m_validationErrors.append("Device class \"" + deviceClass.name() + "\" browser action type \"" + actionTypeName + "\" has duplicate UUID: " + actionTypeId.toString()); m_validationErrors.append("Device class \"" + deviceClass.name() + "\" browser action type \"" + actionTypeName + "\" has duplicate UUID: " + actionTypeId.toString());
hasError = true; hasError = true;
@ -710,6 +738,10 @@ QPair<bool, ParamTypes> PluginMetadata::parseParamTypes(const QJsonArray &array)
hasErrors = true; hasErrors = true;
} }
if (paramTypeId.isNull()) {
m_validationErrors.append("Param type \"" + paramName + "\" has invalid UUID: " + pt.value("id").toString());
hasErrors = true;
}
if (!verifyDuplicateUuid(paramTypeId)) { if (!verifyDuplicateUuid(paramTypeId)) {
m_validationErrors.append("Param type \"" + paramName + "\" has duplicate UUID: " + paramTypeId.toString()); m_validationErrors.append("Param type \"" + paramName + "\" has duplicate UUID: " + paramTypeId.toString());
hasErrors = true; hasErrors = true;

View File

@ -0,0 +1,134 @@
#include "jsonhandler.h"
#include "loggingcategories.h"
#include <QDebug>
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<BasicType>();
// 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 &params, 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 &params, 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<JsonHandler*>(this), data);
}
JsonReply *JsonHandler::createAsyncReply(const QString &method) const
{
return JsonReply::createAsyncReply(const_cast<JsonHandler*>(this), method);
}

View File

@ -0,0 +1,99 @@
#ifndef JSONHANDLER_H
#define JSONHANDLER_H
#include <QObject>
#include <QVariantMap>
#include <QMetaMethod>
#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<typename T> static QString enumRef();
static QString objectRef(const QString &objectName);
template<typename T> static QString enumValueName(T value);
template<typename T> static T enumNameToValue(const QString &name);
static BasicType variantTypeToBasicType(QVariant::Type variantType);
static QVariant::Type basicTypeToVariantType(BasicType basicType);
protected:
template <typename T> void registerEnum();
void registerObject(const QString &name, const QVariantMap &object);
void registerMethod(const QString &name, const QString &description, const QVariantMap &params, const QVariantMap &returns, bool deprecated = false);
void registerNotification(const QString &name, const QString &description, const QVariantMap &params, 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<typename T>
void JsonHandler::registerEnum()
{
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
QStringList values;
for (int i = 0; i < metaEnum.keyCount(); i++) {
values << metaEnum.key(i);
}
m_enums.insert(metaEnum.name(), values);
}
template<typename T>
QString JsonHandler::enumRef()
{
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
return QString("$ref:%1").arg(metaEnum.name());
}
template<typename T>
QString JsonHandler::enumValueName(T value)
{
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
return metaEnum.valueToKey(value);
}
template<typename T>
T JsonHandler::enumNameToValue(const QString &name)
{
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
return static_cast<T>(metaEnum.keyToValue(name.toUtf8()));
}
#endif // JSONHANDLER_H

View File

@ -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;
}

View File

@ -0,0 +1,62 @@
#ifndef JSONREPLY_H
#define JSONREPLY_H
#include <QObject>
#include <QVariantMap>
#include <QUuid>
#include <QTimer>
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

View File

@ -24,6 +24,8 @@ HEADERS += \
devices/devicepairinginfo.h \ devices/devicepairinginfo.h \
devices/deviceactioninfo.h \ devices/deviceactioninfo.h \
devices/browseresult.h \ devices/browseresult.h \
jsonrpc/jsonhandler.h \
jsonrpc/jsonreply.h \
libnymea.h \ libnymea.h \
platform/package.h \ platform/package.h \
platform/repository.h \ platform/repository.h \
@ -98,6 +100,8 @@ SOURCES += \
devices/devicepairinginfo.cpp \ devices/devicepairinginfo.cpp \
devices/deviceactioninfo.cpp \ devices/deviceactioninfo.cpp \
devices/browseresult.cpp \ devices/browseresult.cpp \
jsonrpc/jsonhandler.cpp \
jsonrpc/jsonreply.cpp \
loggingcategories.cpp \ loggingcategories.cpp \
nymeasettings.cpp \ nymeasettings.cpp \
platform/package.cpp \ platform/package.cpp \

View File

@ -279,7 +279,7 @@
], ],
"actionTypes": [ "actionTypes": [
{ {
"id": "e6a22f52-1818-46a7-9d15-5ca08b0612c", "id": "07cd8d5f-2f65-4955-b1f9-05d7f4da488a",
"name": "withParams", "name": "withParams",
"displayName": "Mock Action 1 (with params)", "displayName": "Mock Action 1 (with params)",
"paramTypes": [ "paramTypes": [

View File

@ -69,7 +69,7 @@ ParamTypeId mockDeviceAutoBoolValueEventBoolValueParamTypeId = ParamTypeId("{978
EventTypeId mockDeviceAutoEvent1EventTypeId = EventTypeId("{00f81fca-26f1-4a84-aa2b-4c6a3d953ec6}"); EventTypeId mockDeviceAutoEvent1EventTypeId = EventTypeId("{00f81fca-26f1-4a84-aa2b-4c6a3d953ec6}");
EventTypeId mockDeviceAutoEvent2EventTypeId = EventTypeId("{6e27922d-aa9d-44d1-b9b4-9faf31b6bd97}"); EventTypeId mockDeviceAutoEvent2EventTypeId = EventTypeId("{6e27922d-aa9d-44d1-b9b4-9faf31b6bd97}");
ParamTypeId mockDeviceAutoEvent2EventIntParamParamTypeId = ParamTypeId("{12ed5a15-96b4-4381-9d9c-a24875283d4f}"); 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 mockDeviceAutoWithParamsActionMockActionParam1ParamTypeId = ParamTypeId("{b8126ba6-3a54-45a3-be4d-63feb0ddb77b}");
ParamTypeId mockDeviceAutoWithParamsActionMockActionParam2ParamTypeId = ParamTypeId("{df41ba71-e43b-4854-91d1-b19d8066d4f9}"); ParamTypeId mockDeviceAutoWithParamsActionMockActionParam2ParamTypeId = ParamTypeId("{df41ba71-e43b-4854-91d1-b19d8066d4f9}");
ActionTypeId mockDeviceAutoMockActionNoParmsActionTypeId = ActionTypeId("{ef518d53-50e2-4ca5-a4b1-e9a8b9309d44}"); 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}) //: The name of the ParamType (DeviceClass: mockInputType, Type: device, ID: {a8494faf-3a0f-4cf3-84b7-4b39148a838d})
QT_TRANSLATE_NOOP("mockDevice", "Mail address"), 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)"), QT_TRANSLATE_NOOP("mockDevice", "Mock Action 1 (with params)"),
//: The name of the ActionType ({dea0f4e1-65e3-4981-8eaa-2701c53a9185}) of DeviceClass mock //: The name of the ActionType ({dea0f4e1-65e3-4981-8eaa-2701c53a9185}) of DeviceClass mock

View File

@ -20,6 +20,7 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "nymeatestbase.h" #include "nymeatestbase.h"
#include "devices/device.h"
using namespace nymeaserver; using namespace nymeaserver;
@ -75,7 +76,7 @@ void TestActions::executeAction()
params.insert("params", actionParams); params.insert("params", actionParams);
QVariant response = injectAndWait("Actions.ExecuteAction", params); QVariant response = injectAndWait("Actions.ExecuteAction", params);
qDebug() << "executeActionresponse" << response; qDebug() << "executeActionresponse" << response;
verifyDeviceError(response, error); verifyError(response, "deviceError", enumValueName(error));
// Fetch action execution history from mock device // Fetch action execution history from mock device
QNetworkAccessManager nam; QNetworkAccessManager nam;
@ -132,7 +133,7 @@ void TestActions::getActionType()
params.insert("actionTypeId", actionTypeId.toString()); params.insert("actionTypeId", actionTypeId.toString());
QVariant response = injectAndWait("Actions.GetActionType", params); QVariant response = injectAndWait("Actions.GetActionType", params);
verifyDeviceError(response, error); verifyError(response, "deviceError", enumValueName(error));
if (error == Device::DeviceErrorNoError) { 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."); 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.");

View File

@ -30,6 +30,11 @@ class TestConfigurations: public NymeaTestBase
{ {
Q_OBJECT Q_OBJECT
private:
inline void verifyConfigurationError(const QVariant &response, NymeaConfiguration::ConfigurationError error = NymeaConfiguration::ConfigurationErrorNoError) {
verifyError(response, "configurationError", enumValueName(error));
}
protected slots: protected slots:
void initTestCase(); void initTestCase();

View File

@ -35,6 +35,10 @@ class TestDevices : public NymeaTestBase
private: private:
DeviceId m_mockDeviceAsyncId; DeviceId m_mockDeviceAsyncId;
inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) {
verifyError(response, "deviceError", enumValueName(error));
}
private slots: private slots:
void initTestCase(); void initTestCase();
@ -832,7 +836,7 @@ void TestDevices::getStateValue()
params.insert("stateTypeId", stateTypeId); params.insert("stateTypeId", stateTypeId);
QVariant response = injectAndWait("Devices.GetStateValue", params); 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) { if (statusCode == Device::DeviceErrorNoError) {
QVariant value = response.toMap().value("params").toMap().value("value"); QVariant value = response.toMap().value("params").toMap().value("value");
QCOMPARE(value.toInt(), 10); // Mock device has value 10 by default... QCOMPARE(value.toInt(), 10); // Mock device has value 10 by default...
@ -857,7 +861,7 @@ void TestDevices::getStateValues()
params.insert("deviceId", deviceId); params.insert("deviceId", deviceId);
QVariant response = injectAndWait("Devices.GetStateValues", params); 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) { if (statusCode == Device::DeviceErrorNoError) {
QVariantList values = response.toMap().value("params").toMap().value("values").toList(); QVariantList values = response.toMap().value("params").toMap().value("values").toList();
QCOMPARE(values.count(), 6); // Mock device has 6 states... QCOMPARE(values.count(), 6); // Mock device has 6 states...

View File

@ -128,7 +128,7 @@ void TestEvents::getEventType()
params.insert("eventTypeId", eventTypeId.toString()); params.insert("eventTypeId", eventTypeId.toString());
QVariant response = injectAndWait("Events.GetEventType", params); QVariant response = injectAndWait("Events.GetEventType", params);
verifyDeviceError(response, error); verifyError(response, "deviceError", enumValueName(error));
if (error == Device::DeviceErrorNoError) { 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."); 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.");

View File

@ -23,6 +23,7 @@
#include "../../utils/pushbuttonagent.h" #include "../../utils/pushbuttonagent.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "servers/mocktcpserver.h" #include "servers/mocktcpserver.h"
#include "usermanager/usermanager.h"
using namespace nymeaserver; using namespace nymeaserver;
@ -30,6 +31,14 @@ class TestJSONRPC: public NymeaTestBase
{ {
Q_OBJECT 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: private slots:
void initTestCase(); void initTestCase();
@ -714,7 +723,7 @@ void TestJSONRPC::ruleAddedRemovedNotifications()
QVariantMap stateDescriptor; QVariantMap stateDescriptor;
stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor.insert("deviceId", m_mockDeviceId); stateDescriptor.insert("deviceId", m_mockDeviceId);
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess));
stateDescriptor.insert("value", "20"); stateDescriptor.insert("value", "20");
QVariantMap stateEvaluator; QVariantMap stateEvaluator;
@ -778,7 +787,7 @@ void TestJSONRPC::ruleActiveChangedNotifications()
QVariantMap stateDescriptor; QVariantMap stateDescriptor;
stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor.insert("deviceId", m_mockDeviceId); stateDescriptor.insert("deviceId", m_mockDeviceId);
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptor.insert("value", "20"); stateDescriptor.insert("value", "20");
QVariantMap stateEvaluator; QVariantMap stateEvaluator;

View File

@ -35,6 +35,13 @@ class TestLogging : public NymeaTestBase
private: 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: private slots:
void initTestCase(); void initTestCase();
@ -148,8 +155,8 @@ void TestLogging::systemLogs()
{ {
// check the active system log at boot // check the active system log at boot
QVariantMap params; QVariantMap params;
params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceSystem)); params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceSystem));
params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeActiveChange)); params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeActiveChange));
// there should be 2 logs, one for shutdown, one for startup (from server restart) // there should be 2 logs, one for shutdown, one for startup (from server restart)
QVariant response = injectAndWait("Logging.GetLogEntries", params); QVariant response = injectAndWait("Logging.GetLogEntries", params);
@ -166,15 +173,15 @@ void TestLogging::systemLogs()
} }
QCOMPARE(logEntryShutdown.value("active").toBool(), false); QCOMPARE(logEntryShutdown.value("active").toBool(), false);
QCOMPARE(logEntryShutdown.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeActiveChange)); QCOMPARE(logEntryShutdown.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeActiveChange));
QCOMPARE(logEntryShutdown.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceSystem)); QCOMPARE(logEntryShutdown.value("source").toString(), enumValueName(Logging::LoggingSourceSystem));
QCOMPARE(logEntryShutdown.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); QCOMPARE(logEntryShutdown.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo));
QCOMPARE(logEntryStartup.value("active").toBool(), true); QCOMPARE(logEntryStartup.value("active").toBool(), true);
QCOMPARE(logEntryStartup.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeActiveChange)); QCOMPARE(logEntryStartup.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeActiveChange));
QCOMPARE(logEntryStartup.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceSystem)); QCOMPARE(logEntryStartup.value("source").toString(), enumValueName(Logging::LoggingSourceSystem));
QCOMPARE(logEntryStartup.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); QCOMPARE(logEntryStartup.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo));
} }
void TestLogging::invalidFilter_data() void TestLogging::invalidFilter_data()
@ -189,7 +196,7 @@ void TestLogging::invalidFilter_data()
invalidTypeIds.insert("typeId", QVariantList() << "bla" << "blub"); invalidTypeIds.insert("typeId", QVariantList() << "bla" << "blub");
QVariantMap invalidEventTypes; QVariantMap invalidEventTypes;
invalidEventTypes.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger) << "blub"); invalidEventTypes.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger) << "blub");
QTest::addColumn<QVariantMap>("filter"); QTest::addColumn<QVariantMap>("filter");
@ -247,9 +254,9 @@ void TestLogging::eventLogs()
found = true; found = true;
// Make sure the notification contains all the stuff we expect // Make sure the notification contains all the stuff we expect
QCOMPARE(logEntry.value("typeId").toString(), mockEvent1EventTypeId.toString()); QCOMPARE(logEntry.value("typeId").toString(), mockEvent1EventTypeId.toString());
QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger));
QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceEvents));
QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo));
break; break;
} }
} }
@ -261,8 +268,8 @@ void TestLogging::eventLogs()
// get this logentry with filter // get this logentry with filter
QVariantMap params; QVariantMap params;
params.insert("deviceIds", QVariantList() << device->id()); params.insert("deviceIds", QVariantList() << device->id());
params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents)); params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceEvents));
params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger));
params.insert("typeIds", QVariantList() << mockEvent1EventTypeId); params.insert("typeIds", QVariantList() << mockEvent1EventTypeId);
QVariant response = injectAndWait("Logging.GetLogEntries", params); QVariant response = injectAndWait("Logging.GetLogEntries", params);
@ -317,9 +324,9 @@ void TestLogging::actionLog()
found = true; found = true;
// Make sure the notification contains all the stuff we expect // Make sure the notification contains all the stuff we expect
QCOMPARE(logEntry.value("typeId").toString(), mockWithParamsActionTypeId.toString()); QCOMPARE(logEntry.value("typeId").toString(), mockWithParamsActionTypeId.toString());
QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger));
QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions));
QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelInfo));
break; break;
} }
} }
@ -343,8 +350,8 @@ void TestLogging::actionLog()
// get this logentry with filter // get this logentry with filter
params.clear(); params.clear();
params.insert("deviceIds", QVariantList() << m_mockDeviceId); params.insert("deviceIds", QVariantList() << m_mockDeviceId);
params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions));
params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger));
// FIXME: currently is filtering for values not supported // FIXME: currently is filtering for values not supported
//params.insert("values", QVariantList() << "7, true"); //params.insert("values", QVariantList() << "7, true");
@ -376,10 +383,10 @@ void TestLogging::actionLog()
found = true; found = true;
// Make sure the notification contains all the stuff we expect // Make sure the notification contains all the stuff we expect
QCOMPARE(logEntry.value("typeId").toString(), mockFailingActionTypeId.toString()); QCOMPARE(logEntry.value("typeId").toString(), mockFailingActionTypeId.toString());
QCOMPARE(logEntry.value("eventType").toString(), JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); QCOMPARE(logEntry.value("eventType").toString(), enumValueName(Logging::LoggingEventTypeTrigger));
QCOMPARE(logEntry.value("source").toString(), JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); QCOMPARE(logEntry.value("source").toString(), enumValueName(Logging::LoggingSourceActions));
QCOMPARE(logEntry.value("loggingLevel").toString(), JsonTypes::loggingLevelToString(Logging::LoggingLevelAlert)); QCOMPARE(logEntry.value("loggingLevel").toString(), enumValueName(Logging::LoggingLevelAlert));
QCOMPARE(logEntry.value("errorCode").toString(), JsonTypes::deviceErrorToString(Device::DeviceErrorSetupFailed)); QCOMPARE(logEntry.value("errorCode").toString(), enumValueName(Device::DeviceErrorSetupFailed));
break; break;
} }
} }
@ -391,8 +398,8 @@ void TestLogging::actionLog()
// get this logentry with filter // get this logentry with filter
params.clear(); params.clear();
params.insert("deviceIds", QVariantList() << m_mockDeviceId); params.insert("deviceIds", QVariantList() << m_mockDeviceId);
params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions));
params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger));
// FIXME: filter for values currently not working // FIXME: filter for values currently not working
//params.insert("values", QVariantList() << "7, true"); //params.insert("values", QVariantList() << "7, true");
@ -406,8 +413,8 @@ void TestLogging::actionLog()
// check different filters // check different filters
params.clear(); params.clear();
params.insert("deviceIds", QVariantList() << m_mockDeviceId); params.insert("deviceIds", QVariantList() << m_mockDeviceId);
params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions));
params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger));
params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId); params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId);
response = injectAndWait("Logging.GetLogEntries", params); response = injectAndWait("Logging.GetLogEntries", params);
@ -418,8 +425,8 @@ void TestLogging::actionLog()
params.clear(); params.clear();
params.insert("deviceIds", QVariantList() << m_mockDeviceId); params.insert("deviceIds", QVariantList() << m_mockDeviceId);
params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions)); params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions));
params.insert("eventTypes", QVariantList() << JsonTypes::loggingEventTypeToString(Logging::LoggingEventTypeTrigger)); params.insert("eventTypes", QVariantList() << enumValueName(Logging::LoggingEventTypeTrigger));
params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId << mockWithParamsActionTypeId << mockFailingActionTypeId); params.insert("typeIds", QVariantList() << mockWithoutParamsActionTypeId << mockWithParamsActionTypeId << mockFailingActionTypeId);
response = injectAndWait("Logging.GetLogEntries", params); response = injectAndWait("Logging.GetLogEntries", params);
@ -447,11 +454,11 @@ void TestLogging::deviceLogs()
// get this logentry with filter // get this logentry with filter
params.clear(); params.clear();
params.insert("deviceIds", QVariantList() << m_mockDeviceId << deviceId); params.insert("deviceIds", QVariantList() << m_mockDeviceId << deviceId);
params.insert("loggingSources", QVariantList() << JsonTypes::loggingSourceToString(Logging::LoggingSourceActions) params.insert("loggingSources", QVariantList() << enumValueName(Logging::LoggingSourceActions)
<< JsonTypes::loggingSourceToString(Logging::LoggingSourceEvents) << enumValueName(Logging::LoggingSourceEvents)
<< JsonTypes::loggingSourceToString(Logging::LoggingSourceStates)); << enumValueName(Logging::LoggingSourceStates));
params.insert("loggingLevels", QVariantList() << JsonTypes::loggingLevelToString(Logging::LoggingLevelInfo) params.insert("loggingLevels", QVariantList() << enumValueName(Logging::LoggingLevelInfo)
<< JsonTypes::loggingLevelToString(Logging::LoggingLevelAlert)); << enumValueName(Logging::LoggingLevelAlert));
params.insert("values", QVariantList() << "7, true" << "9, false"); params.insert("values", QVariantList() << "7, true" << "9, false");
QVariantMap timeFilter; QVariantMap timeFilter;
@ -539,14 +546,14 @@ void TestLogging::testDoubleValues()
if (logNotification.value("typeId").toString() == mockDisplayPinDoubleActionDoubleParamTypeId.toString()) { if (logNotification.value("typeId").toString() == mockDisplayPinDoubleActionDoubleParamTypeId.toString()) {
// If state source // 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(); QString logValue = logNotification.value("value").toString();
qDebug() << QString::number(value) << logValue; qDebug() << QString::number(value) << logValue;
QCOMPARE(logValue, QString::number(value)); QCOMPARE(logValue, QString::number(value));
} }
// If action source notification // 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(); QString logValue = logNotification.value("value").toString();
qDebug() << QString::number(value) << logValue; qDebug() << QString::number(value) << logValue;
QCOMPARE(logValue, QString::number(value)); QCOMPARE(logValue, QString::number(value));

View File

@ -23,6 +23,7 @@
#include "nymeasettings.h" #include "nymeasettings.h"
#include "servers/mocktcpserver.h" #include "servers/mocktcpserver.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "jsonrpc/jsonhandler.h"
using namespace nymeaserver; using namespace nymeaserver;
@ -49,6 +50,13 @@ private:
void generateEvent(const EventTypeId &eventTypeId); 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: private slots:
void initTestCase(); void initTestCase();
@ -331,13 +339,13 @@ QVariant TestRules::validIntStateBasedRule(const QString &name, const bool &exec
QVariantMap stateDescriptor; QVariantMap stateDescriptor;
stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor.insert("deviceId", m_mockDeviceId); stateDescriptor.insert("deviceId", m_mockDeviceId);
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess));
stateDescriptor.insert("value", 25); stateDescriptor.insert("value", 25);
// StateEvaluator // StateEvaluator
QVariantMap stateEvaluator; QVariantMap stateEvaluator;
stateEvaluator.insert("stateDescriptor", stateDescriptor); stateEvaluator.insert("stateDescriptor", stateDescriptor);
stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd));
// RuleAction // RuleAction
QVariantMap action; QVariantMap action;
@ -423,13 +431,13 @@ void TestRules::addRemoveRules_data()
QVariantMap stateDescriptor; QVariantMap stateDescriptor;
stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor.insert("deviceId", m_mockDeviceId); stateDescriptor.insert("deviceId", m_mockDeviceId);
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess));
stateDescriptor.insert("value", 20); stateDescriptor.insert("value", 20);
// StateEvaluator // StateEvaluator
QVariantMap validStateEvaluator; QVariantMap validStateEvaluator;
validStateEvaluator.insert("stateDescriptor", stateDescriptor); validStateEvaluator.insert("stateDescriptor", stateDescriptor);
validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); validStateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap invalidStateEvaluator; QVariantMap invalidStateEvaluator;
stateDescriptor.remove("deviceId"); stateDescriptor.remove("deviceId");
@ -448,7 +456,7 @@ void TestRules::addRemoveRules_data()
QVariantMap param1; QVariantMap param1;
param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId);
param1.insert("value", 3); param1.insert("value", 3);
param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); param1.insert("operator", enumValueName(Types::ValueOperatorEquals));
params.append(param1); params.append(param1);
validEventDescriptor2.insert("paramDescriptors", params); validEventDescriptor2.insert("paramDescriptors", params);
@ -667,13 +675,13 @@ void TestRules::editRules_data()
QVariantMap stateDescriptor; QVariantMap stateDescriptor;
stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor.insert("deviceId", m_mockDeviceId); stateDescriptor.insert("deviceId", m_mockDeviceId);
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorLess)); stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorLess));
stateDescriptor.insert("value", 20); stateDescriptor.insert("value", 20);
// StateEvaluator // StateEvaluator
QVariantMap validStateEvaluator; QVariantMap validStateEvaluator;
validStateEvaluator.insert("stateDescriptor", stateDescriptor); validStateEvaluator.insert("stateDescriptor", stateDescriptor);
validStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); validStateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap invalidStateEvaluator; QVariantMap invalidStateEvaluator;
stateDescriptor.remove("deviceId"); stateDescriptor.remove("deviceId");
@ -692,7 +700,7 @@ void TestRules::editRules_data()
QVariantMap param1; QVariantMap param1;
param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); param1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId);
param1.insert("value", 3); param1.insert("value", 3);
param1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); param1.insert("operator", enumValueName(Types::ValueOperatorEquals));
params.append(param1); params.append(param1);
validEventDescriptor2.insert("paramDescriptors", params); validEventDescriptor2.insert("paramDescriptors", params);
@ -807,7 +815,7 @@ void TestRules::editRules()
QVariantMap eventParam1; QVariantMap eventParam1;
eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId);
eventParam1.insert("value", 3); eventParam1.insert("value", 3);
eventParam1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); eventParam1.insert("operator", enumValueName(Types::ValueOperatorEquals));
eventParamDescriptors.append(eventParam1); eventParamDescriptors.append(eventParam1);
eventDescriptor2.insert("paramDescriptors", eventParamDescriptors); eventDescriptor2.insert("paramDescriptors", eventParamDescriptors);
@ -818,25 +826,25 @@ void TestRules::editRules()
QVariantMap stateEvaluator0; QVariantMap stateEvaluator0;
QVariantMap stateDescriptor1; QVariantMap stateDescriptor1;
stateDescriptor1.insert("deviceId", m_mockDeviceId); stateDescriptor1.insert("deviceId", m_mockDeviceId);
stateDescriptor1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptor1.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptor1.insert("stateTypeId", mockIntStateTypeId); stateDescriptor1.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor1.insert("value", 1); stateDescriptor1.insert("value", 1);
QVariantMap stateDescriptor2; QVariantMap stateDescriptor2;
stateDescriptor2.insert("deviceId", m_mockDeviceId); stateDescriptor2.insert("deviceId", m_mockDeviceId);
stateDescriptor2.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptor2.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptor2.insert("stateTypeId", mockBoolStateTypeId); stateDescriptor2.insert("stateTypeId", mockBoolStateTypeId);
stateDescriptor2.insert("value", true); stateDescriptor2.insert("value", true);
QVariantMap stateEvaluator1; QVariantMap stateEvaluator1;
stateEvaluator1.insert("stateDescriptor", stateDescriptor1); stateEvaluator1.insert("stateDescriptor", stateDescriptor1);
stateEvaluator1.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator1.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap stateEvaluator2; QVariantMap stateEvaluator2;
stateEvaluator2.insert("stateDescriptor", stateDescriptor2); stateEvaluator2.insert("stateDescriptor", stateDescriptor2);
stateEvaluator2.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator2.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantList childEvaluators; QVariantList childEvaluators;
childEvaluators.append(stateEvaluator1); childEvaluators.append(stateEvaluator1);
childEvaluators.append(stateEvaluator2); childEvaluators.append(stateEvaluator2);
stateEvaluator0.insert("childEvaluators", childEvaluators); stateEvaluator0.insert("childEvaluators", childEvaluators);
stateEvaluator0.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator0.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap action1; QVariantMap action1;
action1.insert("actionTypeId", mockWithoutParamsActionTypeId); action1.insert("actionTypeId", mockWithoutParamsActionTypeId);
@ -1103,7 +1111,7 @@ void TestRules::loadStoreConfig()
QVariantMap eventParam1; QVariantMap eventParam1;
eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId); eventParam1.insert("paramTypeId", mockEvent2EventIntParamParamTypeId);
eventParam1.insert("value", 3); eventParam1.insert("value", 3);
eventParam1.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); eventParam1.insert("operator", enumValueName(Types::ValueOperatorEquals));
eventParamDescriptors.append(eventParam1); eventParamDescriptors.append(eventParam1);
eventDescriptor2.insert("paramDescriptors", eventParamDescriptors); eventDescriptor2.insert("paramDescriptors", eventParamDescriptors);
@ -1116,38 +1124,38 @@ void TestRules::loadStoreConfig()
QVariantMap stateDescriptor2; QVariantMap stateDescriptor2;
stateDescriptor2.insert("deviceId", m_mockDeviceId); stateDescriptor2.insert("deviceId", m_mockDeviceId);
stateDescriptor2.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptor2.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptor2.insert("stateTypeId", mockIntStateTypeId); stateDescriptor2.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor2.insert("value", 1); stateDescriptor2.insert("value", 1);
QVariantMap stateEvaluator2; QVariantMap stateEvaluator2;
stateEvaluator2.insert("stateDescriptor", stateDescriptor2); stateEvaluator2.insert("stateDescriptor", stateDescriptor2);
stateEvaluator2.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator2.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap stateDescriptor3; QVariantMap stateDescriptor3;
stateDescriptor3.insert("deviceId", m_mockDeviceId); stateDescriptor3.insert("deviceId", m_mockDeviceId);
stateDescriptor3.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptor3.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptor3.insert("stateTypeId", mockBoolStateTypeId); stateDescriptor3.insert("stateTypeId", mockBoolStateTypeId);
stateDescriptor3.insert("value", true); stateDescriptor3.insert("value", true);
QVariantMap stateEvaluator3; QVariantMap stateEvaluator3;
stateEvaluator3.insert("stateDescriptor", stateDescriptor3); stateEvaluator3.insert("stateDescriptor", stateDescriptor3);
stateEvaluator3.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator3.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap stateDescriptor4; QVariantMap stateDescriptor4;
stateDescriptor4.insert("interface", "battery"); stateDescriptor4.insert("interface", "battery");
stateDescriptor4.insert("interfaceState", "batteryCritical"); stateDescriptor4.insert("interfaceState", "batteryCritical");
stateDescriptor4.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptor4.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptor4.insert("value", true); stateDescriptor4.insert("value", true);
QVariantMap stateEvaluator4; QVariantMap stateEvaluator4;
stateEvaluator4.insert("stateDescriptor", stateDescriptor4); stateEvaluator4.insert("stateDescriptor", stateDescriptor4);
stateEvaluator4.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator4.insert("operator", enumValueName(Types::StateOperatorAnd));
childEvaluators.append(stateEvaluator2); childEvaluators.append(stateEvaluator2);
childEvaluators.append(stateEvaluator3); childEvaluators.append(stateEvaluator3);
childEvaluators.append(stateEvaluator4); childEvaluators.append(stateEvaluator4);
stateEvaluator1.insert("childEvaluators", childEvaluators); stateEvaluator1.insert("childEvaluators", childEvaluators);
stateEvaluator1.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator1.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap action1; QVariantMap action1;
action1.insert("actionTypeId", mockWithoutParamsActionTypeId); action1.insert("actionTypeId", mockWithoutParamsActionTypeId);
@ -1657,7 +1665,7 @@ void TestRules::testStateChange() {
QVariantMap stateEvaluator; QVariantMap stateEvaluator;
QVariantMap stateDescriptor; QVariantMap stateDescriptor;
stateDescriptor.insert("deviceId", m_mockDeviceId); stateDescriptor.insert("deviceId", m_mockDeviceId);
stateDescriptor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorGreaterOrEqual)); stateDescriptor.insert("operator", enumValueName(Types::ValueOperatorGreaterOrEqual));
stateDescriptor.insert("stateTypeId", mockIntStateTypeId); stateDescriptor.insert("stateTypeId", mockIntStateTypeId);
stateDescriptor.insert("value", 42); stateDescriptor.insert("value", 42);
stateEvaluator.insert("stateDescriptor", stateDescriptor); stateEvaluator.insert("stateDescriptor", stateDescriptor);
@ -1884,38 +1892,38 @@ void TestRules::testChildEvaluator_data()
// Stateevaluators // Stateevaluators
QVariantMap stateDescriptorPercentage; QVariantMap stateDescriptorPercentage;
stateDescriptorPercentage.insert("deviceId", testDeviceId); stateDescriptorPercentage.insert("deviceId", testDeviceId);
stateDescriptorPercentage.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorGreaterOrEqual)); stateDescriptorPercentage.insert("operator", enumValueName(Types::ValueOperatorGreaterOrEqual));
stateDescriptorPercentage.insert("stateTypeId", mockDisplayPinPercentageStateTypeId); stateDescriptorPercentage.insert("stateTypeId", mockDisplayPinPercentageStateTypeId);
stateDescriptorPercentage.insert("value", 50); stateDescriptorPercentage.insert("value", 50);
QVariantMap stateDescriptorDouble; QVariantMap stateDescriptorDouble;
stateDescriptorDouble.insert("deviceId", testDeviceId); stateDescriptorDouble.insert("deviceId", testDeviceId);
stateDescriptorDouble.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptorDouble.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptorDouble.insert("stateTypeId", mockDisplayPinDoubleActionDoubleParamTypeId); stateDescriptorDouble.insert("stateTypeId", mockDisplayPinDoubleActionDoubleParamTypeId);
stateDescriptorDouble.insert("value", 20.5); stateDescriptorDouble.insert("value", 20.5);
QVariantMap stateDescriptorAllowedValues; QVariantMap stateDescriptorAllowedValues;
stateDescriptorAllowedValues.insert("deviceId", testDeviceId); stateDescriptorAllowedValues.insert("deviceId", testDeviceId);
stateDescriptorAllowedValues.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptorAllowedValues.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptorAllowedValues.insert("stateTypeId", mockDisplayPinAllowedValuesStateTypeId); stateDescriptorAllowedValues.insert("stateTypeId", mockDisplayPinAllowedValuesStateTypeId);
stateDescriptorAllowedValues.insert("value", "String value 2"); stateDescriptorAllowedValues.insert("value", "String value 2");
QVariantMap stateDescriptorColor; QVariantMap stateDescriptorColor;
stateDescriptorColor.insert("deviceId", testDeviceId); stateDescriptorColor.insert("deviceId", testDeviceId);
stateDescriptorColor.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptorColor.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptorColor.insert("stateTypeId", mockDisplayPinColorStateTypeId); stateDescriptorColor.insert("stateTypeId", mockDisplayPinColorStateTypeId);
stateDescriptorColor.insert("value", "#00FF00"); stateDescriptorColor.insert("value", "#00FF00");
QVariantMap firstStateEvaluator; QVariantMap firstStateEvaluator;
firstStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorOr)); firstStateEvaluator.insert("operator", enumValueName(Types::StateOperatorOr));
firstStateEvaluator.insert("childEvaluators", QVariantList() << createStateEvaluatorFromSingleDescriptor(stateDescriptorPercentage) << createStateEvaluatorFromSingleDescriptor(stateDescriptorDouble)); firstStateEvaluator.insert("childEvaluators", QVariantList() << createStateEvaluatorFromSingleDescriptor(stateDescriptorPercentage) << createStateEvaluatorFromSingleDescriptor(stateDescriptorDouble));
QVariantMap secondStateEvaluator; QVariantMap secondStateEvaluator;
secondStateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); secondStateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd));
secondStateEvaluator.insert("childEvaluators", QVariantList() << createStateEvaluatorFromSingleDescriptor(stateDescriptorAllowedValues) << createStateEvaluatorFromSingleDescriptor(stateDescriptorColor)); secondStateEvaluator.insert("childEvaluators", QVariantList() << createStateEvaluatorFromSingleDescriptor(stateDescriptorAllowedValues) << createStateEvaluatorFromSingleDescriptor(stateDescriptorColor));
QVariantMap stateEvaluator; QVariantMap stateEvaluator;
stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd));
stateEvaluator.insert("childEvaluators", QVariantList() << firstStateEvaluator << secondStateEvaluator); stateEvaluator.insert("childEvaluators", QVariantList() << firstStateEvaluator << secondStateEvaluator);
// The rule // The rule

View File

@ -73,7 +73,7 @@ void TestStates::getStateValue()
QVariant response = injectAndWait("Devices.GetStateValue", params); QVariant response = injectAndWait("Devices.GetStateValue", params);
verifyDeviceError(response, error); verifyError(response, "deviceError", enumValueName(error));
} }
void TestStates::save_load_states() void TestStates::save_load_states()

View File

@ -20,6 +20,7 @@
#include "nymeatestbase.h" #include "nymeatestbase.h"
#include "servers/mocktcpserver.h" #include "servers/mocktcpserver.h"
#include "tagging/tagsstorage.h"
using namespace nymeaserver; using namespace nymeaserver;
@ -27,6 +28,11 @@ class TestTags: public NymeaTestBase
{ {
Q_OBJECT Q_OBJECT
private:
inline void verifyTagError(const QVariant &response, TagsStorage::TagError error = TagsStorage::TagErrorNoError) {
verifyError(response, "tagError", enumValueName(error));
}
private slots: private slots:
void addTag_data(); void addTag_data();
void addTag(); void addTag();

View File

@ -29,6 +29,11 @@ class TestTimeManager: public NymeaTestBase
{ {
Q_OBJECT Q_OBJECT
private:
inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) {
verifyError(response, "ruleError", enumValueName(error));
}
private slots: private slots:
void initTestCase(); void initTestCase();
@ -1078,25 +1083,25 @@ void TestTimeManager::testCalendarItemStates_data()
QVariantMap stateEvaluator; QVariantMap stateEvaluator;
QVariantMap stateDescriptorInt; QVariantMap stateDescriptorInt;
stateDescriptorInt.insert("deviceId", m_mockDeviceId); stateDescriptorInt.insert("deviceId", m_mockDeviceId);
stateDescriptorInt.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorGreaterOrEqual)); stateDescriptorInt.insert("operator", enumValueName(Types::ValueOperatorGreaterOrEqual));
stateDescriptorInt.insert("stateTypeId", mockIntStateTypeId); stateDescriptorInt.insert("stateTypeId", mockIntStateTypeId);
stateDescriptorInt.insert("value", 65); stateDescriptorInt.insert("value", 65);
QVariantMap stateDescriptorBool; QVariantMap stateDescriptorBool;
stateDescriptorBool.insert("deviceId", m_mockDeviceId); stateDescriptorBool.insert("deviceId", m_mockDeviceId);
stateDescriptorBool.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptorBool.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId); stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId);
stateDescriptorBool.insert("value", true); stateDescriptorBool.insert("value", true);
QVariantMap stateEvaluatorInt; QVariantMap stateEvaluatorInt;
stateEvaluatorInt.insert("stateDescriptor", stateDescriptorInt); stateEvaluatorInt.insert("stateDescriptor", stateDescriptorInt);
stateEvaluatorInt.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluatorInt.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantMap stateEvaluatorBool; QVariantMap stateEvaluatorBool;
stateEvaluatorBool.insert("stateDescriptor", stateDescriptorBool); stateEvaluatorBool.insert("stateDescriptor", stateDescriptorBool);
stateEvaluatorBool.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluatorBool.insert("operator", enumValueName(Types::StateOperatorAnd));
QVariantList childEvaluators; QVariantList childEvaluators;
childEvaluators.append(stateEvaluatorInt); childEvaluators.append(stateEvaluatorInt);
childEvaluators.append(stateEvaluatorBool); childEvaluators.append(stateEvaluatorBool);
stateEvaluator.insert("childEvaluators", childEvaluators); stateEvaluator.insert("childEvaluators", childEvaluators);
stateEvaluator.insert("operator", JsonTypes::stateOperatorToString(Types::StateOperatorAnd)); stateEvaluator.insert("operator", enumValueName(Types::StateOperatorAnd));
// The rule // The rule
@ -1246,7 +1251,7 @@ void TestTimeManager::testCalendarItemStatesEvent_data()
// State evaluator // State evaluator
QVariantMap stateDescriptorBool; QVariantMap stateDescriptorBool;
stateDescriptorBool.insert("deviceId", m_mockDeviceId); stateDescriptorBool.insert("deviceId", m_mockDeviceId);
stateDescriptorBool.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptorBool.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId); stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId);
stateDescriptorBool.insert("value", true); stateDescriptorBool.insert("value", true);
@ -1880,7 +1885,7 @@ void TestTimeManager::testEventItemStates_data()
// State evaluator // State evaluator
QVariantMap stateDescriptorBool; QVariantMap stateDescriptorBool;
stateDescriptorBool.insert("deviceId", m_mockDeviceId); stateDescriptorBool.insert("deviceId", m_mockDeviceId);
stateDescriptorBool.insert("operator", JsonTypes::valueOperatorToString(Types::ValueOperatorEquals)); stateDescriptorBool.insert("operator", enumValueName(Types::ValueOperatorEquals));
stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId); stateDescriptorBool.insert("stateTypeId", mockBoolStateTypeId);
stateDescriptorBool.insert("value", true); stateDescriptorBool.insert("value", true);
@ -2078,7 +2083,7 @@ void TestTimeManager::setIntState(const int &value)
params.insert("deviceId", m_mockDeviceId); params.insert("deviceId", m_mockDeviceId);
params.insert("stateTypeId", mockIntStateTypeId); params.insert("stateTypeId", mockIntStateTypeId);
QVariant response = injectAndWait("Devices.GetStateValue", params); QVariant response = injectAndWait("Devices.GetStateValue", params);
verifyDeviceError(response); verifyError(response, "deviceError", "DeviceErrorNoError");
int currentStateValue = response.toMap().value("params").toMap().value("value").toInt(); int currentStateValue = response.toMap().value("params").toMap().value("value").toInt();
bool shouldGetNotification = currentStateValue != value; bool shouldGetNotification = currentStateValue != value;
@ -2119,7 +2124,7 @@ void TestTimeManager::setBoolState(const bool &value)
params.insert("deviceId", m_mockDeviceId); params.insert("deviceId", m_mockDeviceId);
params.insert("stateTypeId", mockBoolStateTypeId); params.insert("stateTypeId", mockBoolStateTypeId);
QVariant response = injectAndWait("Devices.GetStateValue", params); QVariant response = injectAndWait("Devices.GetStateValue", params);
verifyDeviceError(response); verifyError(response, "deviceError", "DeviceErrorNoError");
bool currentStateValue = response.toMap().value("params").toMap().value("value").toBool(); bool currentStateValue = response.toMap().value("params").toMap().value("value").toBool();
bool shouldGetNotification = currentStateValue != value; bool shouldGetNotification = currentStateValue != value;

View File

@ -23,6 +23,7 @@
#include "logging/logengine.h" #include "logging/logengine.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "nymeatestbase.h" #include "nymeatestbase.h"
#include "usermanager/usermanager.h"
using namespace nymeaserver; using namespace nymeaserver;

View File

@ -586,7 +586,7 @@ void TestWebserver::getDebugServer()
QVariantMap params; QVariant response; QVariantMap params; QVariant response;
params.insert("enabled", serverEnabled); params.insert("enabled", serverEnabled);
response = injectAndWait("Configuration.SetDebugServerEnabled", params); response = injectAndWait("Configuration.SetDebugServerEnabled", params);
verifyConfigurationError(response); verifyError(response, "configurationError", "ConfigurationErrorNoError");
QNetworkAccessManager nam; QNetworkAccessManager nam;
bool ok = false; bool ok = false;

View File

@ -2,11 +2,12 @@
if [ -z $1 ]; then if [ -z $1 ]; then
echo "usage: $0 host" echo "usage: $0 host"
else exit 1
fi
cat <<EOD | nc $1 2222
{"id":1, "method": "JSONRPC.Hello"} cat << EOD | nc $1 2222
{"id":2, "method": "JSONRPC.Introspect"} {"id":0, "method": "JSONRPC.Hello"}
{"id":1, "method": "JSONRPC.Introspect"}
EOD EOD
fi

View File

@ -23,6 +23,7 @@
#include "nymeacore.h" #include "nymeacore.h"
#include "nymeasettings.h" #include "nymeasettings.h"
#include "servers/mocktcpserver.h" #include "servers/mocktcpserver.h"
#include "usermanager/usermanager.h"
using namespace nymeaserver; using namespace nymeaserver;
@ -423,7 +424,7 @@ void NymeaTestBase::createMockDevice()
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params); QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
verifyDeviceError(response); verifyError(response, "deviceError", "DeviceErrorNoError");
m_mockDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString()); m_mockDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
QVERIFY2(!m_mockDeviceId.isNull(), "Newly created mock device must not be null."); QVERIFY2(!m_mockDeviceId.isNull(), "Newly created mock device must not be null.");

View File

@ -22,8 +22,6 @@
#ifndef NYMEATESTBASE_H #ifndef NYMEATESTBASE_H
#define NYMEATESTBASE_H #define NYMEATESTBASE_H
#include "jsonrpc/jsontypes.h"
#include <QSignalSpy> #include <QSignalSpy>
#include <QtTest> #include <QtTest>
#include <QNetworkRequest> #include <QNetworkRequest>
@ -78,25 +76,17 @@ protected:
.toLatin1().data()); .toLatin1().data());
} }
inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) { template<typename T> QString enumValueName(T value)
verifyError(response, "ruleError", JsonTypes::ruleErrorToString(error)); {
QMetaEnum metaEnum = QMetaEnum::fromType<T>();
return metaEnum.valueToKey(value);
} }
inline void verifyDeviceError(const QVariant &response, Device::DeviceError error = Device::DeviceErrorNoError) { template<typename T> T enumNameToValue(const QString &name) {
verifyError(response, "deviceError", JsonTypes::deviceErrorToString(error)); QMetaEnum metaEnum = QMetaEnum::fromType<T>();
return static_cast<T>(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) inline void verifyParams(const QVariantList &requestList, const QVariantList &responseList, bool allRequired = true)
{ {