From bdd9876a880301f6cd42c36fb1b008e122d9fec9 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Fri, 25 Oct 2019 13:13:06 +0200 Subject: [PATCH] Allow registering QMetaObjects on JSON api --- .../devices/devicemanagerimplementation.cpp | 37 ++ .../devices/devicemanagerimplementation.h | 3 + libnymea-core/jsonrpc/actionhandler.cpp | 20 +- .../jsonrpc/configurationhandler.cpp | 71 +--- libnymea-core/jsonrpc/configurationhandler.h | 3 - libnymea-core/jsonrpc/devicehandler.cpp | 320 +++--------------- libnymea-core/jsonrpc/devicehandler.h | 17 +- libnymea-core/jsonrpc/eventhandler.cpp | 27 +- .../jsonrpc/jsonrpcserverimplementation.cpp | 77 +++-- .../jsonrpc/jsonrpcserverimplementation.h | 3 - libnymea-core/jsonrpc/jsonvalidator.cpp | 67 ++-- libnymea-core/jsonrpc/jsonvalidator.h | 6 +- libnymea-core/jsonrpc/logginghandler.cpp | 17 +- libnymea-core/jsonrpc/ruleshandler.cpp | 7 +- libnymea-core/jsonrpc/statehandler.cpp | 3 +- libnymea-core/logging/logentry.h | 10 + libnymea-core/nymeaconfiguration.h | 16 + libnymea-core/usermanager/tokeninfo.h | 7 + libnymea/devices/device.h | 13 +- libnymea/devices/devicedescriptor.h | 7 + libnymea/devices/devicemanager.h | 4 +- libnymea/devices/deviceplugin.h | 10 +- libnymea/devices/pluginmetadata.cpp | 6 +- libnymea/jsonrpc/jsonhandler.cpp | 78 +++++ libnymea/jsonrpc/jsonhandler.h | 104 +++++- libnymea/libnymea.pro | 6 +- libnymea/time/calendaritem.cpp | 7 +- libnymea/time/calendaritem.h | 8 +- libnymea/time/repeatingoption.cpp | 4 - libnymea/time/repeatingoption.h | 3 - libnymea/time/timedescriptor.cpp | 4 - libnymea/time/timedescriptor.h | 3 - libnymea/time/timeeventitem.cpp | 3 - libnymea/time/timeeventitem.h | 3 - libnymea/types/action.cpp | 10 + libnymea/types/action.h | 7 + libnymea/types/actiontype.cpp | 5 + libnymea/types/actiontype.h | 12 + libnymea/types/browseritem.h | 10 + libnymea/types/deviceclass.h | 17 + libnymea/types/event.cpp | 2 +- libnymea/types/event.h | 4 + libnymea/types/eventtype.cpp | 10 + libnymea/types/eventtype.h | 13 + libnymea/types/mediabrowseritem.h | 2 + libnymea/types/param.cpp | 5 + libnymea/types/param.h | 8 +- libnymea/types/paramtype.cpp | 5 + libnymea/types/paramtype.h | 19 ++ libnymea/types/state.cpp | 20 ++ libnymea/types/state.h | 17 + libnymea/types/statetype.cpp | 10 + libnymea/types/statetype.h | 18 + libnymea/types/vendor.h | 5 + libnymea/typeutils.h | 2 +- tests/scripts/getactiontype.sh | 8 +- tests/scripts/getactiontypes.sh | 9 +- tests/scripts/getconfigureddevices.sh | 20 +- tests/scripts/geteventtype.sh | 11 + tests/scripts/geteventtypes.sh | 8 +- tests/scripts/getpluginconfig.sh | 9 +- tests/scripts/getplugins.sh | 8 +- tests/scripts/getsupporteddevices.sh | 22 +- tests/scripts/token.sh | 11 + 64 files changed, 762 insertions(+), 519 deletions(-) create mode 100755 tests/scripts/geteventtype.sh create mode 100755 tests/scripts/token.sh diff --git a/libnymea-core/devices/devicemanagerimplementation.cpp b/libnymea-core/devices/devicemanagerimplementation.cpp index bb079ad6..6148930a 100644 --- a/libnymea-core/devices/devicemanagerimplementation.cpp +++ b/libnymea-core/devices/devicemanagerimplementation.cpp @@ -865,6 +865,43 @@ QString DeviceManagerImplementation::translate(const PluginId &pluginId, const Q return m_translator->translate(pluginId, string, locale); } +ParamType DeviceManagerImplementation::translateParamType(const PluginId &pluginId, const ParamType ¶mType, const QLocale &locale) +{ + ParamType translatedParamType = paramType; + translatedParamType.setDisplayName(translate(pluginId, paramType.displayName(), locale)); + return translatedParamType; +} + +DeviceClass DeviceManagerImplementation::translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) +{ + DeviceClass translatedDeviceClass = deviceClass; + translatedDeviceClass.setDisplayName(translate(deviceClass.pluginId(), deviceClass.displayName(), locale)); + + ParamTypes translatedSettingsTypes; + foreach (const ParamType ¶mType, deviceClass.settingsTypes()) { + translatedSettingsTypes.append(translateParamType(deviceClass.pluginId(), paramType, locale)); + } + translatedDeviceClass.setSettingsTypes(translatedSettingsTypes); + return translatedDeviceClass; +} + +Vendor DeviceManagerImplementation::translateVendor(const Vendor &vendor, const QLocale &locale) +{ + DevicePlugin *plugin = nullptr; + foreach (DevicePlugin *p, m_devicePlugins) { + if (p->supportedVendors().contains(vendor)) { + plugin = p; + } + } + if (!plugin) { + return vendor; + } + + Vendor translatedVendor = vendor; + translatedVendor.setDisplayName(translate(plugin->pluginId(), vendor.displayName(), locale)); + return translatedVendor; +} + /*! Returns the \l{Device} with the given \a id. Null if the id couldn't be found. */ Device *DeviceManagerImplementation::findConfiguredDevice(const DeviceId &id) const { diff --git a/libnymea-core/devices/devicemanagerimplementation.h b/libnymea-core/devices/devicemanagerimplementation.h index 0d40756d..b3e7918e 100644 --- a/libnymea-core/devices/devicemanagerimplementation.h +++ b/libnymea-core/devices/devicemanagerimplementation.h @@ -107,6 +107,9 @@ public: BrowserItemActionInfo *executeBrowserItemAction(const BrowserItemAction &browserItemAction) override; QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override; + ParamType translateParamType(const PluginId &pluginId, const ParamType ¶mType, const QLocale &locale) override; + DeviceClass translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) override; + Vendor translateVendor(const Vendor &vendor, const QLocale &locale) override; signals: void loaded(); diff --git a/libnymea-core/jsonrpc/actionhandler.cpp b/libnymea-core/jsonrpc/actionhandler.cpp index 19c204e7..22e721dc 100644 --- a/libnymea-core/jsonrpc/actionhandler.cpp +++ b/libnymea-core/jsonrpc/actionhandler.cpp @@ -41,6 +41,7 @@ #include "devices/browseractioninfo.h" #include "devices/browseritemactioninfo.h" #include "types/action.h" +#include "types/actiontype.h" #include "loggingcategories.h" namespace nymeaserver { @@ -49,12 +50,15 @@ namespace nymeaserver { ActionHandler::ActionHandler(QObject *parent) : JsonHandler(parent) { + // Enums + registerEnum(); + registerEnum(); + // Objects - QVariantMap action; - action.insert("actionTypeId", enumValueName(Uuid)); - action.insert("deviceId", enumValueName(Uuid)); - action.insert("o:params", QVariantList() << objectRef("Param")); - registerObject("Action", action); + registerObject(); + registerObject(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -125,14 +129,18 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap ¶ms) JsonReply *ActionHandler::GetActionType(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); qCDebug(dcJsonRpc) << "asked for action type" << params; ActionTypeId actionTypeId(params.value("actionTypeId").toString()); foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const ActionType &actionType, deviceClass.actionTypes()) { if (actionType.id() == actionTypeId) { + ActionType translatedActionType = actionType; + translatedActionType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), actionType.displayName(), locale)); + QVariantMap data; data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); - data.insert("actionType", DeviceHandler::packActionType(actionType, deviceClass.pluginId(), params.value("locale").toLocale())); + data.insert("actionType", pack(translatedActionType)); return createReply(data); } } diff --git a/libnymea-core/jsonrpc/configurationhandler.cpp b/libnymea-core/jsonrpc/configurationhandler.cpp index 597d50a7..4a3f4f64 100644 --- a/libnymea-core/jsonrpc/configurationhandler.cpp +++ b/libnymea-core/jsonrpc/configurationhandler.cpp @@ -72,25 +72,9 @@ ConfigurationHandler::ConfigurationHandler(QObject *parent): registerEnum(); // Objects - QVariantMap serverConfiguration; - serverConfiguration.insert("id", enumValueName(String)); - serverConfiguration.insert("address", enumValueName(String)); - serverConfiguration.insert("port", enumValueName(Uint)); - serverConfiguration.insert("sslEnabled", enumValueName(Bool)); - serverConfiguration.insert("authenticationEnabled", enumValueName(Bool)); - registerObject("ServerConfiguration", serverConfiguration); - - QVariantMap webServerConfiguration = serverConfiguration; - webServerConfiguration.insert("publicFolder", enumValueName(String)); - registerObject("WebServerConfiguration", webServerConfiguration); - - QVariantMap mqttPolicy; - mqttPolicy.insert("clientId", enumValueName(String)); - mqttPolicy.insert("username", enumValueName(String)); - mqttPolicy.insert("password", enumValueName(String)); - mqttPolicy.insert("allowedPublishTopicFilters", enumValueName(StringList)); - mqttPolicy.insert("allowedSubscribeTopicFilters", enumValueName(StringList)); - registerObject("MqttPolicy", mqttPolicy); + registerObject(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -327,20 +311,20 @@ JsonReply *ConfigurationHandler::GetConfigurations(const QVariantMap ¶ms) co returns.insert("basicConfiguration", packBasicConfiguration()); QVariantList tcpServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->tcpServerConfigurations()) { - tcpServerConfigs.append(packServerConfiguration(config)); + tcpServerConfigs.append(pack(config)); } returns.insert("tcpServerConfigurations", tcpServerConfigs); QVariantList webServerConfigs; foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { - webServerConfigs.append(packWebServerConfiguration(config)); + webServerConfigs.append(pack(config)); } returns.insert("webServerConfigurations", webServerConfigs); QVariantList webSocketServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->webSocketServerConfigurations()) { - webSocketServerConfigs.append(packServerConfiguration(config)); + webSocketServerConfigs.append(pack(config)); } returns.insert("webSocketServerConfigurations", webSocketServerConfigs); @@ -503,7 +487,7 @@ JsonReply *ConfigurationHandler::GetMqttServerConfigurations(const QVariantMap & QVariantMap ret; QVariantList mqttServerConfigs; foreach (const ServerConfiguration &config, NymeaCore::instance()->configuration()->mqttServerConfigurations()) { - mqttServerConfigs << packServerConfiguration(config); + mqttServerConfigs << pack(config); } ret.insert("mqttServerConfigurations", mqttServerConfigs); return createReply(ret); @@ -545,7 +529,7 @@ JsonReply *ConfigurationHandler::GetMqttPolicies(const QVariantMap ¶ms) cons Q_UNUSED(params) QVariantList mqttPolicies; foreach (const MqttPolicy &policy, NymeaCore::instance()->configuration()->mqttPolicies()) { - mqttPolicies << packMqttPolicy(policy); + mqttPolicies << pack(policy); } QVariantMap ret; ret.insert("mqttPolicies", mqttPolicies); @@ -592,7 +576,7 @@ void ConfigurationHandler::onTcpServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: TCP server configuration changed"; QVariantMap params; - params.insert("tcpServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id))); + params.insert("tcpServerConfiguration", pack(NymeaCore::instance()->configuration()->tcpServerConfigurations().value(id))); emit TcpServerConfigurationChanged(params); } @@ -608,7 +592,7 @@ void ConfigurationHandler::onWebServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: web server configuration changed"; QVariantMap params; - params.insert("webServerConfiguration", packWebServerConfiguration(NymeaCore::instance()->configuration()->webServerConfigurations().value(id))); + params.insert("webServerConfiguration", pack(NymeaCore::instance()->configuration()->webServerConfigurations().value(id))); emit WebServerConfigurationChanged(params); } @@ -624,7 +608,7 @@ void ConfigurationHandler::onWebSocketServerConfigurationChanged(const QString & { qCDebug(dcJsonRpc()) << "Notification: web socket server configuration changed"; QVariantMap params; - params.insert("webSocketServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id))); + params.insert("webSocketServerConfiguration", pack(NymeaCore::instance()->configuration()->webSocketServerConfigurations().value(id))); emit WebSocketServerConfigurationChanged(params); } @@ -640,7 +624,7 @@ void ConfigurationHandler::onMqttServerConfigurationChanged(const QString &id) { qCDebug(dcJsonRpc()) << "Notification: MQTT server configuration changed"; QVariantMap params; - params.insert("mqttServerConfiguration", packServerConfiguration(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id))); + params.insert("mqttServerConfiguration", pack(NymeaCore::instance()->configuration()->mqttServerConfigurations().value(id))); emit MqttServerConfigurationChanged(params); } @@ -656,7 +640,7 @@ void ConfigurationHandler::onMqttPolicyChanged(const QString &clientId) { qCDebug(dcJsonRpc()) << "Notification: MQTT policy changed"; QVariantMap params; - params.insert("policy", packMqttPolicy(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId))); + params.insert("policy", pack(NymeaCore::instance()->configuration()->mqttPolicies().value(clientId))); emit MqttPolicyChanged(params); } @@ -680,34 +664,6 @@ QVariantMap ConfigurationHandler::packBasicConfiguration() return basicConfiguration; } -QVariantMap ConfigurationHandler::packServerConfiguration(const ServerConfiguration &config) -{ - QVariantMap serverConfiguration; - serverConfiguration.insert("id", config.id); - serverConfiguration.insert("address", config.address.toString()); - serverConfiguration.insert("port", config.port); - serverConfiguration.insert("sslEnabled", config.sslEnabled); - serverConfiguration.insert("authenticationEnabled", config.authenticationEnabled); - return serverConfiguration; -} - -QVariantMap ConfigurationHandler::packWebServerConfiguration(const WebServerConfiguration &config) -{ - QVariantMap webServerConfiguration = packServerConfiguration(config); - webServerConfiguration.insert("publicFolder", config.publicFolder); - return webServerConfiguration; -} - -QVariantMap ConfigurationHandler::packMqttPolicy(const MqttPolicy &policy) -{ - QVariantMap policyMap; - policyMap.insert("clientId", policy.clientId); - policyMap.insert("username", policy.username); - policyMap.insert("password", policy.password); - policyMap.insert("allowedPublishTopicFilters", policy.allowedPublishTopicFilters); - policyMap.insert("allowedSubscribeTopicFilters", policy.allowedSubscribeTopicFilters); - return policyMap; -} MqttPolicy ConfigurationHandler::unpackMqttPolicy(const QVariantMap &mqttPolicyMap) { @@ -741,6 +697,7 @@ WebServerConfiguration ConfigurationHandler::unpackWebServerConfiguration(const webServerConfiguration.sslEnabled = tmp.sslEnabled; webServerConfiguration.authenticationEnabled = tmp.authenticationEnabled; webServerConfiguration.publicFolder = webServerConfigurationMap.value("publicFolder").toString(); + qWarning() << "Unpacking web server config:" << webServerConfigurationMap; return webServerConfiguration; } diff --git a/libnymea-core/jsonrpc/configurationhandler.h b/libnymea-core/jsonrpc/configurationhandler.h index df15a937..578debdb 100644 --- a/libnymea-core/jsonrpc/configurationhandler.h +++ b/libnymea-core/jsonrpc/configurationhandler.h @@ -92,9 +92,6 @@ private slots: private: static QVariantMap packBasicConfiguration(); - static QVariantMap packServerConfiguration(const ServerConfiguration &config); - static QVariantMap packWebServerConfiguration(const WebServerConfiguration &config); - static QVariantMap packMqttPolicy(const MqttPolicy &policy); static ServerConfiguration unpackServerConfiguration(const QVariantMap &serverConfigurationMap); static WebServerConfiguration unpackWebServerConfiguration(const QVariantMap &webServerConfigurationMap); diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 20383cd7..37429bee 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -80,7 +80,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : // Enums registerEnum(); registerEnum(); - registerEnum(); + registerEnum(); registerEnum(); registerEnum(); registerEnum(); @@ -88,109 +88,20 @@ DeviceHandler::DeviceHandler(QObject *parent) : registerEnum(); // Objects - QVariantMap paramType; - paramType.insert("id", enumValueName(Uuid)); - paramType.insert("name", enumValueName(String)); - paramType.insert("displayName", enumValueName(String)); - paramType.insert("type", enumRef()); - paramType.insert("index", enumValueName(Int)); - paramType.insert("o:defaultValue", enumValueName(Variant)); - paramType.insert("o:minValue", enumValueName(Variant)); - paramType.insert("o:maxValue", enumValueName(Variant)); - paramType.insert("o:allowedValues", QVariantList() << enumValueName(Variant)); - paramType.insert("o:inputType", enumRef()); - paramType.insert("o:unit", enumRef()); - paramType.insert("o:readOnly", enumValueName(Bool)); - registerObject("ParamType", paramType); - - QVariantMap param; - param.insert("paramTypeId", enumValueName(Uuid)); - param.insert("value", enumValueName(Variant)); - registerObject("Param", param); - - QVariantMap plugin; - plugin.insert("id", enumValueName(Uuid)); - plugin.insert("name", enumValueName(String)); - plugin.insert("displayName", enumValueName(String)); - plugin.insert("paramTypes", QVariantList() << objectRef("ParamType")); - registerObject("Plugin", plugin); - - QVariantMap vendor; - vendor.insert("id", enumValueName(Uuid)); - vendor.insert("name", enumValueName(String)); - vendor.insert("displayName", enumValueName(String)); - registerObject("Vendor", vendor); - - QVariantMap eventType; - eventType.insert("id", enumValueName(Uuid)); - eventType.insert("name", enumValueName(String)); - eventType.insert("displayName", enumValueName(String)); - eventType.insert("index", enumValueName(Int)); - eventType.insert("paramTypes", QVariantList() << objectRef("ParamType")); - registerObject("EventType", eventType); - - QVariantMap stateType; - stateType.insert("id", enumValueName(Uuid)); - stateType.insert("name", enumValueName(String)); - stateType.insert("displayName", enumValueName(String)); - stateType.insert("type", enumRef()); - stateType.insert("index", enumValueName(Int)); - stateType.insert("defaultValue", enumValueName(Variant)); - stateType.insert("o:unit", enumRef()); - stateType.insert("o:minValue", enumValueName(Variant)); - stateType.insert("o:maxValue", enumValueName(Variant)); - stateType.insert("o:possibleValues", QVariantList() << enumValueName(Variant)); - registerObject("StateType", stateType); - - QVariantMap actionType; - actionType.insert("id", enumValueName(Uuid)); - actionType.insert("name", enumValueName(String)); - actionType.insert("displayName", enumValueName(String)); - actionType.insert("index", enumValueName(Int)); - actionType.insert("paramTypes", QVariantList() << objectRef("ParamType")); - registerObject("ActionType", actionType); - - QVariantMap deviceClass; - deviceClass.insert("id", enumValueName(Uuid)); - deviceClass.insert("vendorId", enumValueName(Uuid)); - deviceClass.insert("pluginId", enumValueName(Uuid)); - deviceClass.insert("name", enumValueName(String)); - deviceClass.insert("displayName", enumValueName(String)); - deviceClass.insert("interfaces", QVariantList() << enumValueName(String)); - deviceClass.insert("browsable", enumValueName(Bool)); - deviceClass.insert("setupMethod", enumRef()); - deviceClass.insert("createMethods", QVariantList() << enumRef()); - deviceClass.insert("stateTypes", QVariantList() << objectRef("StateType")); - deviceClass.insert("eventTypes", QVariantList() << objectRef("EventType")); - deviceClass.insert("actionTypes", QVariantList() << objectRef("ActionType")); - deviceClass.insert("browserItemActionTypes", QVariantList() << objectRef("ActionType")); - deviceClass.insert("paramTypes", QVariantList() << objectRef("ParamType")); - deviceClass.insert("settingsTypes", QVariantList() << objectRef("ParamType")); - deviceClass.insert("discoveryParamTypes", QVariantList() << objectRef("ParamType")); - registerObject("DeviceClass", deviceClass); - - QVariantMap deviceDescriptor; - deviceDescriptor.insert("id", enumValueName(Uuid)); - deviceDescriptor.insert("deviceId", enumValueName(Uuid)); - deviceDescriptor.insert("title", enumValueName(String)); - deviceDescriptor.insert("description", enumValueName(String)); - deviceDescriptor.insert("deviceParams", QVariantList() << objectRef("Param")); - registerObject("DeviceDescriptor", deviceDescriptor); - - QVariantMap device; - device.insert("id", enumValueName(Uuid)); - device.insert("deviceClassId", enumValueName(Uuid)); - device.insert("name", enumValueName(String)); - device.insert("params", QVariantList() << objectRef("Param")); - device.insert("settings", QVariantList() << objectRef("Param")); - QVariantMap stateValues; - stateValues.insert("stateTypeId", enumValueName(Uuid)); - stateValues.insert("value", enumValueName(Variant)); - device.insert("states", QVariantList() << stateValues); - device.insert("setupComplete", enumValueName(Bool)); - device.insert("o:parentId", enumValueName(Uuid)); - registerObject("Device", device); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + registerObject(); + // Regsitering browseritem manually for now. Not sure how to deal with the + // polymorphism in int (e.g MediaBrowserItem) QVariantMap browserItem; browserItem.insert("id", enumValueName(String)); browserItem.insert("displayName", enumValueName(String)); @@ -219,7 +130,7 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); description = "Returns a list of loaded plugins."; - returns.insert("plugins", QVariantList() << objectRef("Plugin")); + returns.insert("plugins", QVariantList() << objectRef("DevicePlugin")); registerMethod("GetPlugins", description, params, returns); params.clear(); returns.clear(); @@ -467,18 +378,8 @@ JsonReply* DeviceHandler::GetSupportedVendors(const QVariantMap ¶ms) const QVariantList vendors; foreach (const Vendor &vendor, NymeaCore::instance()->deviceManager()->supportedVendors()) { - - DevicePlugin *plugin = nullptr; - foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) { - if (p->supportedVendors().contains(vendor)) { - plugin = p; - } - } - QVariantMap variantMap; - variantMap.insert("id", vendor.id().toString()); - variantMap.insert("name", vendor.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale)); - vendors.append(variantMap); + Vendor translatedVendor = NymeaCore::instance()->deviceManager()->translateVendor(vendor, locale); + vendors.append(pack(translatedVendor)); } QVariantMap returns; @@ -492,8 +393,10 @@ JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap ¶ms) const VendorId vendorId = VendorId(params.value("vendorId").toString()); QVariantMap returns; QVariantList deviceClasses; - foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) - deviceClasses.append(packDeviceClass(deviceClass, locale)); + foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices(vendorId)) { + DeviceClass translatedDeviceClass = NymeaCore::instance()->deviceManager()->translateDeviceClass(deviceClass, locale); + deviceClasses.append(pack(translatedDeviceClass)); + } returns.insert("deviceClasses", deviceClasses); return createReply(returns); @@ -511,14 +414,14 @@ JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap ¶ms) const JsonReply *reply = createAsyncReply("GetDiscoveredDevices"); DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(deviceClassId, discoveryParams); - connect(info, &DeviceDiscoveryInfo::finished, reply, [reply, info, locale](){ + connect(info, &DeviceDiscoveryInfo::finished, reply, [this, reply, info, locale](){ QVariantMap returns; returns.insert("deviceError", enumValueName(info->status())); if (info->status() == Device::DeviceErrorNoError) { QVariantList deviceDescriptorList; foreach (const DeviceDescriptor &deviceDescriptor, info->deviceDescriptors()) { - deviceDescriptorList.append(packDeviceDescriptor(deviceDescriptor)); + deviceDescriptorList.append(pack(deviceDescriptor)); } returns.insert("deviceDescriptors", deviceDescriptorList); } @@ -540,7 +443,9 @@ JsonReply* DeviceHandler::GetPlugins(const QVariantMap ¶ms) const QVariantList plugins; foreach (DevicePlugin* plugin, NymeaCore::instance()->deviceManager()->plugins()) { - plugins.append(packPlugin(plugin, locale)); + QVariantMap packedPlugin = pack(*plugin); + packedPlugin["displayName"] = NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale); + plugins.append(packedPlugin); } QVariantMap returns; @@ -560,7 +465,7 @@ JsonReply *DeviceHandler::GetPluginConfiguration(const QVariantMap ¶ms) cons QVariantList paramVariantList; foreach (const Param ¶m, plugin->configuration()) { - paramVariantList.append(packParam(param)); + paramVariantList.append(pack(param)); } returns.insert("configuration", paramVariantList); returns.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); @@ -820,12 +725,15 @@ JsonReply* DeviceHandler::GetActionTypes(const QVariantMap ¶ms) const JsonReply* DeviceHandler::GetStateTypes(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); + QVariantMap returns; QVariantList stateList; DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(DeviceClassId(params.value("deviceClassId").toString())); - foreach (const StateType &stateType, deviceClass.stateTypes()) { - stateList.append(packStateType(stateType, deviceClass.pluginId(), NymeaCore::instance()->configuration()->locale())); + foreach (StateType stateType, deviceClass.stateTypes()) { + stateType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), stateType.displayName(), locale)); + stateList.append(pack(stateType)); } returns.insert("stateTypes", stateList); return createReply(returns); @@ -908,7 +816,7 @@ Param DeviceHandler::unpackParam(const QVariantMap ¶m) if (param.keys().count() == 0) return Param(); - ParamTypeId paramTypeId = param.value("paramTypeId").toString(); + ParamTypeId paramTypeId = param.value("paramTypeId").toUuid(); QVariant value = param.value("value"); return Param(paramTypeId, value); } @@ -992,56 +900,14 @@ QVariantMap DeviceHandler::packBrowserItem(const BrowserItem &item) return ret; } -QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) +QVariantMap DeviceHandler::packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) const { - QVariantMap variantMap; - variantMap.insert("id", paramType.id().toString()); - variantMap.insert("name", paramType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); - variantMap.insert("type", enumValueName(variantTypeToBasicType(paramType.type()))); - variantMap.insert("index", paramType.index()); - - // Optional values - if (paramType.defaultValue().isValid()) - variantMap.insert("defaultValue", paramType.defaultValue()); - - if (paramType.minValue().isValid()) - variantMap.insert("minValue", paramType.minValue()); - - if (paramType.maxValue().isValid()) - variantMap.insert("maxValue", paramType.maxValue()); - - if (!paramType.allowedValues().isEmpty()) - variantMap.insert("allowedValues", paramType.allowedValues()); - - if (paramType.inputType() != Types::InputTypeNone) - variantMap.insert("inputType", enumValueName(paramType.inputType())); - - if (paramType.unit() != Types::UnitNone) - variantMap.insert("unit", enumValueName(paramType.unit())); - - if (paramType.readOnly()) - variantMap.insert("readOnly", paramType.readOnly()); - - return variantMap; + ParamType translatedParamType = paramType; + translatedParamType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(pluginId, paramType.displayName(), locale)); + return pack(translatedParamType); } -QVariantMap DeviceHandler::packPlugin(DevicePlugin *plugin, const QLocale &locale) -{ - QVariantMap pluginMap; - pluginMap.insert("id", plugin->pluginId().toString()); - pluginMap.insert("name", plugin->pluginName()); - pluginMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), plugin->pluginDisplayName(), locale)); - - QVariantList params; - foreach (const ParamType ¶m, plugin->configurationDescription()) - params.append(packParamType(param, plugin->pluginId(), locale)); - - pluginMap.insert("paramTypes", params); - return pluginMap; -} - -QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) +QVariantMap DeviceHandler::packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const { QVariantMap variant; variant.insert("id", eventType.id().toString()); @@ -1057,23 +923,7 @@ QVariantMap DeviceHandler::packEventType(const EventType &eventType, const Plugi return variant; } -QVariantMap DeviceHandler::packVendor(const Vendor &vendor, const QLocale &locale) -{ - DevicePlugin *plugin = nullptr; - foreach (DevicePlugin *p, NymeaCore::instance()->deviceManager()->plugins()) { - if (p->supportedVendors().contains(vendor)) { - plugin = p; - } - } - QVariantMap variantMap; - variantMap.insert("id", vendor.id().toString()); - variantMap.insert("name", vendor.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(plugin->pluginId(), vendor.displayName(), locale)); - return variantMap; - -} - -QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) +QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const { QVariantMap variantMap; variantMap.insert("id", actionType.id().toString()); @@ -1088,7 +938,7 @@ QVariantMap DeviceHandler::packActionType(const ActionType &actionType, const Pl return variantMap; } -QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods) +QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createMethods) const { QVariantList ret; if (createMethods.testFlag(DeviceClass::CreateMethodUser)) @@ -1103,96 +953,6 @@ QVariantList DeviceHandler::packCreateMethods(DeviceClass::CreateMethods createM return ret; } -QVariantMap DeviceHandler::packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) -{ - QVariantMap variant; - variant.insert("id", deviceClass.id().toString()); - variant.insert("name", deviceClass.name()); - variant.insert("displayName", NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), deviceClass.displayName(), locale)); - variant.insert("vendorId", deviceClass.vendorId().toString()); - variant.insert("pluginId", deviceClass.pluginId().toString()); - variant.insert("interfaces", deviceClass.interfaces()); - variant.insert("browsable", deviceClass.browsable()); - - QVariantList stateTypes; - foreach (const StateType &stateType, deviceClass.stateTypes()) - stateTypes.append(packStateType(stateType, deviceClass.pluginId(), locale)); - - QVariantList eventTypes; - foreach (const EventType &eventType, deviceClass.eventTypes()) - eventTypes.append(packEventType(eventType, deviceClass.pluginId(), locale)); - - QVariantList actionTypes; - foreach (const ActionType &actionType, deviceClass.actionTypes()) - actionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); - - QVariantList browserItemActionTypes; - foreach (const ActionType &actionType, deviceClass.browserItemActionTypes()) - browserItemActionTypes.append(packActionType(actionType, deviceClass.pluginId(), locale)); - - QVariantList paramTypes; - foreach (const ParamType ¶mType, deviceClass.paramTypes()) - paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); - - QVariantList settingsTypes; - foreach (const ParamType &settingsType, deviceClass.settingsTypes()) - settingsTypes.append(packParamType(settingsType, deviceClass.pluginId(), locale)); - - QVariantList discoveryParamTypes; - foreach (const ParamType ¶mType, deviceClass.discoveryParamTypes()) - discoveryParamTypes.append(packParamType(paramType, deviceClass.pluginId(), locale)); - - variant.insert("paramTypes", paramTypes); - variant.insert("settingsTypes", settingsTypes); - variant.insert("discoveryParamTypes", discoveryParamTypes); - variant.insert("stateTypes", stateTypes); - variant.insert("eventTypes", eventTypes); - variant.insert("actionTypes", actionTypes); - variant.insert("browserItemActionTypes", browserItemActionTypes); - variant.insert("createMethods", packCreateMethods(deviceClass.createMethods())); - variant.insert("setupMethod", enumValueName(deviceClass.setupMethod())); - return variant; -} - -QVariantMap DeviceHandler::packDeviceDescriptor(const DeviceDescriptor &descriptor) -{ - QVariantMap variant; - variant.insert("id", descriptor.id().toString()); - variant.insert("deviceId", descriptor.deviceId().toString()); - variant.insert("title", descriptor.title()); - variant.insert("description", descriptor.description()); - QVariantList params; - foreach (const Param ¶m, descriptor.params()) { - params.append(packParam(param)); - } - variant.insert("deviceParams", params); - return variant; -} - -QVariantMap DeviceHandler::packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) -{ - QVariantMap variantMap; - variantMap.insert("id", stateType.id().toString()); - variantMap.insert("name", stateType.name()); - variantMap.insert("displayName", NymeaCore::instance()->deviceManager()->translate(pluginId, stateType.displayName(), locale)); - variantMap.insert("index", stateType.index()); - variantMap.insert("type", enumValueName(variantTypeToBasicType(stateType.type()))); - variantMap.insert("defaultValue", stateType.defaultValue()); - - if (stateType.maxValue().isValid()) - variantMap.insert("maxValue", stateType.maxValue()); - - if (stateType.minValue().isValid()) - variantMap.insert("minValue", stateType.minValue()); - - if (!stateType.possibleValues().isEmpty()) - variantMap.insert("possibleValues", stateType.possibleValues()); - - if(stateType.unit() != Types::UnitNone) - variantMap.insert("unit", enumValueName(stateType.unit())); - - return variantMap; -} void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config) { diff --git a/libnymea-core/jsonrpc/devicehandler.h b/libnymea-core/jsonrpc/devicehandler.h index b96d37aa..07dbb6c4 100644 --- a/libnymea-core/jsonrpc/devicehandler.h +++ b/libnymea-core/jsonrpc/devicehandler.h @@ -60,15 +60,14 @@ public: Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *GetBrowserItem(const QVariantMap ¶ms) const; - static QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale); - static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale); - static QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale); - static QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale); - static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods); - static QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale); - static QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor); + QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale) const; +// QVariantMap packPlugin(DevicePlugin *plugin, const QLocale &locale) const; + QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale) const; +// QVariantMap packStateType(const StateType &stateType, const PluginId &pluginId, const QLocale &locale) const; + QVariantMap packActionType(const ActionType &actionType, const PluginId &pluginId, const QLocale &locale) const; + QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods) const; +// QVariantMap packDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) const; + QVariantMap packDeviceDescriptor(const DeviceDescriptor &descriptor) const; static QVariantMap packParam(const Param ¶m); static QVariantList packParams(const ParamList ¶mList); diff --git a/libnymea-core/jsonrpc/eventhandler.cpp b/libnymea-core/jsonrpc/eventhandler.cpp index f48f140b..b33254f4 100644 --- a/libnymea-core/jsonrpc/eventhandler.cpp +++ b/libnymea-core/jsonrpc/eventhandler.cpp @@ -48,12 +48,12 @@ namespace nymeaserver { EventHandler::EventHandler(QObject *parent) : JsonHandler(parent) { + registerEnum(); + registerEnum(); // Objects - QVariantMap event; - event.insert("eventTypeId", enumValueName(Uuid)); - event.insert("deviceId", enumValueName(Uuid)); - event.insert("o:params", QVariantList() << objectRef("Param")); - registerObject("Event", event); + registerObject(); + registerObject(); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -80,30 +80,23 @@ QString EventHandler::name() const void EventHandler::eventTriggered(const Event &event) { QVariantMap params; - - QVariantMap variant; - variant.insert("eventTypeId", event.eventTypeId().toString()); - variant.insert("deviceId", event.deviceId().toString()); - QVariantList eventParams; - foreach (const Param ¶m, event.params()) { - eventParams.append(DeviceHandler::packParam(param)); - } - variant.insert("params", eventParams); - - params.insert("event", variant); + params.insert("event", pack(event)); emit EventTriggered(params); } JsonReply* EventHandler::GetEventType(const QVariantMap ¶ms) const { + QLocale locale = params.value("locale").toLocale(); qCDebug(dcJsonRpc) << "asked for event type" << params; EventTypeId eventTypeId(params.value("eventTypeId").toString()); foreach (const DeviceClass &deviceClass, NymeaCore::instance()->deviceManager()->supportedDevices()) { foreach (const EventType &eventType, deviceClass.eventTypes()) { if (eventType.id() == eventTypeId) { + EventType translatedEventType = eventType; + translatedEventType.setDisplayName(NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), eventType.displayName(), locale)); QVariantMap data; data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); - data.insert("eventType", DeviceHandler::packEventType(eventType, deviceClass.pluginId(), params.value("locale").toLocale())); + data.insert("eventType", pack(translatedEventType)); return createReply(data); } } diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp index 1f6c8bb4..5a4aaab0 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.cpp @@ -80,12 +80,13 @@ JsonRPCServerImplementation::JsonRPCServerImplementation(const QSslConfiguration registerEnum(); // Objects - QVariantMap tokenInfo; - tokenInfo.insert("id", enumValueName(Uuid)); - tokenInfo.insert("userName", enumValueName(String)); - tokenInfo.insert("deviceName", enumValueName(String)); - tokenInfo.insert("creationTime", enumValueName(Uint)); - registerObject("TokenInfo", tokenInfo); +// QVariantMap tokenInfo; +// tokenInfo.insert("id", enumValueName(Uuid)); +// tokenInfo.insert("userName", enumValueName(String)); +// tokenInfo.insert("deviceName", enumValueName(String)); +// tokenInfo.insert("creationTime", enumValueName(Uint)); +// registerObject("TokenInfo", tokenInfo); + registerObject(); // Methods QString description; QVariantMap returns; QVariantMap params; @@ -355,14 +356,10 @@ JsonReply *JsonRPCServerImplementation::Tokens(const QVariantMap ¶ms) const QByteArray token = property("token").toByteArray(); QString username = NymeaCore::instance()->userManager()->userForToken(token); - if (username.isEmpty()) { - // There *really* should be a user for the token in the DB - Q_ASSERT(false); - } QList tokens = NymeaCore::instance()->userManager()->tokens(username); QVariantList retList; foreach (const TokenInfo &tokenInfo, tokens) { - retList << packTokenInfo(tokenInfo); + retList << pack(tokenInfo); } QVariantMap retMap; retMap.insert("tokenInfoList", retList); @@ -682,16 +679,6 @@ void JsonRPCServerImplementation::processJsonPacket(TransportInterface *interfac } } -QVariantMap JsonRPCServerImplementation::packTokenInfo(const TokenInfo &tokenInfo) -{ - QVariantMap ret; - ret.insert("id", tokenInfo.id().toString()); - ret.insert("userName", tokenInfo.username()); - ret.insert("deviceName", tokenInfo.deviceName()); - ret.insert("creationTime", tokenInfo.creationTime().toTime_t()); - return ret; -} - void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms) { JsonHandler *handler = qobject_cast(sender()); @@ -793,39 +780,57 @@ void JsonRPCServerImplementation::onPushButtonAuthFinished(int transactionId, bo bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler) { // Sanity checks on API: - // * Make sure all $ref: entries are valid. A Handler can reference Types from previously loaded handlers or own ones. - // * A handler must not register a type name that is already registered by a previously loaded handler. - QVariantMap types = m_api.value("types").toMap(); + // * Make sure all $ref: entries are valid. + // * A handler must not register a type name that is already registered by a previously loaded handler with different content. QVariantMap methods = m_api.value("methods").toMap(); QVariantMap notifications = m_api.value("notifications").toMap(); + QVariantMap apiIncludingThis = m_api; // Verify enums name clash + QVariantMap enums = m_api.value("enums").toMap(); foreach (const QString &enumName, handler->jsonEnums().keys()) { QVariantList list = handler->jsonEnums().value(enumName).toList(); - if (types.contains(enumName)) { + if (enums.contains(enumName) && enums.value(enumName) != list) { qCWarning(dcJsonRpc()) << "Enum type" << enumName << "is already registered. Not registering handler" << handler->name(); return false; } - types.insert(enumName, list); + enums.insert(enumName, list); } + apiIncludingThis["enums"] = enums; + + QVariantMap flags = m_api.value("flags").toMap(); + foreach (const QString &flagName, handler->jsonFlags().keys()) { + QVariant flagDescription = handler->jsonFlags().value(flagName); + if (enums.contains(flagName)) { + qCWarning(dcJsonRpc()) << "Enum with name" << flagName << "is already registered. Not registering handler" << handler->name(); + return false; + } + if (flags.contains(flagName) && flags.value(flagName) != handler->jsonFlags().value(flagName)) { + qCWarning(dcJsonRpc()) << "Flags with name" << flagName << "is already registered. Not registering handler" << handler->name(); + return false; + } + flags.insert(flagName, flagDescription); + } + apiIncludingThis["flags"] = flags; // Verify objects - QVariantMap typesIncludingThis = types; + QVariantMap existingTypes = m_api.value("types").toMap(); + QVariantMap typesIncludingThis = existingTypes; typesIncludingThis.unite(handler->jsonObjects()); + apiIncludingThis["types"] = typesIncludingThis; foreach (const QString &objectName, handler->jsonObjects().keys()) { QVariantMap object = handler->jsonObjects().value(objectName).toMap(); // Check for name clashes - if (types.contains(objectName)) { + if (existingTypes.contains(objectName) && existingTypes.value(objectName) != handler->jsonObjects().value(objectName)) { qCWarning(dcJsonRpc()) << "Object type" << objectName << "is already registered. Not registering handler" << handler->name(); return false; } // Check for invalid $ref: entries - if (!JsonValidator::checkRefs(object, typesIncludingThis)) { + if (!JsonValidator::checkRefs(object, apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in object type " << objectName << ". Not registering handler " << handler->name(); return false; } } - types = typesIncludingThis; // Verify methods QVariantMap newMethods; @@ -835,35 +840,35 @@ bool JsonRPCServerImplementation::registerHandler(JsonHandler *handler) qCWarning(dcJsonRpc()).nospace().noquote() << "Invalid method \"" << methodName << "\". Method \"JsonReply* " + methodName + "(QVariantMap)\" does not exist. Not registering handler " << handler->name(); return false; } - if (!JsonValidator::checkRefs(method.value("params").toMap(), types)) { + if (!JsonValidator::checkRefs(method.value("params").toMap(), apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of method " << methodName << ". Not registering handler " << handler->name(); return false; } - if (!JsonValidator::checkRefs(method.value("returns").toMap(), types)) { + if (!JsonValidator::checkRefs(method.value("returns").toMap(), apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in return value of method " << methodName << ". Not registering handler " << handler->name(); return false; } newMethods.insert(handler->name() + '.' + methodName, method); } methods.unite(newMethods); + apiIncludingThis["methods"] = methods; // Verify notifications QVariantMap newNotifications; foreach (const QString ¬ificationName, handler->jsonNotifications().keys()) { QVariantMap notification = handler->jsonNotifications().value(notificationName).toMap(); - if (!JsonValidator::checkRefs(notification.value("params").toMap(), types)) { + if (!JsonValidator::checkRefs(notification.value("params").toMap(), apiIncludingThis)) { qCWarning(dcJsonRpc()).nospace() << "Invalid reference in params of notification " << notificationName << ". Not registering handler " << handler->name(); return false; } newNotifications.insert(handler->name() + '.' + notificationName, notification); } notifications.unite(newNotifications); + apiIncludingThis["notifications"] = notifications; // Checks completed. Store new API qCDebug(dcJsonRpc()) << "Registering JSON RPC handler:" << handler->name(); - m_api["types"] = types; - m_api["methods"] = methods; - m_api["notifications"] = notifications; + m_api = apiIncludingThis; m_handlers.insert(handler->name(), handler); for (int i = 0; i < handler->metaObject()->methodCount(); ++i) { diff --git a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h index 4f5741bc..7d9f2598 100644 --- a/libnymea-core/jsonrpc/jsonrpcserverimplementation.h +++ b/libnymea-core/jsonrpc/jsonrpcserverimplementation.h @@ -84,9 +84,6 @@ private: void processJsonPacket(TransportInterface *interface, const QUuid &clientId, const QByteArray &data); - - static QVariantMap packTokenInfo(const TokenInfo &tokenInfo); - private slots: void setup(); diff --git a/libnymea-core/jsonrpc/jsonvalidator.cpp b/libnymea-core/jsonrpc/jsonvalidator.cpp index 56cb1c61..7b9e3dbc 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.cpp +++ b/libnymea-core/jsonrpc/jsonvalidator.cpp @@ -9,18 +9,23 @@ namespace nymeaserver { -bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types) +bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &api) { + QVariantMap enums = api.value("enums").toMap(); + QVariantMap flags = api.value("flags").toMap(); + QVariantMap types = api.value("types").toMap(); +// qWarning() << "checkrefs enums" << enums.keys(); foreach (const QString &key, map.keys()) { +// qWarning() << "checking prop" << key; if (map.value(key).toString().startsWith("$ref:")) { QString refName = map.value(key).toString().remove("$ref:"); - if (!types.contains(refName)) { + if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) { qCWarning(dcJsonRpc()) << "Invalid reference to" << refName; return false; } } if (map.value(key).type() == QVariant::Map) { - bool ret = checkRefs(map.value(key).toMap(), types); + bool ret = checkRefs(map.value(key).toMap(), api); if (!ret) { return false; } @@ -29,13 +34,13 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types) foreach (const QVariant &entry, map.value(key).toList()) { if (entry.toString().startsWith("$ref:")) { QString refName = entry.toString().remove("$ref:"); - if (!types.contains(refName)) { + if (!enums.contains(refName) && !flags.contains(refName) && !types.contains(refName)) { qCWarning(dcJsonRpc()) << "Invalid reference to" << refName; return false; } } if (entry.type() == QVariant::Map) { - bool ret = checkRefs(map.value(key).toMap(), types); + bool ret = checkRefs(map.value(key).toMap(), api); if (!ret) { return false; } @@ -50,7 +55,7 @@ bool JsonValidator::checkRefs(const QVariantMap &map, const QVariantMap &types) JsonValidator::Result JsonValidator::validateParams(const QVariantMap ¶ms, const QString &method, const QVariantMap &api) { QVariantMap paramDefinition = api.value("methods").toMap().value(method).toMap().value("params").toMap(); - m_result = validateMap(params, paramDefinition, api.value("types").toMap()); + m_result = validateMap(params, paramDefinition, api); m_result.setWhere(method + ", param " + m_result.where()); return m_result; } @@ -58,7 +63,7 @@ JsonValidator::Result JsonValidator::validateParams(const QVariantMap ¶ms, c JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api) { QVariantMap returnsDefinition = api.value("methods").toMap().value(method).toMap().value("returns").toMap(); - m_result = validateMap(returns, returnsDefinition, api.value("types").toMap()); + m_result = validateMap(returns, returnsDefinition, api); m_result.setWhere(method + ", returns " + m_result.where()); return m_result; } @@ -66,7 +71,7 @@ JsonValidator::Result JsonValidator::validateReturns(const QVariantMap &returns, JsonValidator::Result JsonValidator::validateNotificationParams(const QVariantMap ¶ms, const QString ¬ification, const QVariantMap &api) { QVariantMap paramDefinition = api.value("notifications").toMap().value(notification).toMap().value("params").toMap(); - m_result = validateMap(params, paramDefinition, api.value("types").toMap()); + m_result = validateMap(params, paramDefinition, api); m_result.setWhere(notification + ", param " + m_result.where()); return m_result; } @@ -76,7 +81,7 @@ JsonValidator::Result JsonValidator::result() const return m_result; } -JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types) +JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api) { // Make sure all required values are available foreach (const QString &key, definition.keys()) { @@ -102,7 +107,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q // Validate content QVariant value = map.value(key); - Result result = validateEntry(value, expectedValue, types); + Result result = validateEntry(value, expectedValue, api); if (!result.success()) { result.setWhere(key + '.' + result.where()); result.setErrorString(result.errorString()); @@ -114,8 +119,11 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q return Result(true); } -JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types) +JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api) { +// qWarning() << "validating" << definition; +// qWarning() << "** enums:" << api.value("enums").toMap().keys(); +// qWarning() << "** types:" << api.value("types").toMap().keys(); if (definition.type() == QVariant::String) { QString expectedTypeName = definition.toString(); @@ -123,20 +131,39 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const QString refName = expectedTypeName; refName.remove("$ref:"); - QVariant refDefinition = types.value(refName); // Refs might be enums - if (refDefinition.type() == QVariant::List) { - if (value.type() != QVariant::String) { - return Result(false, "Expected enum " + refName + " but got " + value.toString()); - } + QVariantMap enums = api.value("enums").toMap(); + if (enums.contains(refName)) { + QVariant refDefinition = enums.value(refName); + QVariantList enumList = refDefinition.toList(); if (!enumList.contains(value.toString())) { - return Result(false, "Expected enum " + refName + " but got " + value.toString()); + return Result(false, "Expected enum " + refName + " but got " + value.toJsonDocument().toJson()); + } + return Result(true); + } + // Or flags + QVariantMap flags = api.value("flags").toMap(); + if (flags.contains(refName)) { + QVariant refDefinition = flags.value(refName); + qWarning() << "Flag:" << value.type(); + if (value.type() != QVariant::StringList) { + return Result(false, "Expected flags " + refName + " but got " + value.toString()); + } + QString flagEnum = refDefinition.toList().first().toString(); + qWarning() << "Flag enum:" << flagEnum; + foreach (const QVariant &flagsEntry, value.toList()) { + Result result = validateEntry(flagsEntry, flagEnum, api); + if (!result.success()) { + return result; + } } return Result(true); } - return validateEntry(value, refDefinition, types); + QVariantMap types = api.value("types").toMap(); + QVariant refDefinition = types.value(refName); + return validateEntry(value, refDefinition, api); } JsonHandler::BasicType expectedBasicType = JsonHandler::enumNameToValue(expectedTypeName); @@ -199,7 +226,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const if (value.type() != QVariant::Map) { return Result(false, "Invalud value. Expected a map bug received: " + value.toString()); } - return validateMap(value.toMap(), definition.toMap(), types); + return validateMap(value.toMap(), definition.toMap(), api); } if (definition.type() == QVariant::List) { @@ -209,7 +236,7 @@ JsonValidator::Result JsonValidator::validateEntry(const QVariant &value, const return Result(false, "Expected list of " + entryDefinition.toString() + " but got value of type " + value.typeName() + "\n" + QJsonDocument::fromVariant(value).toJson()); } foreach (const QVariant &entry, value.toList()) { - Result result = validateEntry(entry, entryDefinition, types); + Result result = validateEntry(entry, entryDefinition, api); if (!result.success()) { return result; } diff --git a/libnymea-core/jsonrpc/jsonvalidator.h b/libnymea-core/jsonrpc/jsonvalidator.h index 731da915..8d2d1130 100644 --- a/libnymea-core/jsonrpc/jsonvalidator.h +++ b/libnymea-core/jsonrpc/jsonvalidator.h @@ -30,7 +30,7 @@ public: JsonValidator() {} - static bool checkRefs(const QVariantMap &map, const QVariantMap &types); + static bool checkRefs(const QVariantMap &map, const QVariantMap &api); Result validateParams(const QVariantMap ¶ms, const QString &method, const QVariantMap &api); Result validateReturns(const QVariantMap &returns, const QString &method, const QVariantMap &api); @@ -38,8 +38,8 @@ public: Result result() const; private: - Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &types); - Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &types); + Result validateMap(const QVariantMap &map, const QVariantMap &definition, const QVariantMap &api); + Result validateEntry(const QVariant &value, const QVariant &definition, const QVariantMap &api); Result m_result; }; diff --git a/libnymea-core/jsonrpc/logginghandler.cpp b/libnymea-core/jsonrpc/logginghandler.cpp index f3e3e0c0..5af2e1c7 100644 --- a/libnymea-core/jsonrpc/logginghandler.cpp +++ b/libnymea-core/jsonrpc/logginghandler.cpp @@ -62,18 +62,7 @@ LoggingHandler::LoggingHandler(QObject *parent) : registerEnum(); // Objects - QVariantMap logEntry; - logEntry.insert("timestamp", enumValueName(Int)); - logEntry.insert("loggingLevel", enumRef()); - logEntry.insert("source", enumRef()); - logEntry.insert("o:typeId", enumValueName(Uuid)); - logEntry.insert("o:deviceId", enumValueName(Uuid)); - logEntry.insert("o:itemId", enumValueName(String)); - logEntry.insert("o:value", enumValueName(String)); - logEntry.insert("o:active", enumValueName(Bool)); - logEntry.insert("o:eventType", enumRef()); - logEntry.insert("o:errorCode", enumValueName(String)); - registerObject("LogEntry", logEntry); + registerObject(); // Methods QString description; QVariantMap params; QVariantMap returns; @@ -198,8 +187,8 @@ QVariantMap LoggingHandler::packLogEntry(const LogEntry &logEntry) case Logging::LoggingSourceActions: case Logging::LoggingSourceEvents: case Logging::LoggingSourceStates: - logEntryMap.insert("typeId", logEntry.typeId().toString()); - logEntryMap.insert("deviceId", logEntry.deviceId().toString()); + logEntryMap.insert("typeId", logEntry.typeId()); + logEntryMap.insert("deviceId", logEntry.deviceId()); logEntryMap.insert("value", LogValueTool::convertVariantToString(logEntry.value())); break; case Logging::LoggingSourceSystem: diff --git a/libnymea-core/jsonrpc/ruleshandler.cpp b/libnymea-core/jsonrpc/ruleshandler.cpp index 0ddd8d1c..457f4ff1 100644 --- a/libnymea-core/jsonrpc/ruleshandler.cpp +++ b/libnymea-core/jsonrpc/ruleshandler.cpp @@ -116,12 +116,7 @@ RulesHandler::RulesHandler(QObject *parent) : repeatingOption.insert("o:monthDays", QVariantList() << enumValueName(Int)); registerObject("RepeatingOption", repeatingOption); - QVariantMap calendarItem; - calendarItem.insert("o:datetime", enumValueName(Uint)); - calendarItem.insert("o:startTime", enumValueName(Time)); - calendarItem.insert("duration", enumValueName(Uint)); - calendarItem.insert("o:repeating", objectRef("RepeatingOption")); - registerObject("CalendarItem", calendarItem); + registerObject(); QVariantMap timeEventItem; timeEventItem.insert("o:datetime", enumValueName(Uint)); diff --git a/libnymea-core/jsonrpc/statehandler.cpp b/libnymea-core/jsonrpc/statehandler.cpp index 2ede3ded..d260d322 100644 --- a/libnymea-core/jsonrpc/statehandler.cpp +++ b/libnymea-core/jsonrpc/statehandler.cpp @@ -73,7 +73,8 @@ JsonReply* StateHandler::GetStateType(const QVariantMap ¶ms) const if (stateType.id() == stateTypeId) { QVariantMap data; data.insert("deviceError", enumValueName(Device::DeviceErrorNoError)); - data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); + // FIXME TODO!!! +// data.insert("stateType", DeviceHandler::packStateType(stateType, deviceClass.pluginId(), params.value("locale").toLocale())); return createReply(data); } } diff --git a/libnymea-core/logging/logentry.h b/libnymea-core/logging/logentry.h index 5cd8fb84..abb973b0 100644 --- a/libnymea-core/logging/logentry.h +++ b/libnymea-core/logging/logentry.h @@ -34,6 +34,16 @@ namespace nymeaserver { class LogEntry { Q_GADGET + Q_PROPERTY(QDateTime timestamp READ timestamp) + Q_PROPERTY(Logging::LoggingLevel loggingLevel READ level) + Q_PROPERTY(Logging::LoggingSource source READ source) + Q_PROPERTY(QUuid typeId READ typeId USER true) + Q_PROPERTY(QUuid deviceId READ deviceId USER true) +// Q_PROPERTY(QString itemId READ itemId USER true) + Q_PROPERTY(QVariant value READ value USER true) + Q_PROPERTY(bool active READ active USER true) + Q_PROPERTY(Logging::LoggingEventType eventType READ eventType USER true) + Q_PROPERTY(QString errorCode READ errorCode USER true) public: LogEntry(QDateTime timestamp, Logging::LoggingLevel level, Logging::LoggingSource source, int errorCode = 0); diff --git a/libnymea-core/nymeaconfiguration.h b/libnymea-core/nymeaconfiguration.h index e6ada65b..aa24409b 100644 --- a/libnymea-core/nymeaconfiguration.h +++ b/libnymea-core/nymeaconfiguration.h @@ -30,9 +30,16 @@ namespace nymeaserver { class ServerConfiguration { + Q_GADGET + Q_PROPERTY(QString id MEMBER id) + Q_PROPERTY(QString address READ addressString) + Q_PROPERTY(uint port MEMBER port) + Q_PROPERTY(bool sslEnabled MEMBER sslEnabled) + Q_PROPERTY(bool authenticationEnabled MEMBER authenticationEnabled) public: QString id; QHostAddress address; + QString addressString() { return address.toString(); } uint port = 0; bool sslEnabled = true; bool authenticationEnabled = true; @@ -50,6 +57,8 @@ QDebug operator <<(QDebug debug, const ServerConfiguration &configuration); class WebServerConfiguration: public ServerConfiguration { + Q_GADGET + Q_PROPERTY(QString publicFolder MEMBER publicFolder) public: QString publicFolder; bool restServerEnabled = false; @@ -57,6 +66,13 @@ public: class MqttPolicy { + Q_GADGET + Q_PROPERTY(QString clientId MEMBER clientId) + Q_PROPERTY(QString username MEMBER username) + Q_PROPERTY(QString password MEMBER password) + Q_PROPERTY(QStringList allowedPublishTopicFilters MEMBER allowedPublishTopicFilters) + Q_PROPERTY(QStringList allowedSubscribeTopicFilters MEMBER allowedSubscribeTopicFilters) + public: QString clientId; QString username; diff --git a/libnymea-core/usermanager/tokeninfo.h b/libnymea-core/usermanager/tokeninfo.h index d65cf544..ed24200d 100644 --- a/libnymea-core/usermanager/tokeninfo.h +++ b/libnymea-core/usermanager/tokeninfo.h @@ -23,11 +23,18 @@ #include #include +#include namespace nymeaserver { class TokenInfo { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString username READ username) + Q_PROPERTY(QDateTime createionTime READ creationTime) + Q_PROPERTY(QString deviveName READ deviceName) + public: TokenInfo(const QUuid &id, const QString &username, const QDateTime &creationTime, const QString &deviceName); diff --git a/libnymea/devices/device.h b/libnymea/devices/device.h index acc937ab..7a012b01 100644 --- a/libnymea/devices/device.h +++ b/libnymea/devices/device.h @@ -41,9 +41,14 @@ class DevicePlugin; class LIBNYMEA_EXPORT Device: public QObject { Q_OBJECT - - friend class DeviceManager; - friend class DeviceManagerImplementation; + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QUuid deviceClassId READ deviceClassId) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(ParamList params READ params WRITE setParams) + Q_PROPERTY(ParamList settings READ settings WRITE setSettings) + Q_PROPERTY(States states READ states WRITE setStates) + Q_PROPERTY(bool setupComplete READ setupComplete WRITE setSetupComplete) + Q_PROPERTY(QUuid parentId READ parentId WRITE setParentId USER true) public: enum DeviceError { @@ -122,6 +127,8 @@ signals: void nameChanged(); private: + friend class DeviceManager; + friend class DeviceManagerImplementation; Device(DevicePlugin *plugin, const DeviceClass &deviceClass, const DeviceId &id, QObject *parent = nullptr); Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *parent = nullptr); diff --git a/libnymea/devices/devicedescriptor.h b/libnymea/devices/devicedescriptor.h index 6952cc65..15e84fc7 100644 --- a/libnymea/devices/devicedescriptor.h +++ b/libnymea/devices/devicedescriptor.h @@ -32,6 +32,13 @@ class LIBNYMEA_EXPORT DeviceDescriptor { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QUuid deviceId READ deviceId USER true) + Q_PROPERTY(QString title READ title) + Q_PROPERTY(QString description READ description) + Q_PROPERTY(ParamList deviceParams READ params) + public: DeviceDescriptor(); DeviceDescriptor(const DeviceClassId &deviceClassId, const QString &title = QString(), const QString &description = QString(), const DeviceId &parentDeviceId = DeviceId()); diff --git a/libnymea/devices/devicemanager.h b/libnymea/devices/devicemanager.h index 2d55f80c..66bfd87a 100644 --- a/libnymea/devices/devicemanager.h +++ b/libnymea/devices/devicemanager.h @@ -125,7 +125,9 @@ public: virtual BrowserItemActionInfo* executeBrowserItemAction(const BrowserItemAction &browserItemAction) = 0; virtual QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0; - + virtual ParamType translateParamType(const PluginId &pluginId, const ParamType ¶mType, const QLocale &locale) = 0; + virtual DeviceClass translateDeviceClass(const DeviceClass &deviceClass, const QLocale &locale) = 0; + virtual Vendor translateVendor(const Vendor &vendor, const QLocale &locale) = 0; signals: void pluginConfigChanged(const PluginId &id, const ParamList &config); void eventTriggered(const Event &event); diff --git a/libnymea/devices/deviceplugin.h b/libnymea/devices/deviceplugin.h index 034f06e6..0b6726c1 100644 --- a/libnymea/devices/deviceplugin.h +++ b/libnymea/devices/deviceplugin.h @@ -62,8 +62,10 @@ class LIBNYMEA_EXPORT DevicePlugin: public QObject { Q_OBJECT - friend class DeviceManager; - friend class DeviceManagerImplementation; + Q_PROPERTY(QUuid id READ pluginId) + Q_PROPERTY(QString name READ pluginName) + Q_PROPERTY(QString displayName READ pluginDisplayName) + Q_PROPERTY(ParamTypes paramTypes READ configurationDescription) public: DevicePlugin(QObject *parent = nullptr); @@ -115,6 +117,10 @@ protected: QSettings *pluginStorage() const; private: + friend class DeviceManager; + friend class DeviceManagerImplementation; + + void setMetaData(const PluginMetadata &metaData); void initPlugin(const PluginMetadata &metadata, DeviceManager *deviceManager, HardwareManager *hardwareManager); diff --git a/libnymea/devices/pluginmetadata.cpp b/libnymea/devices/pluginmetadata.cpp index e5830391..75aded84 100644 --- a/libnymea/devices/pluginmetadata.cpp +++ b/libnymea/devices/pluginmetadata.cpp @@ -103,7 +103,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) return; } - m_pluginId = jsonObject.value("id").toString(); + m_pluginId = PluginId(jsonObject.value("id").toString()); m_pluginName = jsonObject.value("name").toString(); m_pluginDisplayName = jsonObject.value("displayName").toString(); @@ -192,7 +192,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) continue; } - DeviceClassId deviceClassId = deviceClassObject.value("id").toString(); + DeviceClassId deviceClassId = DeviceClassId(deviceClassObject.value("id").toString()); QString deviceClassName = deviceClassObject.value("name").toString(); // Check if there are any unknown fields @@ -304,7 +304,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject) continue; } - StateTypeId stateTypeId = st.value("id").toString(); + StateTypeId stateTypeId = StateTypeId(st.value("id").toString()); QString stateTypeName = st.value("name").toString(); // Check if there are any unknown fields diff --git a/libnymea/jsonrpc/jsonhandler.cpp b/libnymea/jsonrpc/jsonhandler.cpp index 3b5e728e..4f5170e6 100644 --- a/libnymea/jsonrpc/jsonhandler.cpp +++ b/libnymea/jsonrpc/jsonhandler.cpp @@ -6,6 +6,7 @@ JsonHandler::JsonHandler(QObject *parent) : QObject(parent) { + registerEnum(); } QVariantMap JsonHandler::jsonEnums() const @@ -13,6 +14,11 @@ QVariantMap JsonHandler::jsonEnums() const return m_enums; } +QVariantMap JsonHandler::jsonFlags() const +{ + return m_flags; +} + QVariantMap JsonHandler::jsonObjects() const { return m_objects; @@ -62,6 +68,8 @@ JsonHandler::BasicType JsonHandler::variantTypeToBasicType(QVariant::Type varian return Time; case QVariant::Map: return Object; + case QVariant::DateTime: + return Uint; // DateTime is represented as time_t default: return Variant; } @@ -132,3 +140,73 @@ JsonReply *JsonHandler::createAsyncReply(const QString &method) const return JsonReply::createAsyncReply(const_cast(this), method); } +QVariantMap JsonHandler::pack(const QMetaObject &metaObject, const void *value) const +{ + QVariantMap ret; +// qWarning() << "+ Packing" << metaObject.className(); + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + if (metaProperty.name() == QStringLiteral("objectName")) { + continue; // Skip QObject's objectName property + } + + QVariant val = metaProperty.readOnGadget(value); +// qWarning() << "|- Property:" << metaProperty.name() << metaProperty.readOnGadget(value) << metaProperty.type() << metaProperty.typeName(); +// qWarning() << "|-- All list types:" << m_listMetaObjects.keys(); + if (metaProperty.type() == QVariant::UserType) { + if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { + QMetaEnum metaEnum = QMetaEnum::fromType(); +// qWarning() << "|--" << metaProperty.readOnGadget(value).toInt() << metaEnum.key(metaProperty.readOnGadget(value).toInt()); + ret.insert(metaProperty.name(), metaEnum.key(variantTypeToBasicType(metaProperty.readOnGadget(value).template value()))); + } else if (m_listMetaObjects.contains(metaProperty.typeName())) { + QVariant listObject = metaProperty.readOnGadget(value); + QMetaObject listMetaObject = m_listMetaObjects.value(metaProperty.typeName()); + QMetaProperty countProperty = listMetaObject.property(listMetaObject.indexOfProperty("count")); + int listCount = countProperty.readOnGadget(listObject.constData()).toInt(); +// qWarning() << "Packing list type" << listObject << "count is" << listCount; + QMetaMethod metaMethod = listMetaObject.method(listMetaObject.indexOfMethod("get(int)")); +// qWarning() << "get method" << listMetaObject.indexOfMethod("get(int)") << listMetaObject.method(0).name() << QMetaObject::normalizedSignature("QVariant get(int)"); + + QMetaObject entryMetaObject = m_metaObjects.value(m_listEntryTypes.value(listMetaObject.className())); + QVariantList list; + for (int i = 0; i < listCount; i++) { + QVariant entry; + metaMethod.invokeOnGadget(listObject.data(), Q_RETURN_ARG(QVariant, entry), Q_ARG(int, i)); +// qWarning() << "|---Feckin hell" << entry; + + list.append(pack(entryMetaObject, entry.data())); + } + + ret.insert(metaProperty.name(), list); + + + } else { + Q_ASSERT_X(false, this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered in this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); + } + } else if (metaProperty.isFlagType()) { + QMetaEnum metaFlag = m_metaFlags.value(QString(metaProperty.typeName()).split("::").last()); +// QMetaEnum metaEnum = m_metaEnums.value(m_flagsEnums.value(metaFlag.name())); + int flagValue = metaProperty.readOnGadget(value).toInt(); +// qWarning() << "|-- Flag" << flagValue << metaFlag.name() << metaFlag.keyCount() << metaProperty.type(); + QStringList flags; + for (int i = 0; i < metaFlag.keyCount(); i++) { +// qWarning() << "|--- flag key:" << metaFlag.key(i) << metaFlag.value(i); + if ((metaFlag.value(i) & flagValue) > 0) { + flags.append(metaFlag.key(i)); + } + } + ret.insert(metaProperty.name(), flags); + } else if (metaProperty.isEnumType()) { + QString enumName = QString(metaProperty.typeName()).split("::").last(); + Q_ASSERT_X(m_metaEnums.contains(enumName), this->metaObject()->className(), QString("Cannot pack %1. %2 is not registered int this handler.").arg(metaObject.className()).arg(metaProperty.typeName()).toUtf8()); + QMetaEnum metaEnum = m_metaEnums.value(enumName); +// qWarning() << "|-- Enum: Name:" << metaEnum.name() << "as int:" << metaEnum.key(metaProperty.readOnGadget(value).toInt()) << "All enums:" << m_metaEnums.keys(); + ret.insert(metaProperty.name(), metaEnum.key(metaProperty.readOnGadget(value).toInt())); + } else if (!metaProperty.isUser() || !metaProperty.readOnGadget(value).isNull()) { +// qWarning() << "|-- property" << metaProperty.name() << metaProperty.readOnGadget(value); + ret.insert(metaProperty.name(), metaProperty.readOnGadget(value)); + } + } + return ret; +} + diff --git a/libnymea/jsonrpc/jsonhandler.h b/libnymea/jsonrpc/jsonhandler.h index 09b509c5..87423f64 100644 --- a/libnymea/jsonrpc/jsonhandler.h +++ b/libnymea/jsonrpc/jsonhandler.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include "jsonreply.h" @@ -32,6 +34,7 @@ public: virtual QString name() const = 0; QVariantMap jsonEnums() const; + QVariantMap jsonFlags() const; QVariantMap jsonObjects() const; QVariantMap jsonMethods() const; QVariantMap jsonNotifications() const; @@ -46,8 +49,13 @@ public: static BasicType variantTypeToBasicType(QVariant::Type variantType); static QVariant::Type basicTypeToVariantType(BasicType basicType); + template QVariantMap pack(const T &value) const; + protected: - template void registerEnum(); + template void registerEnum(); + template void registerEnum(); + template void registerObject(); + template void registerObject(); void registerObject(const QString &name, const QVariantMap &object); void registerMethod(const QString &name, const QString &description, const QVariantMap ¶ms, const QVariantMap &returns, bool deprecated = false); void registerNotification(const QString &name, const QString &description, const QVariantMap ¶ms, bool deprecated = false); @@ -55,13 +63,23 @@ protected: JsonReply *createReply(const QVariantMap &data) const; JsonReply *createAsyncReply(const QString &method) const; +private: + QVariantMap pack(const QMetaObject &metaObject, const void *gadget) const; private: QVariantMap m_enums; + QHash m_metaEnums; + QVariantMap m_flags; + QHash m_metaFlags; + QHash m_flagsEnums; QVariantMap m_objects; + QHash m_metaObjects; + QHash m_listMetaObjects; + QHash m_listEntryTypes; QVariantMap m_methods; QVariantMap m_notifications; }; +Q_DECLARE_METATYPE(QVariant::Type) template void JsonHandler::registerEnum() @@ -72,9 +90,83 @@ void JsonHandler::registerEnum() values << metaEnum.key(i); } m_enums.insert(metaEnum.name(), values); - + m_metaEnums.insert(metaEnum.name(), metaEnum); } +template +void JsonHandler::registerEnum() +{ + registerEnum(); + QMetaEnum metaEnum = QMetaEnum::fromType(); + QMetaEnum metaFlags = QMetaEnum::fromType(); + m_metaFlags.insert(metaFlags.name(), metaFlags); + m_flagsEnums.insert(metaFlags.name(), metaEnum.name()); + m_flags.insert(metaFlags.name(), QVariantList() << QString("$ref:%1").arg(metaEnum.name())); +} + +template +void JsonHandler::registerObject() +{ + qRegisterMetaType(); + QMetaObject metaObject = ObjectType::staticMetaObject; + QString className = QString(metaObject.className()).split("::").last(); + QVariantMap description; + for (int i = 0; i < metaObject.propertyCount(); i++) { + QMetaProperty metaProperty = metaObject.property(i); + QString name = metaProperty.name(); + if (name == "objectName") { + continue; // Skip QObject's objectName property + } + if (metaProperty.isUser()) { + name.prepend("o:"); + } + QVariant typeName; +// qWarning() << ".-.-.-.-.-" << metaProperty.name() << metaProperty.type() << metaProperty.typeName(); + if (metaProperty.type() == QVariant::UserType) { + if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) { + typeName = QString("$ref:BasicType"); + } else if (QString(metaProperty.typeName()).startsWith("QList")) { + typeName = QVariantList() << "$ref:" + QString(metaProperty.typeName()).remove("QList<").remove(">"); + } else { + typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); + } + } else if (metaProperty.isEnumType()) { + typeName = QString("$ref:%1").arg(QString(metaProperty.typeName()).split("::").last()); + } else if (metaProperty.isFlagType()) { + typeName = QVariantList() << "$ref:" + m_flagsEnums.value(metaProperty.name()); + } else if (metaProperty.type() == QVariant::List) { + typeName = QVariantList() << enumValueName(Variant); + } else { + typeName = enumValueName(variantTypeToBasicType(metaProperty.type())); + } + description.insert(name, typeName); + } + m_objects.insert(className, description); + m_metaObjects.insert(className, metaObject); +} + +template +void JsonHandler::registerObject() +{ + registerObject(); + QMetaObject metaObject = ObjectType::staticMetaObject; + QMetaObject listMetaObject = ListType::staticMetaObject; + m_objects.insert(listMetaObject.className(), QVariantList() << QVariant(QString("$ref:%1").arg(metaObject.className()))); + m_metaObjects.insert(listMetaObject.className(), listMetaObject); + m_listMetaObjects.insert(listMetaObject.className(), listMetaObject); + m_listEntryTypes.insert(listMetaObject.className(), metaObject.className()); + Q_ASSERT_X(listMetaObject.indexOfProperty("count") >= 0, "JsonHandler", "List type does not implement \"count\" property!"); + Q_ASSERT_X(listMetaObject.indexOfMethod("get(int)") >= 0, "JsonHandler", "List type does not implement \"Q_INVOKABLE QVariant get(int index)\" method!"); +} + +//template +//void JsonHandler::registerList() +//{ +// QMetaObject metaObject = T::staticMetaObject; +// m_lists.insert(metaObject.className(), metaObject); +// m_objects.insert(metaObject.classInfo(), QVariantList() << ) +//} + template QString JsonHandler::enumRef() { @@ -96,4 +188,12 @@ T JsonHandler::enumNameToValue(const QString &name) return static_cast(metaEnum.keyToValue(name.toUtf8())); } +template +QVariantMap JsonHandler::pack(const T &value) const +{ + QMetaObject metaObject = T::staticMetaObject; + return pack(metaObject, static_cast(&value)); +} + + #endif // JSONHANDLER_H diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index b00b7833..0fc19205 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -26,8 +26,7 @@ HEADERS += \ devices/browseresult.h \ jsonrpc/jsonhandler.h \ jsonrpc/jsonreply.h \ - experiences/experienceplugin.h \ - jsonrpc/jsonrpcserver.h \ + jsonrpc/jsonrpcserver.h \ libnymea.h \ platform/package.h \ platform/repository.h \ @@ -109,8 +108,7 @@ SOURCES += \ devices/browseresult.cpp \ jsonrpc/jsonhandler.cpp \ jsonrpc/jsonreply.cpp \ - experiences/experienceplugin.cpp \ - jsonrpc/jsonrpcserver.cpp \ + jsonrpc/jsonrpcserver.cpp \ loggingcategories.cpp \ nymeasettings.cpp \ platform/package.cpp \ diff --git a/libnymea/time/calendaritem.cpp b/libnymea/time/calendaritem.cpp index b3a07e5d..edee90bb 100644 --- a/libnymea/time/calendaritem.cpp +++ b/libnymea/time/calendaritem.cpp @@ -19,8 +19,8 @@ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /*! - \class nymeaserver::CalendarItem - \brief Describes a clendar item for a time based \l{nymeaserver::Rule}{Rule}. + \class CalendarItem + \brief Describes a clendar item. \ingroup rules \inmodule core @@ -33,8 +33,6 @@ #include -namespace nymeaserver { - /*! Construct a invalid \l{CalendarItem}. */ CalendarItem::CalendarItem(): m_duration(0) @@ -275,5 +273,4 @@ QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem) return dbg; } -} diff --git a/libnymea/time/calendaritem.h b/libnymea/time/calendaritem.h index c99798b4..56eb6341 100644 --- a/libnymea/time/calendaritem.h +++ b/libnymea/time/calendaritem.h @@ -25,10 +25,13 @@ #include "repeatingoption.h" -namespace nymeaserver { - class CalendarItem { + Q_GADGET + Q_PROPERTY(uint duration READ duration WRITE setDuration) + Q_PROPERTY(QDateTime datetime READ dateTime WRITE setDateTime USER true) + Q_PROPERTY(QTime startTime READ startTime WRITE setStartTime USER true) + Q_PROPERTY(RepeatingOption repeating READ repeatingOption WRITE setRepeatingOption USER true) public: CalendarItem(); @@ -64,6 +67,5 @@ private: }; QDebug operator<<(QDebug dbg, const CalendarItem &calendarItem); -} #endif // CALENDARITEM_H diff --git a/libnymea/time/repeatingoption.cpp b/libnymea/time/repeatingoption.cpp index 3a25fd26..58807d9f 100644 --- a/libnymea/time/repeatingoption.cpp +++ b/libnymea/time/repeatingoption.cpp @@ -83,8 +83,6 @@ #include -namespace nymeaserver { - /*! Constructs an empty \l{RepeatingOption}. */ RepeatingOption::RepeatingOption() : m_mode(RepeatingModeNone) @@ -197,5 +195,3 @@ QDebug operator<<(QDebug dbg, const RepeatingOption &repeatingOption) dbg.nospace() << "RepeatingOption(Mode:" << repeatingOption.mode() << ", Monthdays:" << repeatingOption.monthDays() << "Weekdays:" << repeatingOption.weekDays() << ")"; return dbg; } - -} diff --git a/libnymea/time/repeatingoption.h b/libnymea/time/repeatingoption.h index 28055546..85390a11 100644 --- a/libnymea/time/repeatingoption.h +++ b/libnymea/time/repeatingoption.h @@ -26,8 +26,6 @@ class QDateTime; -namespace nymeaserver { - class RepeatingOption { Q_GADGET @@ -66,6 +64,5 @@ private: }; QDebug operator<<(QDebug dbg, const RepeatingOption &RepeatingOption); -} #endif // REPEATINGOPTION_H diff --git a/libnymea/time/timedescriptor.cpp b/libnymea/time/timedescriptor.cpp index eb00bd46..dda50d2a 100644 --- a/libnymea/time/timedescriptor.cpp +++ b/libnymea/time/timedescriptor.cpp @@ -36,8 +36,6 @@ #include -namespace nymeaserver { - /*! Constructs an invalid \l{TimeDescriptor}.*/ TimeDescriptor::TimeDescriptor() { @@ -119,5 +117,3 @@ QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor) } return dbg; } - -} diff --git a/libnymea/time/timedescriptor.h b/libnymea/time/timedescriptor.h index 94efcc7c..0da0c0a7 100644 --- a/libnymea/time/timedescriptor.h +++ b/libnymea/time/timedescriptor.h @@ -24,8 +24,6 @@ #include "timeeventitem.h" #include "calendaritem.h" -namespace nymeaserver { - class TimeDescriptor { public: @@ -54,6 +52,5 @@ private: QDebug operator<<(QDebug dbg, const TimeDescriptor &timeDescriptor); -} #endif // TIMEDESCRIPTOR_H diff --git a/libnymea/time/timeeventitem.cpp b/libnymea/time/timeeventitem.cpp index b4fa53f8..408b79a8 100644 --- a/libnymea/time/timeeventitem.cpp +++ b/libnymea/time/timeeventitem.cpp @@ -33,8 +33,6 @@ #include -namespace nymeaserver { - /*! Constructs an invalid \l{TimeEventItem}. */ TimeEventItem::TimeEventItem() { @@ -141,4 +139,3 @@ QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem) return dbg; } -} diff --git a/libnymea/time/timeeventitem.h b/libnymea/time/timeeventitem.h index 60a2a82a..90b8819e 100644 --- a/libnymea/time/timeeventitem.h +++ b/libnymea/time/timeeventitem.h @@ -25,8 +25,6 @@ #include "repeatingoption.h" -namespace nymeaserver { - class TimeEventItem { public: @@ -56,6 +54,5 @@ private: QDebug operator<<(QDebug dbg, const TimeEventItem &timeEventItem); -} #endif // TIMEEVENTITEM_H diff --git a/libnymea/types/action.cpp b/libnymea/types/action.cpp index a38597c1..95f9c589 100644 --- a/libnymea/types/action.cpp +++ b/libnymea/types/action.cpp @@ -73,12 +73,22 @@ ActionTypeId Action::actionTypeId() const return m_actionTypeId; } +void Action::setActionTypeId(const ActionTypeId &actionTypeId) +{ + m_actionTypeId = actionTypeId; +} + /*! Returns the deviceId this Action is associated with. */ DeviceId Action::deviceId() const { return m_deviceId; } +void Action::setDeviceId(const DeviceId &deviceId) +{ + m_deviceId = deviceId; +} + /*! Returns the parameters for this Action. */ ParamList Action::params() const { diff --git a/libnymea/types/action.h b/libnymea/types/action.h index 85e9c005..bfeda7fd 100644 --- a/libnymea/types/action.h +++ b/libnymea/types/action.h @@ -32,6 +32,11 @@ class LIBNYMEA_EXPORT Action { + Q_GADGET + Q_PROPERTY(QUuid actionTypeId READ actionTypeId WRITE setActionTypeId) + Q_PROPERTY(QUuid deviceId READ deviceId WRITE setDeviceId) + Q_PROPERTY(ParamList params READ params WRITE setParams USER true) + public: explicit Action(const ActionTypeId &actionTypeId = ActionTypeId(), const DeviceId &deviceId = DeviceId()); Action(const Action &other); @@ -41,7 +46,9 @@ public: bool isValid() const; ActionTypeId actionTypeId() const; + void setActionTypeId(const ActionTypeId &actionTypeId); DeviceId deviceId() const; + void setDeviceId(const DeviceId &deviceId); ParamList params() const; void setParams(const ParamList ¶ms); diff --git a/libnymea/types/actiontype.cpp b/libnymea/types/actiontype.cpp index 959183bd..94e35701 100644 --- a/libnymea/types/actiontype.cpp +++ b/libnymea/types/actiontype.cpp @@ -123,6 +123,11 @@ ActionTypes::ActionTypes(const QList &other) } } +QVariant ActionTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + ActionType ActionTypes::findByName(const QString &name) { foreach (const ActionType &actionType, *this) { diff --git a/libnymea/types/actiontype.h b/libnymea/types/actiontype.h index d809ab4e..6b03e6b9 100644 --- a/libnymea/types/actiontype.h +++ b/libnymea/types/actiontype.h @@ -32,6 +32,13 @@ class LIBNYMEA_EXPORT ActionType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(int index READ index WRITE setIndex) + Q_PROPERTY(ParamTypes paramTypes READ paramTypes WRITE setParamTypes) + public: ActionType(const ActionTypeId &id = ActionTypeId()); @@ -59,16 +66,21 @@ private: int m_index; ParamTypes m_paramTypes; }; +Q_DECLARE_METATYPE(ActionType) QDebug operator<<(QDebug dbg, const ActionType &actionType); class ActionTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: ActionTypes() = default; ActionTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); ActionType findByName(const QString &name); ActionType findById(const ActionTypeId &id); }; +Q_DECLARE_METATYPE(ActionTypes) #endif // ACTIONTYPE_H diff --git a/libnymea/types/browseritem.h b/libnymea/types/browseritem.h index 466f725e..c32bcaea 100644 --- a/libnymea/types/browseritem.h +++ b/libnymea/types/browseritem.h @@ -33,6 +33,16 @@ class LIBNYMEA_EXPORT BrowserItem { Q_GADGET + Q_PROPERTY(QString id READ id) + Q_PROPERTY(QString displayName READ displayName) + Q_PROPERTY(QString description READ description) + Q_PROPERTY(BrowserIcon icon READ icon) + Q_PROPERTY(QString thumbnail READ thumbnail) + Q_PROPERTY(bool executable READ executable) + Q_PROPERTY(bool browsable READ browsable) + Q_PROPERTY(bool disabled READ disabled) + Q_PROPERTY(QList actionTypeIds READ actionTypeIds) + public: enum BrowserIcon { BrowserIconNone, diff --git a/libnymea/types/deviceclass.h b/libnymea/types/deviceclass.h index abf1644e..e03c494c 100644 --- a/libnymea/types/deviceclass.h +++ b/libnymea/types/deviceclass.h @@ -38,6 +38,22 @@ class LIBNYMEA_EXPORT DeviceClass { Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QUuid vendorId READ vendorId) + Q_PROPERTY(QUuid pluginId READ pluginId) + Q_PROPERTY(QString name READ name) + Q_PROPERTY(QString displayName READ displayName) + Q_PROPERTY(QStringList interfaces READ interfaces) + Q_PROPERTY(bool browsable READ browsable) + Q_PROPERTY(SetupMethod setupMethod READ setupMethod) + Q_PROPERTY(CreateMethods createMethods READ createMethods) + Q_PROPERTY(StateTypes stateTypes READ stateTypes) + Q_PROPERTY(EventTypes eventTypes READ eventTypes) + Q_PROPERTY(ActionTypes actionTypes READ actionTypes) + Q_PROPERTY(ActionTypes browserItemActionTypes READ browserItemActionTypes) + Q_PROPERTY(ParamTypes paramTypes READ paramTypes) + Q_PROPERTY(ParamTypes settingsTypes READ settingsTypes) + Q_PROPERTY(ParamTypes discoveryParamTypes READ discoveryParamTypes) public: enum CreateMethod { @@ -47,6 +63,7 @@ public: }; Q_ENUM(CreateMethod) Q_DECLARE_FLAGS(CreateMethods, CreateMethod) + Q_FLAG(CreateMethods) enum SetupMethod { SetupMethodJustAdd, diff --git a/libnymea/types/event.cpp b/libnymea/types/event.cpp index 9703c68d..82a50eb4 100644 --- a/libnymea/types/event.cpp +++ b/libnymea/types/event.cpp @@ -108,7 +108,7 @@ Param Event::param(const ParamTypeId ¶mTypeId) const return param; } } - return Param(QString()); + return Param(paramTypeId); } /*! Returns true if this event is autogenerated by a state change. */ diff --git a/libnymea/types/event.h b/libnymea/types/event.h index e88867ab..de2bd947 100644 --- a/libnymea/types/event.h +++ b/libnymea/types/event.h @@ -34,6 +34,10 @@ class LIBNYMEA_EXPORT Event { + Q_GADGET + Q_PROPERTY(QUuid eventTypeId READ eventTypeId) + Q_PROPERTY(QUuid deviceId READ deviceId) + Q_PROPERTY(ParamList params READ params) public: Event(); Event(const EventTypeId &eventTypeId, const DeviceId &deviceId, const ParamList ¶ms = ParamList(), bool isStateChangeEvent = false); diff --git a/libnymea/types/eventtype.cpp b/libnymea/types/eventtype.cpp index b7a10fa1..9b563736 100644 --- a/libnymea/types/eventtype.cpp +++ b/libnymea/types/eventtype.cpp @@ -33,6 +33,11 @@ #include "eventtype.h" +EventType::EventType() +{ + +} + /*! Constructs a EventType object with the given \a id. */ EventType::EventType(const EventTypeId &id): m_id(id), @@ -123,6 +128,11 @@ EventTypes::EventTypes(const QList &other) } } +QVariant EventTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + EventType EventTypes::findByName(const QString &name) { foreach (const EventType &eventType, *this) { diff --git a/libnymea/types/eventtype.h b/libnymea/types/eventtype.h index c50ec651..fbdb4628 100644 --- a/libnymea/types/eventtype.h +++ b/libnymea/types/eventtype.h @@ -32,7 +32,15 @@ class LIBNYMEA_EXPORT EventType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(int index READ index) + Q_PROPERTY(ParamTypes paramTypes READ paramTypes WRITE setParamTypes) + public: + EventType(); EventType(const EventTypeId &id); EventTypeId id() const; @@ -61,14 +69,19 @@ private: int m_index; QList m_paramTypes; }; +Q_DECLARE_METATYPE(EventType) class EventTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: EventTypes() = default; EventTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); EventType findByName(const QString &name); EventType findById(const EventTypeId &id); }; +Q_DECLARE_METATYPE(EventTypes) #endif // TRIGGERTYPE_H diff --git a/libnymea/types/mediabrowseritem.h b/libnymea/types/mediabrowseritem.h index 64df18b2..03ad702e 100644 --- a/libnymea/types/mediabrowseritem.h +++ b/libnymea/types/mediabrowseritem.h @@ -28,6 +28,8 @@ class MediaBrowserItem: public BrowserItem { Q_GADGET + Q_PROPERTY(MediaBrowserIcon mediaIcon READ mediaIcon) + public: enum MediaBrowserIcon { MediaBrowserIconNone = 1, diff --git a/libnymea/types/param.cpp b/libnymea/types/param.cpp index f49f39f6..0d3b81aa 100644 --- a/libnymea/types/param.cpp +++ b/libnymea/types/param.cpp @@ -109,6 +109,11 @@ ParamList::ParamList(const QList &other): QList(other) } +QVariant ParamList::get(int index) +{ + return QVariant::fromValue(at(index)); +} + /*! Returns true if this ParamList contains a Param with the given \a paramTypeId. */ bool ParamList::hasParam(const ParamTypeId ¶mTypeId) const { diff --git a/libnymea/types/param.h b/libnymea/types/param.h index 04c14fe5..9b180054 100644 --- a/libnymea/types/param.h +++ b/libnymea/types/param.h @@ -32,6 +32,9 @@ class LIBNYMEA_EXPORT Param { + Q_GADGET + Q_PROPERTY(QUuid paramTypeId READ paramTypeId) + Q_PROPERTY(QVariant value READ value WRITE setValue) public: Param(const ParamTypeId ¶mTypeId = ParamTypeId(), const QVariant &value = QVariant()); @@ -52,9 +55,12 @@ QDebug operator<<(QDebug dbg, const Param ¶m); class LIBNYMEA_EXPORT ParamList: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: ParamList(); ParamList(const QList &other); + Q_INVOKABLE QVariant get(int index); bool hasParam(const ParamTypeId ¶mTypeId) const; QVariant paramValue(const ParamTypeId ¶mTypeId) const; bool setParamValue(const ParamTypeId ¶mTypeId, const QVariant &value); @@ -64,7 +70,7 @@ private: QList m_ids; }; - +Q_DECLARE_METATYPE(ParamList) QDebug operator<<(QDebug dbg, const ParamList ¶ms); #endif // PARAM_H diff --git a/libnymea/types/paramtype.cpp b/libnymea/types/paramtype.cpp index 246d4a8e..cb69b88f 100644 --- a/libnymea/types/paramtype.cpp +++ b/libnymea/types/paramtype.cpp @@ -255,6 +255,11 @@ ParamTypes::ParamTypes(const QList &other): QList(other) { } +QVariant ParamTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + ParamType ParamTypes::findByName(const QString &name) { foreach (const ParamType ¶mType, *this) { diff --git a/libnymea/types/paramtype.h b/libnymea/types/paramtype.h index ea80fc00..217e4185 100644 --- a/libnymea/types/paramtype.h +++ b/libnymea/types/paramtype.h @@ -32,6 +32,20 @@ class LIBNYMEA_EXPORT ParamType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(QVariant::Type type READ type WRITE setType) + Q_PROPERTY(int index READ index WRITE setIndex) + Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue USER true) + Q_PROPERTY(QVariant minValue READ minValue WRITE setMinValue USER true) + Q_PROPERTY(QVariant maxValue READ maxValue WRITE setMaxValue USER true) + Q_PROPERTY(QVariantList allowedValues READ allowedValues WRITE setAllowedValues USER true) + Q_PROPERTY(Types::InputType inputType READ inputType WRITE setInputType USER true) + Q_PROPERTY(Types::Unit unit READ unit WRITE setUnit USER true) + Q_PROPERTY(bool readOnly READ readOnly WRITE setReadOnly USER true) + public: ParamType() = default; ParamType(const ParamTypeId &id, const QString &name, const QVariant::Type type, const QVariant &defaultValue = QVariant()); @@ -96,12 +110,17 @@ private: class ParamTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: ParamTypes() = default; ParamTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); ParamType findByName(const QString &name); ParamType findById(const ParamTypeId &id); }; +Q_DECLARE_METATYPE(QList) +Q_DECLARE_METATYPE(ParamTypes) QDebug operator<<(QDebug dbg, const ParamType ¶mType); QDebug operator<<(QDebug dbg, const QList ¶mTypes); diff --git a/libnymea/types/state.cpp b/libnymea/types/state.cpp index 272d670c..e1c3185e 100644 --- a/libnymea/types/state.cpp +++ b/libnymea/types/state.cpp @@ -36,6 +36,11 @@ #include "state.h" +State::State() +{ + +} + /*! Constructs a State reflecting the \l{StateType} given by \a stateTypeId * and associated with the \l{Device} given by \a deviceId */ State::State(const StateTypeId &stateTypeId, const DeviceId &deviceId): @@ -92,3 +97,18 @@ QDebug operator<<(QDebug dbg, const QList &states) return dbg.space(); } + +States::States() +{ + +} + +States::States(const QList &other): QList(other) +{ + +} + +QVariant States::get(int index) +{ + return QVariant::fromValue(at(index)); +} diff --git a/libnymea/types/state.h b/libnymea/types/state.h index 471115ca..969323af 100644 --- a/libnymea/types/state.h +++ b/libnymea/types/state.h @@ -32,7 +32,12 @@ class LIBNYMEA_EXPORT State { + Q_GADGET + Q_PROPERTY(QUuid stateTypeId READ stateTypeId) + Q_PROPERTY(QVariant value READ value) + public: + State(); State(const StateTypeId &stateTypeId, const DeviceId &deviceId); StateId id() const; @@ -49,6 +54,18 @@ private: DeviceId m_deviceId; QVariant m_value; }; +Q_DECLARE_METATYPE(State) + +class States: public QList +{ + Q_GADGET + Q_PROPERTY(int count READ count) +public: + States(); + States(const QList &other); + Q_INVOKABLE QVariant get(int index); +}; +Q_DECLARE_METATYPE(States) QDebug operator<<(QDebug dbg, const State &event); QDebug operator<<(QDebug dbg, const QList &events); diff --git a/libnymea/types/statetype.cpp b/libnymea/types/statetype.cpp index acbd55c9..6953f6e1 100644 --- a/libnymea/types/statetype.cpp +++ b/libnymea/types/statetype.cpp @@ -34,6 +34,11 @@ #include "statetype.h" +StateType::StateType() +{ + +} + /*! Constructs a StateType with the given \a id. * When creating a \l{DevicePlugin} generate a new uuid for each StateType you define and * hardcode it into the plugin json file. */ @@ -193,6 +198,11 @@ StateTypes::StateTypes(const QList &other) } } +QVariant StateTypes::get(int index) +{ + return QVariant::fromValue(at(index)); +} + StateType StateTypes::findByName(const QString &name) { foreach (const StateType &stateType, *this) { diff --git a/libnymea/types/statetype.h b/libnymea/types/statetype.h index 88d65a16..7a3a0905 100644 --- a/libnymea/types/statetype.h +++ b/libnymea/types/statetype.h @@ -32,7 +32,20 @@ class LIBNYMEA_EXPORT StateType { + Q_GADGET + Q_PROPERTY(QUuid id READ id) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + Q_PROPERTY(QVariant::Type type READ type WRITE setType) + Q_PROPERTY(int index READ index WRITE setIndex) + Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue) + Q_PROPERTY(Types::Unit unit READ unit WRITE setUnit USER true) + Q_PROPERTY(QVariant minValue READ minValue WRITE setMinValue USER true) + Q_PROPERTY(QVariant maxValue READ maxValue WRITE setMaxValue USER true) + Q_PROPERTY(QVariantList possibleValues READ possibleValues WRITE setPossibleValues USER true) + public: + StateType(); StateType(const StateTypeId &id); StateTypeId id() const; @@ -83,14 +96,19 @@ private: Types::Unit m_unit = Types::UnitNone; bool m_cached = true; }; +Q_DECLARE_METATYPE(StateType) class StateTypes: public QList { + Q_GADGET + Q_PROPERTY(int count READ count) public: StateTypes() = default; StateTypes(const QList &other); + Q_INVOKABLE QVariant get(int index); StateType findByName(const QString &name); StateType findById(const StateTypeId &id); }; +Q_DECLARE_METATYPE(StateTypes) #endif // STATETYPE_H diff --git a/libnymea/types/vendor.h b/libnymea/types/vendor.h index cdbb32ae..27010619 100644 --- a/libnymea/types/vendor.h +++ b/libnymea/types/vendor.h @@ -32,6 +32,11 @@ class LIBNYMEA_EXPORT Vendor { + Q_GADGET + Q_PROPERTY(QUuid id READ id WRITE setId) + Q_PROPERTY(QString name READ name WRITE setName) + Q_PROPERTY(QString displayName READ displayName WRITE setDisplayName) + public: Vendor(const VendorId &id, const QString &name = QString()); diff --git a/libnymea/typeutils.h b/libnymea/typeutils.h index d211d9ff..a8439a69 100644 --- a/libnymea/typeutils.h +++ b/libnymea/typeutils.h @@ -32,7 +32,7 @@ #define DECLARE_TYPE_ID(type) class type##Id: public QUuid \ { \ public: \ - type##Id(const QString &uuid): QUuid(uuid) {} \ + type##Id(const QUuid &uuid): QUuid(uuid) {} \ type##Id(): QUuid() {} \ static type##Id create##type##Id() { return type##Id(QUuid::createUuid().toString()); } \ static type##Id fromUuid(const QUuid &uuid) { return type##Id(uuid.toString()); } \ diff --git a/tests/scripts/getactiontype.sh b/tests/scripts/getactiontype.sh index 94f8d2be..38f5447f 100755 --- a/tests/scripts/getactiontype.sh +++ b/tests/scripts/getactiontype.sh @@ -2,6 +2,10 @@ if [ -z $2 ]; then echo "usage: $0 host actionTypeId" -else - (echo '{"id":1, "method":"Actions.GetActionType", "params":{"actionTypeId":"'$2'"}}'; sleep 1) | nc $1 2222 + exit 1; fi + +cat << EOD | nc $1 2222 +{"id":0, "method":"JSONRPC.Hello"} +{"id":1, "method":"Actions.GetActionType", "params":{"actionTypeId":"$2"}} +EOD diff --git a/tests/scripts/getactiontypes.sh b/tests/scripts/getactiontypes.sh index 0557d377..fb03af88 100755 --- a/tests/scripts/getactiontypes.sh +++ b/tests/scripts/getactiontypes.sh @@ -2,6 +2,11 @@ if [ -z $2 ]; then echo "usage: $0 host deviceClassId" -else - (echo '{"id":1, "method":"Devices.GetActionTypes", "params":{"deviceClassId":"'$2'"}}'; sleep 1) | nc $1 2222 + exit 1 fi + + +cat <" + exit 1 fi + +if [ -z $2 ]; then +cat <