From ff337bf8b604d3e639a70a9e1ed7164ad0076c6d Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Tue, 9 Jul 2019 01:37:33 +0200 Subject: [PATCH] Make browser item execution work async too --- doc/jsonrpc-api.qdoc | 5 +- .../devices/devicemanagerimplementation.cpp | 13 ++-- .../devices/devicemanagerimplementation.h | 7 +- libnymea-core/jsonrpc/actionhandler.cpp | 37 +++++++++++ libnymea-core/jsonrpc/actionhandler.h | 3 + libnymea-core/jsonrpc/devicehandler.cpp | 24 +------ libnymea-core/jsonrpc/devicehandler.h | 1 - libnymea-core/jsonrpc/jsontypes.cpp | 5 ++ libnymea-core/logging/logengine.cpp | 10 +++ libnymea-core/logging/logengine.h | 2 + libnymea-core/logging/logentry.h | 2 +- libnymea-core/logging/logging.h | 3 +- libnymea-core/nymeacore.cpp | 21 ++++++ libnymea-core/nymeacore.h | 4 ++ libnymea/devices/devicemanager.h | 8 ++- libnymea/devices/deviceplugin.cpp | 4 +- libnymea/devices/deviceplugin.h | 4 +- libnymea/libnymea.pro | 2 + libnymea/types/browseritem.cpp | 5 +- libnymea/types/browseritem.h | 4 +- libnymea/types/browseritemaction.cpp | 66 +++++++++++++++++++ libnymea/types/browseritemaction.h | 50 ++++++++++++++ plugins/mock/devicepluginmock.cpp | 59 ++++++++++++++--- plugins/mock/devicepluginmock.h | 3 +- 24 files changed, 287 insertions(+), 55 deletions(-) create mode 100644 libnymea/types/browseritemaction.cpp create mode 100644 libnymea/types/browseritemaction.h diff --git a/doc/jsonrpc-api.qdoc b/doc/jsonrpc-api.qdoc index b6370686..b0488c1a 100644 --- a/doc/jsonrpc-api.qdoc +++ b/doc/jsonrpc-api.qdoc @@ -3523,8 +3523,9 @@ See also: \l{Tag} "LoggingSourceEvents", "LoggingSourceActions", "LoggingSourceStates", - "LoggingSourceRules" - ], + "LoggingSourceRules", + "LoggingSourceBrowserActions" + ], "NetworkDeviceState": [ "NetworkDeviceStateUnknown", "NetworkDeviceStateUnmanaged", diff --git a/libnymea-core/devices/devicemanagerimplementation.cpp b/libnymea-core/devices/devicemanagerimplementation.cpp index 1f9a26bc..b45ae186 100644 --- a/libnymea-core/devices/devicemanagerimplementation.cpp +++ b/libnymea-core/devices/devicemanagerimplementation.cpp @@ -710,10 +710,10 @@ Device::DeviceError DeviceManagerImplementation::removeConfiguredDevice(const De return Device::DeviceErrorNoError; } -Device::BrowseResult DeviceManagerImplementation::browseDevice(const DeviceId &deviceId, const QString &nodeId) +Device::BrowseResult DeviceManagerImplementation::browseDevice(const DeviceId &deviceId, const QString &itemId) { Q_UNUSED(deviceId) - Q_UNUSED(nodeId) + Q_UNUSED(itemId) Device::BrowseResult result = createBrowseResult(); @@ -730,20 +730,20 @@ Device::BrowseResult DeviceManagerImplementation::browseDevice(const DeviceId &d return result; } - result = device->plugin()->browseDevice(device, result, nodeId); + result = device->plugin()->browseDevice(device, result, itemId); return result; } -Device::DeviceError DeviceManagerImplementation::executeBrowserItem(const DeviceId &deviceId, const QString &nodeId) +Device::DeviceError DeviceManagerImplementation::executeBrowserItem(const BrowserItemAction &browserItemAction) { - Device *device = m_configuredDevices.value(deviceId); + Device *device = m_configuredDevices.value(browserItemAction.deviceId()); if (!device) { return Device::DeviceErrorDeviceNotFound; } if (!device->deviceClass().browsable()) { return Device::DeviceErrorUnsupportedFeature; } - return device->plugin()->executeBrowserItem(device, nodeId); + return device->plugin()->executeBrowserItem(device, browserItemAction); } QString DeviceManagerImplementation::translate(const PluginId &pluginId, const QString &string, const QLocale &locale) @@ -1009,6 +1009,7 @@ void DeviceManagerImplementation::loadPlugin(DevicePlugin *pluginIface, const Pl connect(pluginIface, &DevicePlugin::autoDevicesAppeared, this, &DeviceManagerImplementation::onAutoDevicesAppeared); connect(pluginIface, &DevicePlugin::autoDeviceDisappeared, this, &DeviceManagerImplementation::onAutoDeviceDisappeared); connect(pluginIface, &DevicePlugin::browseRequestFinished, this, &DeviceManagerImplementation::browseRequestFinished); + connect(pluginIface, &DevicePlugin::browserItemExecutionFinished, this, &DeviceManagerImplementation::browserItemExecutionFinished); } diff --git a/libnymea-core/devices/devicemanagerimplementation.h b/libnymea-core/devices/devicemanagerimplementation.h index 86df086e..99437dfe 100644 --- a/libnymea-core/devices/devicemanagerimplementation.h +++ b/libnymea-core/devices/devicemanagerimplementation.h @@ -97,8 +97,10 @@ public: Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) override; - Device::BrowseResult browseDevice(const DeviceId &deviceId, const QString &nodeId = QString()) override; - Device::DeviceError executeBrowserItem(const DeviceId &deviceId, const QString &nodeId) override; + Device::DeviceError executeAction(const Action &action) override; + + Device::BrowseResult browseDevice(const DeviceId &deviceId, const QString &itemId = QString()) override; + Device::DeviceError executeBrowserItem(const BrowserItemAction &browserItemAction) override; QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override; @@ -106,7 +108,6 @@ signals: void loaded(); public slots: - Device::DeviceError executeAction(const Action &action); void timeTick(); private slots: diff --git a/libnymea-core/jsonrpc/actionhandler.cpp b/libnymea-core/jsonrpc/actionhandler.cpp index 2105e994..bb096dae 100644 --- a/libnymea-core/jsonrpc/actionhandler.cpp +++ b/libnymea-core/jsonrpc/actionhandler.cpp @@ -62,7 +62,16 @@ ActionHandler::ActionHandler(QObject *parent) : returns.insert("o:actionType", JsonTypes::actionTypeDescription()); setReturns("GetActionType", returns); + params.clear(); returns.clear(); + setDescription("ExecuteBrowserItem", "Execute the item identified by itemId on the given device."); + params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); + params.insert("o:itemId", JsonTypes::basicTypeToString(JsonTypes::String)); + setParams("ExecuteBrowserItem", params); + returns.insert("deviceError", JsonTypes::deviceErrorRef()); + setReturns("ExecuteBrowserItem", returns); + connect(NymeaCore::instance(), &NymeaCore::actionExecuted, this, &ActionHandler::actionExecuted); + connect(NymeaCore::instance(), &NymeaCore::browserItemExecuted, this, &ActionHandler::browserItemExecuted); } /*! Returns the name of the \l{ActionHandler}. In this case \b Actions.*/ @@ -119,4 +128,32 @@ void ActionHandler::actionExecuted(const ActionId &id, Device::DeviceError statu reply->finished(); } +JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap ¶ms) +{ + DeviceId deviceId = DeviceId(params.value("deviceId").toString()); + QString itemId = params.value("itemId").toString(); + BrowserItemAction action(deviceId, itemId); + Device::DeviceError status = NymeaCore::instance()->executeBrowserItem(action); + if (status == Device::DeviceErrorAsync) { + JsonReply *reply = createAsyncReply("ExecuteBrowserItem"); + ActionId id = action.id(); + connect(reply, &JsonReply::finished, [this, id](){ m_asyncActionExecutions.remove(id); }); + m_asyncActionExecutions.insert(id, reply); + return reply; + } + return createReply(statusToReply(status)); +} + +void ActionHandler::browserItemExecuted(const ActionId &id, Device::DeviceError status) +{ + if (!m_asyncActionExecutions.contains(id)) { + return; // Not the action we are waiting for. + } + + JsonReply *reply = m_asyncActionExecutions.take(id); + reply->setData(statusToReply(status)); + reply->finished(); +} + + } diff --git a/libnymea-core/jsonrpc/actionhandler.h b/libnymea-core/jsonrpc/actionhandler.h index d641c917..346ed920 100644 --- a/libnymea-core/jsonrpc/actionhandler.h +++ b/libnymea-core/jsonrpc/actionhandler.h @@ -38,8 +38,11 @@ public: Q_INVOKABLE JsonReply *ExecuteAction(const QVariantMap ¶ms); Q_INVOKABLE JsonReply *GetActionType(const QVariantMap ¶ms) const; + Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap ¶ms); + private slots: void actionExecuted(const ActionId &id, Device::DeviceError status); + void browserItemExecuted(const ActionId &id, Device::DeviceError status); private: QHash m_asyncActionExecutions; diff --git a/libnymea-core/jsonrpc/devicehandler.cpp b/libnymea-core/jsonrpc/devicehandler.cpp index 5f2deaf4..b4479818 100644 --- a/libnymea-core/jsonrpc/devicehandler.cpp +++ b/libnymea-core/jsonrpc/devicehandler.cpp @@ -286,20 +286,12 @@ DeviceHandler::DeviceHandler(QObject *parent) : params.clear(); returns.clear(); setDescription("BrowseDevice", "Browse a device. If a DeviceClass indicates a device is browsable, this method will return the BrowserItems. If no parameter besides the deviceId is used, the root node of this device will be returned. Any returned item which is browsable can be passed as node. Results will be children of the given node."); params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:nodeId", JsonTypes::basicTypeToString(JsonTypes::String)); + params.insert("o:itemId", JsonTypes::basicTypeToString(JsonTypes::String)); setParams("BrowseDevice", params); returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("items", QVariantList() << JsonTypes::browserItemRef()); setReturns("BrowseDevice", returns); - params.clear(); returns.clear(); - setDescription("ExecuteBrowserItem", "Execute the item identified by nodeId on the given device."); - params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); - params.insert("o:nodeId", JsonTypes::basicTypeToString(JsonTypes::String)); - setParams("ExecuteBrowserItem", params); - returns.insert("deviceError", JsonTypes::deviceErrorRef()); - setReturns("ExecuteBrowserItem", returns); - // Notifications params.clear(); returns.clear(); setDescription("StateChanged", "Emitted whenever a State of a device changes."); @@ -687,9 +679,9 @@ JsonReply *DeviceHandler::BrowseDevice(const QVariantMap ¶ms) const { QVariantMap returns; DeviceId deviceId = DeviceId(params.value("deviceId").toString()); - QString nodeId = params.value("nodeId").toString(); + QString itemId = params.value("itemId").toString(); - Device::BrowseResult result = NymeaCore::instance()->deviceManager()->browseDevice(deviceId, nodeId); + Device::BrowseResult result = NymeaCore::instance()->deviceManager()->browseDevice(deviceId, itemId); if (result.status == Device::DeviceErrorAsync ) { JsonReply *reply = createAsyncReply("BrowseDevice"); @@ -705,16 +697,6 @@ JsonReply *DeviceHandler::BrowseDevice(const QVariantMap ¶ms) const return createReply(returns); } -JsonReply *DeviceHandler::ExecuteBrowserItem(const QVariantMap ¶ms) -{ - DeviceId deviceId = DeviceId(params.value("deviceId").toString()); - QString nodeId = params.value("nodeId").toString(); - Device::DeviceError status = NymeaCore::instance()->deviceManager()->executeBrowserItem(deviceId, nodeId); - QVariantMap returns; - returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); - return createReply(returns); -} - void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config) { QVariantMap params; diff --git a/libnymea-core/jsonrpc/devicehandler.h b/libnymea-core/jsonrpc/devicehandler.h index 217de3ec..7ae2352a 100644 --- a/libnymea-core/jsonrpc/devicehandler.h +++ b/libnymea-core/jsonrpc/devicehandler.h @@ -58,7 +58,6 @@ public: Q_INVOKABLE JsonReply *GetStateValues(const QVariantMap ¶ms) const; Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap ¶ms) const; - Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap ¶ms); signals: void PluginConfigurationChanged(const QVariantMap ¶ms); diff --git a/libnymea-core/jsonrpc/jsontypes.cpp b/libnymea-core/jsonrpc/jsontypes.cpp index 4e8bc131..d7666ed9 100644 --- a/libnymea-core/jsonrpc/jsontypes.cpp +++ b/libnymea-core/jsonrpc/jsontypes.cpp @@ -335,6 +335,7 @@ void JsonTypes::init() s_logEntry.insert("source", loggingSourceRef()); s_logEntry.insert("o:typeId", basicTypeToString(Uuid)); s_logEntry.insert("o:deviceId", basicTypeToString(Uuid)); + s_logEntry.insert("o:itemId", basicTypeToString(String)); s_logEntry.insert("o:value", basicTypeToString(String)); s_logEntry.insert("o:active", basicTypeToString(Bool)); s_logEntry.insert("o:eventType", loggingEventTypeRef()); @@ -993,6 +994,7 @@ QVariantMap JsonTypes::packLogEntry(const LogEntry &logEntry) case Logging::LoggingSourceActions: case Logging::LoggingSourceEvents: case Logging::LoggingSourceStates: + case Logging::LoggingSourceBrowserActions: logEntryMap.insert("errorCode", s_deviceError.at(logEntry.errorCode())); break; case Logging::LoggingSourceSystem: @@ -1016,6 +1018,9 @@ QVariantMap JsonTypes::packLogEntry(const LogEntry &logEntry) case Logging::LoggingSourceRules: logEntryMap.insert("typeId", logEntry.typeId().toString()); break; + case Logging::LoggingSourceBrowserActions: + logEntryMap.insert("itemId", logEntry.value()); + break; } return logEntryMap; diff --git a/libnymea-core/logging/logengine.cpp b/libnymea-core/logging/logengine.cpp index f17a9352..c85186a8 100644 --- a/libnymea-core/logging/logengine.cpp +++ b/libnymea-core/logging/logengine.cpp @@ -108,6 +108,8 @@ This \l{LogEntry} was created from an \l{State} which hase changed. \value LoggingSourceRules This \l{LogEntry} represents the enable/disable event from an \l{Rule}. + \value LoggingSourceBrowserActions + This \l{LogEntry} was created from a \l{BrowserItemAction}. */ #include "nymeasettings.h" @@ -312,6 +314,14 @@ void LogEngine::logAction(const Action &action, Logging::LoggingLevel level, int appendLogEntry(entry); } +void LogEngine::logBrowserAction(const BrowserItemAction &browserItemAction, Logging::LoggingLevel level, int errorCode) +{ + LogEntry entry(level, Logging::LoggingSourceBrowserActions, errorCode); + entry.setDeviceId(browserItemAction.deviceId()); + entry.setValue(browserItemAction.itemId()); + appendLogEntry(entry); +} + void LogEngine::logRuleTriggered(const Rule &rule) { LogEntry entry(Logging::LoggingSourceRules); diff --git a/libnymea-core/logging/logengine.h b/libnymea-core/logging/logengine.h index 7115ecca..d115b404 100644 --- a/libnymea-core/logging/logengine.h +++ b/libnymea-core/logging/logengine.h @@ -26,6 +26,7 @@ #include "logfilter.h" #include "types/event.h" #include "types/action.h" +#include "types/browseritemaction.h" #include "ruleengine/rule.h" #include @@ -49,6 +50,7 @@ public: void logSystemEvent(const QDateTime &dateTime, bool active, Logging::LoggingLevel level = Logging::LoggingLevelInfo); void logEvent(const Event &event); void logAction(const Action &action, Logging::LoggingLevel level = Logging::LoggingLevelInfo, int errorCode = 0); + void logBrowserAction(const BrowserItemAction &browserItemAction, Logging::LoggingLevel level = Logging::LoggingLevelInfo, int errorCode = 0); void logRuleTriggered(const Rule &rule); void logRuleActiveChanged(const Rule &rule); void logRuleEnabledChanged(const Rule &rule, const bool &enabled); diff --git a/libnymea-core/logging/logentry.h b/libnymea-core/logging/logentry.h index f49c60ad..5cd8fb84 100644 --- a/libnymea-core/logging/logentry.h +++ b/libnymea-core/logging/logentry.h @@ -56,7 +56,7 @@ public: DeviceId deviceId() const; void setDeviceId(const DeviceId &deviceId); - // Valid for LoggingSourceStates + // Valid for LoggingSourceStates, LoggingSourceBrowserActions QVariant value() const; void setValue(const QVariant &value); diff --git a/libnymea-core/logging/logging.h b/libnymea-core/logging/logging.h index e07d3622..f4e13517 100644 --- a/libnymea-core/logging/logging.h +++ b/libnymea-core/logging/logging.h @@ -42,7 +42,8 @@ public: LoggingSourceEvents, LoggingSourceActions, LoggingSourceStates, - LoggingSourceRules + LoggingSourceRules, + LoggingSourceBrowserActions, }; Q_ENUM(LoggingSource) Q_FLAGS(LoggingSources) diff --git a/libnymea-core/nymeacore.cpp b/libnymea-core/nymeacore.cpp index 102276f6..cb8fbfb4 100644 --- a/libnymea-core/nymeacore.cpp +++ b/libnymea-core/nymeacore.cpp @@ -201,6 +201,7 @@ void NymeaCore::init() { connect(m_deviceManager, &DeviceManagerImplementation::deviceRemoved, this, &NymeaCore::deviceRemoved); connect(m_deviceManager, &DeviceManagerImplementation::deviceDisappeared, this, &NymeaCore::onDeviceDisappeared); connect(m_deviceManager, &DeviceManagerImplementation::actionExecutionFinished, this, &NymeaCore::actionExecutionFinished); + connect(m_deviceManager, &DeviceManagerImplementation::browserItemExecutionFinished, this, &NymeaCore::browserItemExecutionFinished); connect(m_deviceManager, &DeviceManagerImplementation::devicesDiscovered, this, &NymeaCore::devicesDiscovered); connect(m_deviceManager, &DeviceManagerImplementation::deviceSetupFinished, this, &NymeaCore::deviceSetupFinished); connect(m_deviceManager, &DeviceManagerImplementation::deviceReconfigurationFinished, this, &NymeaCore::deviceReconfigurationFinished); @@ -447,6 +448,19 @@ Device::DeviceError NymeaCore::executeAction(const Action &action) return ret; } +Device::DeviceError NymeaCore::executeBrowserItem(const BrowserItemAction &browserItemAction) +{ + Device::DeviceError ret = m_deviceManager->executeBrowserItem(browserItemAction); + if (ret == Device::DeviceErrorNoError) { + m_logger->logBrowserAction(browserItemAction); + } else if (ret == Device::DeviceErrorAsync) { + m_pendingBrowserItemActions.insert(browserItemAction.id(), browserItemAction); + } else { + m_logger->logBrowserAction(browserItemAction, Logging::LoggingLevelAlert, ret); + } + return ret; +} + /*! Execute the given \a ruleActions. */ void NymeaCore::executeRuleActions(const QList ruleActions) { @@ -797,6 +811,13 @@ void NymeaCore::actionExecutionFinished(const ActionId &id, Device::DeviceError m_logger->logAction(action, status == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, status); } +void NymeaCore::browserItemExecutionFinished(const ActionId &id, Device::DeviceError status) +{ + emit browserItemExecuted(id, status); + Action action = m_pendingActions.take(id); + m_logger->logAction(action, status == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, status); +} + void NymeaCore::onDeviceDisappeared(const DeviceId &deviceId) { Device *device = m_deviceManager->findConfiguredDevice(deviceId); diff --git a/libnymea-core/nymeacore.h b/libnymea-core/nymeacore.h index f05db29f..e3d1e888 100644 --- a/libnymea-core/nymeacore.h +++ b/libnymea-core/nymeacore.h @@ -72,6 +72,7 @@ public: Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId, const RuleEngine::RemovePolicy &removePolicy); Device::DeviceError executeAction(const Action &action); + Device::DeviceError executeBrowserItem(const BrowserItemAction &browserItemAction); void executeRuleActions(const QList ruleActions); @@ -106,6 +107,7 @@ signals: void deviceChanged(Device *device); void deviceSettingChanged(const DeviceId deviceId, const ParamTypeId &settingParamTypeId, const QVariant &value); void actionExecuted(const ActionId &id, Device::DeviceError status); + void browserItemExecuted(const ActionId &id, Device::DeviceError status); void devicesDiscovered(const DeviceClassId &deviceClassId, const QList deviceDescriptors); void deviceSetupFinished(Device *device, Device::DeviceError status); @@ -139,12 +141,14 @@ private: System *m_system; QHash m_pendingActions; + QHash m_pendingBrowserItemActions; QList m_executingRules; private slots: void gotEvent(const Event &event); void onDateTimeChanged(const QDateTime &dateTime); void actionExecutionFinished(const ActionId &id, Device::DeviceError status); + void browserItemExecutionFinished(const ActionId &id, Device::DeviceError status); void onDeviceDisappeared(const DeviceId &deviceId); void deviceManagerLoaded(); diff --git a/libnymea/devices/devicemanager.h b/libnymea/devices/devicemanager.h index ef77f1cd..d1fe3290 100644 --- a/libnymea/devices/devicemanager.h +++ b/libnymea/devices/devicemanager.h @@ -30,6 +30,7 @@ #include "types/interface.h" #include "types/vendor.h" #include "types/browseritem.h" +#include "types/browseritemaction.h" class DeviceManager : public QObject { @@ -70,8 +71,10 @@ public: virtual Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) = 0; - virtual Device::BrowseResult browseDevice(const DeviceId &deviceId, const QString &nodeId = QString()) = 0; - virtual Device::DeviceError executeBrowserItem(const DeviceId &deviceId, const QString &nodeId) = 0; + virtual Device::DeviceError executeAction(const Action &action) = 0; + + virtual Device::BrowseResult browseDevice(const DeviceId &deviceId, const QString &itemId = QString()) = 0; + virtual Device::DeviceError executeBrowserItem(const BrowserItemAction &browserItemAction) = 0; virtual QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0; @@ -90,6 +93,7 @@ signals: void pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId = DeviceId()); void actionExecutionFinished(const ActionId &actionId, Device::DeviceError status); void browseRequestFinished(const Device::BrowseResult &result); + void browserItemExecutionFinished(const ActionId &actionId, Device::DeviceError status); protected: Device::BrowseResult createBrowseResult(); diff --git a/libnymea/devices/deviceplugin.cpp b/libnymea/devices/deviceplugin.cpp index 5d826aa7..05e30e13 100644 --- a/libnymea/devices/deviceplugin.cpp +++ b/libnymea/devices/deviceplugin.cpp @@ -257,10 +257,10 @@ Device::BrowseResult DevicePlugin::browseDevice(Device *device, Device::BrowseRe return result; } -Device::DeviceError DevicePlugin::executeBrowserItem(Device *device, const QString &nodeId) +Device::DeviceError DevicePlugin::executeBrowserItem(Device *device, const BrowserItemAction &browserItemAction) { Q_UNUSED(device) - Q_UNUSED(nodeId) + Q_UNUSED(browserItemAction) return Device::DeviceErrorUnsupportedFeature; } diff --git a/libnymea/devices/deviceplugin.h b/libnymea/devices/deviceplugin.h index 29e9e0f6..3d28293d 100644 --- a/libnymea/devices/deviceplugin.h +++ b/libnymea/devices/deviceplugin.h @@ -37,6 +37,7 @@ #include "types/vendor.h" #include "types/param.h" #include "types/interface.h" +#include "types/browseritemaction.h" #include "hardwaremanager.h" @@ -79,7 +80,7 @@ public: virtual Device::DeviceError executeAction(Device *device, const Action &action); virtual Device::BrowseResult browseDevice(Device *device, Device::BrowseResult result, const QString &nodeId = QString()); - virtual Device::DeviceError executeBrowserItem(Device *device, const QString &nodeId); + virtual Device::DeviceError executeBrowserItem(Device *device, const BrowserItemAction &browserItemAction); // Configuration ParamTypes configurationDescription() const; @@ -100,6 +101,7 @@ signals: void autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList &deviceDescriptors); void autoDeviceDisappeared(const DeviceId &deviceId); void browseRequestFinished(const Device::BrowseResult &result); + void browserItemExecutionFinished(const ActionId &actionid, Device::DeviceError status); protected: Devices myDevices() const; diff --git a/libnymea/libnymea.pro b/libnymea/libnymea.pro index 4e06ec2a..21f46c81 100644 --- a/libnymea/libnymea.pro +++ b/libnymea/libnymea.pro @@ -16,6 +16,7 @@ HEADERS += \ platform/package.h \ platform/repository.h \ types/browseritem.h \ + types/browseritemaction.h \ types/mediabrowseritem.h \ typeutils.h \ loggingcategories.h \ @@ -113,6 +114,7 @@ SOURCES += \ coap/corelink.cpp \ coap/coapobserveresource.cpp \ types/browseritem.cpp \ + types/browseritemaction.cpp \ types/mediabrowseritem.cpp \ types/deviceclass.cpp \ types/action.cpp \ diff --git a/libnymea/types/browseritem.cpp b/libnymea/types/browseritem.cpp index 58c745c4..77af9ae7 100644 --- a/libnymea/types/browseritem.cpp +++ b/libnymea/types/browseritem.cpp @@ -23,10 +23,11 @@ #include "browseritem.h" -BrowserItem::BrowserItem(const QString &id, const QString &displayName, bool browsable): +BrowserItem::BrowserItem(const QString &id, const QString &displayName, bool browsable, bool executable): m_id(id), m_displayName(displayName), - m_browsable(browsable) + m_browsable(browsable), + m_executable(executable) { } diff --git a/libnymea/types/browseritem.h b/libnymea/types/browseritem.h index cce473a8..7bbd14cb 100644 --- a/libnymea/types/browseritem.h +++ b/libnymea/types/browseritem.h @@ -56,7 +56,7 @@ public: Q_DECLARE_FLAGS(ExtendedPropertiesFlags, ExtendedProperties) - BrowserItem(const QString &id = QString(), const QString &displayName = QString(), bool browsable = false); + BrowserItem(const QString &id = QString(), const QString &displayName = QString(), bool browsable = false, bool executable = false); QString id() const; void setId(const QString &id); @@ -86,8 +86,8 @@ private: QString m_id; QString m_displayName; QString m_description; - bool m_executable = false; bool m_browsable = false; + bool m_executable = false; BrowserIcon m_icon = BrowserIconNone; QString m_thumbnail; diff --git a/libnymea/types/browseritemaction.cpp b/libnymea/types/browseritemaction.cpp new file mode 100644 index 00000000..e9236482 --- /dev/null +++ b/libnymea/types/browseritemaction.cpp @@ -0,0 +1,66 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#include "browseritemaction.h" + +BrowserItemAction::BrowserItemAction(const DeviceId &deviceId, const QString &itemId): + m_id(ActionId::createActionId()), + m_deviceId(deviceId), + m_itemId(itemId) +{ + +} + +BrowserItemAction::BrowserItemAction(const BrowserItemAction &other): + m_id(other.id()), + m_deviceId(other.deviceId()), + m_itemId(other.itemId()) +{ + +} + +ActionId BrowserItemAction::id() const +{ + return m_id; +} + +bool BrowserItemAction::isValid() const +{ + return !m_id.isNull() && !m_deviceId.isNull() && !m_itemId.isNull(); +} + +DeviceId BrowserItemAction::deviceId() const +{ + return m_deviceId; +} + +QString BrowserItemAction::itemId() const +{ + return m_itemId; +} + +void BrowserItemAction::operator=(const BrowserItemAction &other) +{ + m_id = other.id(); + m_deviceId = other.deviceId(); + m_itemId = other.itemId(); +} diff --git a/libnymea/types/browseritemaction.h b/libnymea/types/browseritemaction.h new file mode 100644 index 00000000..e5ee311d --- /dev/null +++ b/libnymea/types/browseritemaction.h @@ -0,0 +1,50 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * Copyright (C) 2019 Michael Zanetti * + * * + * This file is part of nymea. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with this library; If not, see * + * . * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef BROWSERITEMACTION_H +#define BROWSERITEMACTION_H + +#include "typeutils.h" + +class BrowserItemAction +{ +public: + BrowserItemAction(); + + explicit BrowserItemAction(const DeviceId &deviceId = DeviceId(), const QString &itemId = QString()); + BrowserItemAction(const BrowserItemAction &other); + + ActionId id() const; + + bool isValid() const; + + DeviceId deviceId() const; + QString itemId() const; + + void operator=(const BrowserItemAction &other); +private: + ActionId m_id; + DeviceId m_deviceId; + QString m_itemId; +}; + +#endif // BROWSERITEMACTION_H diff --git a/plugins/mock/devicepluginmock.cpp b/plugins/mock/devicepluginmock.cpp index 4bd5e398..531031dd 100644 --- a/plugins/mock/devicepluginmock.cpp +++ b/plugins/mock/devicepluginmock.cpp @@ -393,6 +393,24 @@ Device::DeviceError DevicePluginMock::executeAction(Device *device, const Action return Device::DeviceErrorDeviceClassNotFound; } +Device::DeviceError DevicePluginMock::executeBrowserItem(Device *device, const BrowserItemAction &browserItemAction) +{ + bool broken = device->paramValue(mockDeviceBrokenParamTypeId).toBool(); + bool async = device->paramValue(mockDeviceAsyncParamTypeId).toBool(); + + if (!async){ + if (broken) { + return Device::DeviceErrorHardwareFailure; + } + return Device::DeviceErrorNoError; + } + + QTimer::singleShot(2000, device, [this, broken, browserItemAction](){ + emit this->browserItemExecutionFinished(browserItemAction.id(), broken ? Device::DeviceErrorHardwareFailure : Device::DeviceErrorNoError); + }); + return Device::DeviceErrorAsync; +} + void DevicePluginMock::setState(const StateTypeId &stateTypeId, const QVariant &value) { HttpDaemon *daemon = qobject_cast(sender()); @@ -591,32 +609,53 @@ void DevicePluginMock::onPluginConfigChanged() } -Device::BrowseResult DevicePluginMock::generateBrowseItems(const QString &nodeId, Device::BrowseResult result) +Device::BrowseResult DevicePluginMock::generateBrowseItems(const QString &itemId, Device::BrowseResult result) { result.status = Device::DeviceErrorNoError; - if (nodeId.isEmpty()) { - result.items.append(BrowserItem("0", "Item 0", true)); - result.items.append(BrowserItem("1", "Item 1")); - result.items.append(BrowserItem("2", "Item 2", true)); - result.items.append(BrowserItem("3", "Item 3")); - result.items.append(BrowserItem("4", "Item 4")); + if (itemId.isEmpty()) { + BrowserItem item = BrowserItem("0", "Item 0", true); + item.setDescription("I'm a folder"); + item.setIcon(BrowserItem::BrowserIconFolder); + result.items.append(item); + + item = BrowserItem("1", "Item 1", false, true); + item.setDescription("I'm executable"); + item.setIcon(BrowserItem::BrowserIconApplication); + result.items.append(item); + + item = BrowserItem("2", "Item 2", false, true); + item.setDescription("I'm a file"); + item.setIcon(BrowserItem::BrowserIconFile); + result.items.append(item); + + item = BrowserItem("3", "Item 3", false, true); + item.setDescription("I have a nice thumbnail"); + item.setIcon(BrowserItem::BrowserIconFile); + item.setThumbnail("https://github.com/guh/nymea/raw/master/icons/nymea-logo-256x256.png"); + result.items.append(item); + + item = BrowserItem("4", "Item 4", false, false); + item.setDescription("I'm disabled"); + item.setIcon(BrowserItem::BrowserIconFile); + result.items.append(item); + } - else if (nodeId == "0") { + else if (itemId == "0") { result.items.append(BrowserItem("5", "Item 5")); result.items.append(BrowserItem("6", "Item 6")); result.items.append(BrowserItem("7", "Item 7")); result.items.append(BrowserItem("8", "Item 8")); result.items.append(BrowserItem("9", "Item 9")); } - else if (nodeId == "2") { + else if (itemId == "2") { result.items.append(BrowserItem("10", "Item 10", true)); result.items.append(BrowserItem("11", "Item 11")); result.items.append(BrowserItem("12", "Item 12")); result.items.append(BrowserItem("13", "Item 13")); result.items.append(BrowserItem("14", "Item 14")); } - else if (nodeId == "10") { + else if (itemId == "10") { result.items.append(BrowserItem("15", "Item 15")); result.items.append(BrowserItem("16", "Item 16")); } else { diff --git a/plugins/mock/devicepluginmock.h b/plugins/mock/devicepluginmock.h index 2081fa24..521a3e17 100644 --- a/plugins/mock/devicepluginmock.h +++ b/plugins/mock/devicepluginmock.h @@ -56,6 +56,7 @@ public: public slots: Device::DeviceError executeAction(Device *device, const Action &action) override; + Device::DeviceError executeBrowserItem(Device *device, const BrowserItemAction &browserItemAction) override; private slots: void setState(const StateTypeId &stateTypeId, const QVariant &value); @@ -75,7 +76,7 @@ private slots: void onPluginConfigChanged(); private: - Device::BrowseResult generateBrowseItems(const QString &nodeId, Device::BrowseResult result); + Device::BrowseResult generateBrowseItems(const QString &itemId, Device::BrowseResult result); private: QHash m_daemons;