BrowserItemActions, yay!

This commit is contained in:
Michael Zanetti 2019-07-10 10:55:34 +02:00
parent 968f1fe2fa
commit aee554a1ee
32 changed files with 542 additions and 114 deletions

View File

@ -734,7 +734,19 @@ Device::BrowseResult DeviceManagerImplementation::browseDevice(const DeviceId &d
return result;
}
Device::DeviceError DeviceManagerImplementation::executeBrowserItem(const BrowserItemAction &browserItemAction)
Device::DeviceError DeviceManagerImplementation::executeBrowserItem(const BrowserAction &browserAction)
{
Device *device = m_configuredDevices.value(browserAction.deviceId());
if (!device) {
return Device::DeviceErrorDeviceNotFound;
}
if (!device->deviceClass().browsable()) {
return Device::DeviceErrorUnsupportedFeature;
}
return device->plugin()->executeBrowserItem(device, browserAction);
}
Device::DeviceError DeviceManagerImplementation::executeBrowserItemAction(const BrowserItemAction &browserItemAction)
{
Device *device = m_configuredDevices.value(browserItemAction.deviceId());
if (!device) {
@ -743,7 +755,9 @@ Device::DeviceError DeviceManagerImplementation::executeBrowserItem(const Browse
if (!device->deviceClass().browsable()) {
return Device::DeviceErrorUnsupportedFeature;
}
return device->plugin()->executeBrowserItem(device, browserItemAction);
// TODO: check browserItemAction.params with deviceClass
return device->plugin()->executeBrowserItemAction(device, browserItemAction);
}
QString DeviceManagerImplementation::translate(const PluginId &pluginId, const QString &string, const QLocale &locale)
@ -879,6 +893,7 @@ void DeviceManagerImplementation::loadPlugins()
loader.setFileName(fi.absoluteFilePath());
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
qCDebug(dcDeviceManager()) << "Loading plugin from:" << fi.absoluteFilePath();
if (!loader.load()) {
qCWarning(dcDeviceManager) << "Could not load plugin data of" << entry << "\n" << loader.errorString();
continue;

View File

@ -100,7 +100,8 @@ public:
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;
Device::DeviceError executeBrowserItem(const BrowserAction &browserAction) override;
Device::DeviceError executeBrowserItemAction(const BrowserItemAction &browserItemAction) override;
QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override;

View File

@ -65,11 +65,21 @@ ActionHandler::ActionHandler(QObject *parent) :
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));
params.insert("itemId", JsonTypes::basicTypeToString(JsonTypes::String));
setParams("ExecuteBrowserItem", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef());
setReturns("ExecuteBrowserItem", returns);
params.clear(); returns.clear();
setDescription("ExecuteBrowserItemAction", "Execute the action for the browser item identified by actionTypeId and the itemId on the given device.");
params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("itemId", JsonTypes::basicTypeToString(JsonTypes::String));
params.insert("actionTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:params", QVariantList() << JsonTypes::paramRef());
setParams("ExecuteBrowserItemAction", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef());
setReturns("ExecuteBrowserItemAction", returns);
connect(NymeaCore::instance(), &NymeaCore::actionExecuted, this, &ActionHandler::actionExecuted);
connect(NymeaCore::instance(), &NymeaCore::browserItemExecuted, this, &ActionHandler::browserItemExecuted);
}
@ -132,7 +142,7 @@ JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap &params)
{
DeviceId deviceId = DeviceId(params.value("deviceId").toString());
QString itemId = params.value("itemId").toString();
BrowserItemAction action(deviceId, itemId);
BrowserAction action(deviceId, itemId);
Device::DeviceError status = NymeaCore::instance()->executeBrowserItem(action);
if (status == Device::DeviceErrorAsync) {
JsonReply *reply = createAsyncReply("ExecuteBrowserItem");
@ -144,6 +154,25 @@ JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap &params)
return createReply(statusToReply(status));
}
JsonReply *ActionHandler::ExecuteBrowserItemAction(const QVariantMap &params)
{
DeviceId deviceId = DeviceId(params.value("deviceId").toString());
QString itemId = params.value("itemId").toString();
ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString());
ParamList paramList = JsonTypes::unpackParams(params.value("params").toList());
BrowserItemAction browserItemAction(deviceId, itemId, actionTypeId, paramList);
Device::DeviceError status = NymeaCore::instance()->executeBrowserItemAction(browserItemAction);
if (status == Device::DeviceErrorAsync) {
JsonReply *reply = createAsyncReply("ExecuteBrowserItemAction");
ActionId id = browserItemAction.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)) {
@ -155,5 +184,16 @@ void ActionHandler::browserItemExecuted(const ActionId &id, Device::DeviceError
reply->finished();
}
void ActionHandler::browserItemActionExecuted(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();
}
}

View File

@ -39,10 +39,12 @@ public:
Q_INVOKABLE JsonReply *GetActionType(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap &params);
Q_INVOKABLE JsonReply *ExecuteBrowserItemAction(const QVariantMap &params);
private slots:
void actionExecuted(const ActionId &id, Device::DeviceError status);
void browserItemExecuted(const ActionId &id, Device::DeviceError status);
void browserItemActionExecuted(const ActionId &id, Device::DeviceError status);
private:
QHash<ActionId, JsonReply *> m_asyncActionExecutions;

View File

@ -286,6 +286,7 @@ void JsonTypes::init()
s_deviceClass.insert("stateTypes", QVariantList() << stateTypeRef());
s_deviceClass.insert("eventTypes", QVariantList() << eventTypeRef());
s_deviceClass.insert("actionTypes", QVariantList() << actionTypeRef());
s_deviceClass.insert("browserItemActionTypes", QVariantList() << actionTypeRef());
s_deviceClass.insert("paramTypes", QVariantList() << paramTypeRef());
s_deviceClass.insert("settingsTypes", QVariantList() << paramTypeRef());
s_deviceClass.insert("discoveryParamTypes", QVariantList() << paramTypeRef());
@ -436,6 +437,8 @@ void JsonTypes::init()
s_browserItem.insert("thumbnail", basicTypeToString(QVariant::String));
s_browserItem.insert("executable", basicTypeToString(QVariant::Bool));
s_browserItem.insert("browsable", basicTypeToString(QVariant::Bool));
s_browserItem.insert("disabled", basicTypeToString(QVariant::Bool));
s_browserItem.insert("actionTypeIds", QVariantList() << basicTypeToString(QVariant::Uuid));
s_browserItem.insert("o:mediaIcon", mediaBrowserIconRef());
s_initialized = true;
@ -743,6 +746,12 @@ QVariantMap JsonTypes::packBrowserItem(const BrowserItem &item)
ret.insert("thumbnail", item.thumbnail());
ret.insert("executable", item.executable());
ret.insert("browsable", item.browsable());
ret.insert("disabled", item.disabled());
QVariantList actionTypeIds;
foreach (const ActionTypeId &id, item.actionTypeIds()) {
actionTypeIds.append(id.toString());
}
ret.insert("actionTypeIds", actionTypeIds);
return ret;
}
@ -844,6 +853,10 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass, const QLo
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 &paramType, deviceClass.paramTypes())
paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale));
@ -862,6 +875,7 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass, const QLo
variant.insert("stateTypes", stateTypes);
variant.insert("eventTypes", eventTypes);
variant.insert("actionTypes", actionTypes);
variant.insert("browserItemActionTypes", browserItemActionTypes);
variant.insert("createMethods", packCreateMethods(deviceClass.createMethods()));
variant.insert("setupMethod", s_setupMethod.at(deviceClass.setupMethod()));
return variant;

View File

@ -314,10 +314,19 @@ void LogEngine::logAction(const Action &action, Logging::LoggingLevel level, int
appendLogEntry(entry);
}
void LogEngine::logBrowserAction(const BrowserItemAction &browserItemAction, Logging::LoggingLevel level, int errorCode)
void LogEngine::logBrowserAction(const BrowserAction &browserAction, Logging::LoggingLevel level, int errorCode)
{
LogEntry entry(level, Logging::LoggingSourceBrowserActions, errorCode);
entry.setDeviceId(browserAction.deviceId());
entry.setValue(browserAction.itemId());
appendLogEntry(entry);
}
void LogEngine::logBrowserItemAction(const BrowserItemAction &browserItemAction, Logging::LoggingLevel level, int errorCode)
{
LogEntry entry(level, Logging::LoggingSourceBrowserActions, errorCode);
entry.setDeviceId(browserItemAction.deviceId());
entry.setTypeId(browserItemAction.actionTypeId());
entry.setValue(browserItemAction.itemId());
appendLogEntry(entry);
}

View File

@ -27,6 +27,7 @@
#include "types/event.h"
#include "types/action.h"
#include "types/browseritemaction.h"
#include "types/browseraction.h"
#include "ruleengine/rule.h"
#include <QObject>
@ -50,7 +51,8 @@ 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 logBrowserAction(const BrowserAction &browserAction, Logging::LoggingLevel level = Logging::LoggingLevelInfo, int errorCode = 0);
void logBrowserItemAction(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);

View File

@ -448,15 +448,28 @@ Device::DeviceError NymeaCore::executeAction(const Action &action)
return ret;
}
Device::DeviceError NymeaCore::executeBrowserItem(const BrowserItemAction &browserItemAction)
Device::DeviceError NymeaCore::executeBrowserItem(const BrowserAction &browserAction)
{
Device::DeviceError ret = m_deviceManager->executeBrowserItem(browserItemAction);
Device::DeviceError ret = m_deviceManager->executeBrowserItem(browserAction);
if (ret == Device::DeviceErrorNoError) {
m_logger->logBrowserAction(browserItemAction);
m_logger->logBrowserAction(browserAction);
} else if (ret == Device::DeviceErrorAsync) {
m_pendingBrowserActions.insert(browserAction.id(), browserAction);
} else {
m_logger->logBrowserAction(browserAction, Logging::LoggingLevelAlert, ret);
}
return ret;
}
Device::DeviceError NymeaCore::executeBrowserItemAction(const BrowserItemAction &browserItemAction)
{
Device::DeviceError ret = m_deviceManager->executeBrowserItemAction(browserItemAction);
if (ret == Device::DeviceErrorNoError) {
m_logger->logBrowserItemAction(browserItemAction);
} else if (ret == Device::DeviceErrorAsync) {
m_pendingBrowserItemActions.insert(browserItemAction.id(), browserItemAction);
} else {
m_logger->logBrowserAction(browserItemAction, Logging::LoggingLevelAlert, ret);
m_logger->logBrowserItemAction(browserItemAction, Logging::LoggingLevelAlert, ret);
}
return ret;
}
@ -814,8 +827,15 @@ void NymeaCore::actionExecutionFinished(const ActionId &id, Device::DeviceError
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);
BrowserAction action = m_pendingBrowserActions.take(id);
m_logger->logBrowserAction(action, status == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, status);
}
void NymeaCore::browserItemActionExecutionFinished(const ActionId &id, Device::DeviceError status)
{
emit browserItemActionExecuted(id, status);
BrowserItemAction action = m_pendingBrowserItemActions.take(id);
m_logger->logBrowserItemAction(action, status == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, status);
}
void NymeaCore::onDeviceDisappeared(const DeviceId &deviceId)

View File

@ -72,7 +72,8 @@ public:
Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId, const RuleEngine::RemovePolicy &removePolicy);
Device::DeviceError executeAction(const Action &action);
Device::DeviceError executeBrowserItem(const BrowserItemAction &browserItemAction);
Device::DeviceError executeBrowserItem(const BrowserAction &browserAction);
Device::DeviceError executeBrowserItemAction(const BrowserItemAction &browserItemAction);
void executeRuleActions(const QList<RuleAction> ruleActions);
@ -108,6 +109,7 @@ signals:
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 browserItemActionExecuted(const ActionId &id, Device::DeviceError status);
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
void deviceSetupFinished(Device *device, Device::DeviceError status);
@ -141,6 +143,7 @@ private:
System *m_system;
QHash<ActionId, Action> m_pendingActions;
QHash<ActionId, BrowserAction> m_pendingBrowserActions;
QHash<ActionId, BrowserItemAction> m_pendingBrowserItemActions;
QList<RuleId> m_executingRules;
@ -149,6 +152,7 @@ private slots:
void onDateTimeChanged(const QDateTime &dateTime);
void actionExecutionFinished(const ActionId &id, Device::DeviceError status);
void browserItemExecutionFinished(const ActionId &id, Device::DeviceError status);
void browserItemActionExecutionFinished(const ActionId &id, Device::DeviceError status);
void onDeviceDisappeared(const DeviceId &deviceId);
void deviceManagerLoaded();

View File

@ -71,6 +71,7 @@ public:
DeviceErrorDeviceIsChild,
DeviceErrorPairingTransactionIdNotFound,
DeviceErrorParameterNotWritable,
DeviceErrorItemNotFound,
DeviceErrorUnsupportedFeature,
};
Q_ENUM(DeviceError)

View File

@ -30,6 +30,7 @@
#include "types/interface.h"
#include "types/vendor.h"
#include "types/browseritem.h"
#include "types/browseraction.h"
#include "types/browseritemaction.h"
class DeviceManager : public QObject
@ -74,7 +75,8 @@ public:
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 Device::DeviceError executeBrowserItem(const BrowserAction &browserAction) = 0;
virtual Device::DeviceError executeBrowserItemAction(const BrowserItemAction &browserItemAction) = 0;
virtual QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0;
@ -94,6 +96,7 @@ signals:
void actionExecutionFinished(const ActionId &actionId, Device::DeviceError status);
void browseRequestFinished(const Device::BrowseResult &result);
void browserItemExecutionFinished(const ActionId &actionId, Device::DeviceError status);
void browserItemActionExecutionFinished(const ActionId &actionId, Device::DeviceError status);
protected:
Device::BrowseResult createBrowseResult();

View File

@ -248,16 +248,43 @@ Device::DeviceError DevicePlugin::executeAction(Device *device, const Action &ac
return Device::DeviceErrorNoError;
}
Device::BrowseResult DevicePlugin::browseDevice(Device *device, Device::BrowseResult result, const QString &nodeId)
/*! Implement this if your devices support browsing. When the system calls this method,
* fill the \a result object's items list with entries from the browser. If \a itemId is empty
* it means that the root node of the file system should be returned. Each item in the result set
* shall be uniquely identifiable using its \l{BrowserItem::id}{id} property.
* The system might call this method again, with an \a itemId returned in a previous query, provided
* that item's \l{BrowserItem::browsable} property is true. In this case all children of the given
* item shall be returned.
* When done, set the \l{BrowserResult::status}{result's status} field approprietly. Set the result's
* status to Device::DeviceErrorAsync if this operation requires async behavior and emit
* \l{browseRequestFinished} when done.
*/
Device::BrowseResult DevicePlugin::browseDevice(Device *device, Device::BrowseResult result, const QString &itemId)
{
Q_UNUSED(device)
Q_UNUSED(nodeId)
Q_UNUSED(itemId)
result.status = Device::DeviceErrorUnsupportedFeature;
return result;
}
Device::DeviceError DevicePlugin::executeBrowserItem(Device *device, const BrowserItemAction &browserItemAction)
/*! Implement this if your devices support browsing and execute the itemId defined in \a browserAction.
* Return Device::DeviceErrorAsync if this operation requires async behavior and emit
* \l{browserItemExecutionFinished} when done.
*/
Device::DeviceError DevicePlugin::executeBrowserItem(Device *device, const BrowserAction &browserAction)
{
Q_UNUSED(device)
Q_UNUSED(browserAction)
return Device::DeviceErrorUnsupportedFeature;
}
/*! Implement this if your devices support browsing and execute the item's action for the itemId defined
* in \a browserItemAction.
* Return Device::DeviceErrorAsync if this operation requires async behavior and emit
* \l{browserItemActionExecutionFinished} when done.
*/
Device::DeviceError DevicePlugin::executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction)
{
Q_UNUSED(device)
Q_UNUSED(browserItemAction)

View File

@ -37,6 +37,7 @@
#include "types/vendor.h"
#include "types/param.h"
#include "types/interface.h"
#include "types/browseraction.h"
#include "types/browseritemaction.h"
#include "hardwaremanager.h"
@ -80,7 +81,8 @@ 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 BrowserItemAction &browserItemAction);
virtual Device::DeviceError executeBrowserItem(Device *device, const BrowserAction &browserAction);
virtual Device::DeviceError executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction);
// Configuration
ParamTypes configurationDescription() const;
@ -102,6 +104,7 @@ signals:
void autoDeviceDisappeared(const DeviceId &deviceId);
void browseRequestFinished(const Device::BrowseResult &result);
void browserItemExecutionFinished(const ActionId &actionid, Device::DeviceError status);
void browserItemActionExecutionFinished(const ActionId &actionid, Device::DeviceError status);
protected:
Devices myDevices() const;

View File

@ -163,7 +163,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
/*! Returns a list of all valid JSON properties a DeviceClass JSON definition can have. */
QStringList deviceClassProperties = QStringList() << "id" << "name" << "displayName" << "createMethods" << "setupMethod"
<< "interfaces" << "browsable" << "pairingInfo" << "discoveryParamTypes" << "discoveryParamTypes"
<< "paramTypes" << "settingsTypes" << "stateTypes" << "actionTypes" << "eventTypes";
<< "paramTypes" << "settingsTypes" << "stateTypes" << "actionTypes" << "eventTypes" << "browserItemActionTypes";
QStringList mandatoryDeviceClassProperties = QStringList() << "id" << "name" << "displayName";
QPair<QStringList, QStringList> verificationResult = verifyFields(deviceClassProperties, mandatoryDeviceClassProperties, deviceClassObject);
@ -261,9 +261,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
// Read pairing info
deviceClass.setPairingInfo(deviceClassObject.value("pairingInfo").toString());
QList<ActionType> actionTypes;
QList<StateType> stateTypes;
QList<EventType> eventTypes;
ActionTypes actionTypes;
StateTypes stateTypes;
EventTypes eventTypes;
ActionTypes browserItemActionTypes;
// Read StateTypes
int index = 0;
@ -458,6 +459,48 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
}
deviceClass.setEventTypes(eventTypes);
// BrowserItemActionTypes
index = 0;
foreach (const QJsonValue &browserItemActionTypesJson, deviceClassObject.value("browserItemActionTypes").toArray()) {
QJsonObject at = browserItemActionTypesJson.toObject();
QPair<QStringList, QStringList> verificationResult = verifyFields(ActionType::typeProperties(), ActionType::mandatoryTypeProperties(), at);
// Check mandatory fields
if (!verificationResult.first.isEmpty()) {
qCWarning(dcPluginMetadata()) << "Device class" << deviceClass.name() << " has missing fields" << verificationResult.first.join(", ") << "in browser item action type:" << endl << at;
hasError = true;
continue;
}
// Check if there are any unknown fields
if (!verificationResult.second.isEmpty()) {
qCWarning(dcPluginMetadata()) << pluginName() << "Device class" << deviceClass.name() << "has unknown fields:" << verificationResult.second.join(", ") << "in browser item action type:" << endl << at;
hasError = true;
}
ActionTypeId actionTypeId = ActionTypeId(at.value("id").toString());
QString actionTypeName = at.value("name").toString();
if (!verifyDuplicateUuid(actionTypeId)) {
qCWarning(dcPluginMetadata()) << "Browser Action Type" << actionTypeName << "has duplicate UUID:" << actionTypeId.toString();
hasError = true;
}
ActionType actionType(actionTypeId);
actionType.setName(actionTypeName);
actionType.setDisplayName(at.value("displayName").toString());
actionType.setIndex(index++);
QPair<bool, QList<ParamType> > paramVerification = parseParamTypes(at.value("paramTypes").toArray());
if (!paramVerification.first) {
hasError = true;
break;
} else {
actionType.setParamTypes(paramVerification.second);
}
browserItemActionTypes.append(actionType);
}
deviceClass.setBrowserItemActionTypes(browserItemActionTypes);
// Read interfaces
QStringList interfaces;
foreach (const QJsonValue &value, deviceClassObject.value("interfaces").toArray()) {
@ -617,6 +660,7 @@ QPair<QStringList, QStringList> PluginMetadata::verifyFields(const QStringList &
QPair<bool, ParamTypes> PluginMetadata::parseParamTypes(const QJsonArray &array)
{
bool hasErrors = false;
int index = 0;
QList<ParamType> paramTypes;
foreach (const QJsonValue &paramTypesJson, array) {
@ -627,13 +671,14 @@ QPair<bool, ParamTypes> PluginMetadata::parseParamTypes(const QJsonArray &array)
// Check mandatory fields
if (!verificationResult.first.isEmpty()) {
qCWarning(dcPluginMetadata()) << pluginName() << "Error parsing ParamType: missing fields:" << verificationResult.first.join(", ") << endl << pt;
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
hasErrors = true;
continue;
}
// Check if there are any unknown fields
if (!verificationResult.second.isEmpty()) {
qCWarning(dcPluginMetadata()) << pluginName() << "Error parsing ParamType: unknown fields:" << verificationResult.second.join(", ") << endl << pt;
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
hasErrors = true;
}
// Check type
@ -642,14 +687,14 @@ QPair<bool, ParamTypes> PluginMetadata::parseParamTypes(const QJsonArray &array)
qCWarning(dcPluginMetadata()) << pluginName() << QString("Invalid type %1 for param %2 in json file.")
.arg(pt.value("type").toString())
.arg(pt.value("name").toString()).toLatin1().data();
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
hasErrors = true;
}
ParamTypeId paramTypeId = ParamTypeId(pt.value("id").toString());
QString paramName = pt.value("name").toString();
if (!verifyDuplicateUuid(paramTypeId)) {
qCWarning(dcPluginMetadata()) << "Param" << paramName << "has duplicate UUID:" << paramTypeId.toString();
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
hasErrors = true;
}
ParamType paramType(paramTypeId, paramName, t, pt.value("defaultValue").toVariant());
paramType.setDisplayName(pt.value("displayName").toString());
@ -666,7 +711,7 @@ QPair<bool, ParamTypes> PluginMetadata::parseParamTypes(const QJsonArray &array)
QPair<bool, Types::InputType> inputTypeVerification = loadAndVerifyInputType(pt.value("inputType").toString());
if (!inputTypeVerification.first) {
qCWarning(dcPluginMetadata()) << pluginName() << QString("Invalid inputType for paramType") << pt;
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
hasErrors = true;
} else {
paramType.setInputType(inputTypeVerification.second);
}
@ -677,7 +722,7 @@ QPair<bool, ParamTypes> PluginMetadata::parseParamTypes(const QJsonArray &array)
QPair<bool, Types::Unit> unitVerification = loadAndVerifyUnit(pt.value("unit").toString());
if (!unitVerification.first) {
qCWarning(dcPluginMetadata()) << pluginName() << QString("Invalid unit type for paramType") << pt;
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
hasErrors = true;
} else {
paramType.setUnit(unitVerification.second);
}
@ -693,7 +738,7 @@ QPair<bool, ParamTypes> PluginMetadata::parseParamTypes(const QJsonArray &array)
paramTypes.append(paramType);
}
return QPair<bool, QList<ParamType> >(true, paramTypes);
return QPair<bool, QList<ParamType> >(!hasErrors, paramTypes);
}
QPair<bool, Types::InputType> PluginMetadata::loadAndVerifyInputType(const QString &inputType)

View File

@ -16,7 +16,8 @@ HEADERS += \
platform/package.h \
platform/repository.h \
types/browseritem.h \
types/browseritemaction.h \
types/browseritemaction.h \
types/browseraction.h \
types/mediabrowseritem.h \
typeutils.h \
loggingcategories.h \
@ -114,7 +115,8 @@ SOURCES += \
coap/corelink.cpp \
coap/coapobserveresource.cpp \
types/browseritem.cpp \
types/browseritemaction.cpp \
types/browseritemaction.cpp \
types/browseraction.cpp \
types/mediabrowseritem.cpp \
types/deviceclass.cpp \
types/action.cpp \

View File

@ -142,3 +142,9 @@ ActionType ActionTypes::findById(const ActionTypeId &id)
}
return ActionType(ActionTypeId());
}
QDebug operator<<(QDebug dbg, const ActionType &actionType)
{
dbg.nospace().noquote() << "ActionType: " << actionType.name() << actionType.displayName() << actionType.id();
return dbg;
}

View File

@ -60,6 +60,8 @@ private:
ParamTypes m_paramTypes;
};
QDebug operator<<(QDebug dbg, const ActionType &actionType);
class ActionTypes: public QList<ActionType>
{
public:

View File

@ -0,0 +1,66 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "browseraction.h"
BrowserAction::BrowserAction(const DeviceId &deviceId, const QString &itemId):
m_id(ActionId::createActionId()),
m_deviceId(deviceId),
m_itemId(itemId)
{
}
BrowserAction::BrowserAction(const BrowserAction &other):
m_id(other.id()),
m_deviceId(other.deviceId()),
m_itemId(other.itemId())
{
}
ActionId BrowserAction::id() const
{
return m_id;
}
bool BrowserAction::isValid() const
{
return !m_id.isNull() && !m_deviceId.isNull() && !m_itemId.isNull();
}
DeviceId BrowserAction::deviceId() const
{
return m_deviceId;
}
QString BrowserAction::itemId() const
{
return m_itemId;
}
void BrowserAction::operator=(const BrowserAction &other)
{
m_id = other.id();
m_deviceId = other.deviceId();
m_itemId = other.itemId();
}

View File

@ -0,0 +1,48 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* Copyright (C) 2019 Michael Zanetti <michael.zanetti@nymea.io> *
* *
* 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 *
* <http://www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#ifndef BROWSERACTION_H
#define BROWSERACTION_H
#include "typeutils.h"
class BrowserAction
{
public:
explicit BrowserAction(const DeviceId &deviceId = DeviceId(), const QString &itemId = QString());
BrowserAction(const BrowserAction &other);
ActionId id() const;
bool isValid() const;
DeviceId deviceId() const;
QString itemId() const;
void operator=(const BrowserAction &other);
private:
ActionId m_id;
DeviceId m_deviceId;
QString m_itemId;
};
#endif // BROWSERACTION_H

View File

@ -77,6 +77,16 @@ void BrowserItem::setBrowsable(bool browsable)
m_browsable = browsable;
}
bool BrowserItem::disabled() const
{
return m_disabled;
}
void BrowserItem::setDisabled(bool disabled)
{
m_disabled = disabled;
}
BrowserItem::BrowserIcon BrowserItem::icon() const
{
return m_icon;

View File

@ -73,6 +73,9 @@ public:
bool browsable() const;
void setBrowsable(bool browsable);
bool disabled() const;
void setDisabled(bool disabled);
BrowserIcon icon() const;
void setIcon(BrowserIcon icon);
@ -91,6 +94,7 @@ private:
QString m_description;
bool m_browsable = false;
bool m_executable = false;
bool m_disabled = false;
BrowserIcon m_icon = BrowserIconNone;
QString m_thumbnail;

View File

@ -22,10 +22,13 @@
#include "browseritemaction.h"
BrowserItemAction::BrowserItemAction(const DeviceId &deviceId, const QString &itemId):
BrowserItemAction::BrowserItemAction(const DeviceId &deviceId, const QString &itemId, const ActionTypeId &actionTypeId, const ParamList &params):
m_id(ActionId::createActionId()),
m_deviceId(deviceId),
m_itemId(itemId)
m_itemId(itemId),
m_actionTypeId(actionTypeId),
m_params(params)
{
}
@ -33,7 +36,9 @@ BrowserItemAction::BrowserItemAction(const DeviceId &deviceId, const QString &it
BrowserItemAction::BrowserItemAction(const BrowserItemAction &other):
m_id(other.id()),
m_deviceId(other.deviceId()),
m_itemId(other.itemId())
m_itemId(other.itemId()),
m_actionTypeId(other.actionTypeId()),
m_params(other.params())
{
}
@ -58,9 +63,21 @@ QString BrowserItemAction::itemId() const
return m_itemId;
}
ActionTypeId BrowserItemAction::actionTypeId() const
{
return m_actionTypeId;
}
ParamList BrowserItemAction::params() const
{
return m_params;
}
void BrowserItemAction::operator=(const BrowserItemAction &other)
{
m_id = other.id();
m_deviceId = other.deviceId();
m_itemId = other.itemId();
m_actionTypeId = other.actionTypeId();
m_params = other.params();
}

View File

@ -24,13 +24,12 @@
#define BROWSERITEMACTION_H
#include "typeutils.h"
#include "types/param.h"
class BrowserItemAction
{
public:
BrowserItemAction();
explicit BrowserItemAction(const DeviceId &deviceId = DeviceId(), const QString &itemId = QString());
explicit BrowserItemAction(const DeviceId &deviceId = DeviceId(), const QString &itemId = QString(), const ActionTypeId &actionTypeId = ActionTypeId(), const ParamList &params = ParamList());
BrowserItemAction(const BrowserItemAction &other);
ActionId id() const;
@ -39,12 +38,19 @@ public:
DeviceId deviceId() const;
QString itemId() const;
ActionTypeId actionTypeId() const;
ParamList params() const;
void setParams(const ParamList &params);
Param param(const ParamTypeId &paramTypeId) const;
void operator=(const BrowserItemAction &other);
private:
ActionId m_id;
DeviceId m_deviceId;
QString m_itemId;
ActionTypeId m_actionTypeId;
ParamList m_params;
};
#endif // BROWSERITEMACTION_H

View File

@ -213,24 +213,24 @@ bool DeviceClass::hasActionType(const ActionTypeId &actionTypeId)
return false;
}
/*! Returns the browserActionTypes of this DeviceClass. \{Device}{Devices} created
/*! Returns the browserItemActionTypes of this DeviceClass. \{Device}{Devices} created
from this \l{DeviceClass} may set those actions to their browser items. */
ActionTypes DeviceClass::browserActionTypes() const
ActionTypes DeviceClass::browserItemActionTypes() const
{
return m_browserActionTypes;
return m_browserItemActionTypes;
}
/*! Set the \a browserActionTypes of this DeviceClass. \{Device}{Devices} created
from this \l{DeviceClass} may set those actions to their browser items. */
void DeviceClass::setBrowserActionTypes(const ActionTypes &browserActionTypes)
void DeviceClass::setBrowserItemActionTypes(const ActionTypes &browserItemActionTypes)
{
m_browserActionTypes = browserActionTypes;
m_browserItemActionTypes = browserItemActionTypes;
}
/*! Returns true if this DeviceClass has a \l{ActionType} with the given \a actionTypeId. */
bool DeviceClass::hasBrowserActionType(const ActionTypeId &actionTypeId)
bool DeviceClass::hasBrowserItemActionType(const ActionTypeId &actionTypeId)
{
foreach (const ActionType &actionType, m_actionTypes) {
foreach (const ActionType &actionType, m_browserItemActionTypes) {
if (actionType.id() == actionTypeId) {
return true;
}
@ -333,11 +333,13 @@ void DeviceClass::setInterfaces(const QStringList &interfaces)
m_interfaces = interfaces;
}
/*! Returns whether \l{Device}{Devices} created from this \l{DeviceClass} are browsable */
bool DeviceClass::browsable() const
{
return m_browsable;
}
/*! Sets whether \l{Device}{Devices} created from this \l{DeviceClass} are browsable */
void DeviceClass::setBrowsable(bool browsable)
{
m_browsable = browsable;

View File

@ -82,9 +82,12 @@ public:
void setActionTypes(const ActionTypes &actionTypes);
bool hasActionType(const ActionTypeId &actionTypeId);
ActionTypes browserActionTypes() const;
void setBrowserActionTypes(const ActionTypes &browserActionTypes);
bool hasBrowserActionType(const ActionTypeId &actionTypeId);
bool browsable() const;
void setBrowsable(bool browsable);
ActionTypes browserItemActionTypes() const;
void setBrowserItemActionTypes(const ActionTypes &browserItemActionTypes);
bool hasBrowserItemActionType(const ActionTypeId &actionTypeId);
ParamTypes paramTypes() const;
void setParamTypes(const ParamTypes &paramTypes);
@ -107,9 +110,6 @@ public:
QStringList interfaces() const;
void setInterfaces(const QStringList &interfaces);
bool browsable() const;
void setBrowsable(bool browsable);
bool operator==(const DeviceClass &device) const;
private:
@ -122,7 +122,7 @@ private:
StateTypes m_stateTypes;
EventTypes m_eventTypes;
ActionTypes m_actionTypes;
ActionTypes m_browserActionTypes;
ActionTypes m_browserItemActionTypes;
ParamTypes m_paramTypes;
ParamTypes m_settingsTypes;
ParamTypes m_discoveryParamTypes;

View File

@ -51,7 +51,7 @@
DevicePluginMock::DevicePluginMock()
{
generateBrowseItems();
}
DevicePluginMock::~DevicePluginMock()
@ -239,17 +239,21 @@ Device::DeviceError DevicePluginMock::displayPin(const PairingTransactionId &pai
return Device::DeviceErrorNoError;
}
Device::BrowseResult DevicePluginMock::browseDevice(Device *device, Device::BrowseResult result, const QString &nodeId)
Device::BrowseResult DevicePluginMock::browseDevice(Device *device, Device::BrowseResult result, const QString &itemId)
{
qCDebug(dcMockDevice()) << "Browse device called" << device;
if (device->deviceClassId() == mockDeviceClassId) {
if (device->paramValue(mockDeviceAsyncParamTypeId).toBool()) {
result.status = Device::DeviceErrorAsync;
QTimer::singleShot(1000, device, [this, device, result, nodeId]() mutable {
QTimer::singleShot(1000, device, [this, device, result, itemId]() mutable {
if (device->paramValue(mockDeviceBrokenParamTypeId).toBool()) {
result.status = Device::DeviceErrorHardwareFailure;
} else {
result = generateBrowseItems(nodeId, result);
VirtualFsNode *node = m_virtualFs->findNode(itemId);
foreach (VirtualFsNode *child, node->childs) {
result.items.append(child->item);
}
result.status = Device::DeviceErrorNoError;
}
emit browseRequestFinished(result);
});
@ -257,7 +261,11 @@ Device::BrowseResult DevicePluginMock::browseDevice(Device *device, Device::Brow
else if (device->paramValue(mockDeviceBrokenParamTypeId).toBool()) {
result.status = Device::DeviceErrorHardwareFailure;
} else {
result = generateBrowseItems(nodeId, result);
VirtualFsNode *node = m_virtualFs->findNode(itemId);
foreach (VirtualFsNode *child, node->childs) {
result.items.append(child->item);
}
result.status = Device::DeviceErrorNoError;
}
}
return result;
@ -393,8 +401,9 @@ Device::DeviceError DevicePluginMock::executeAction(Device *device, const Action
return Device::DeviceErrorDeviceClassNotFound;
}
Device::DeviceError DevicePluginMock::executeBrowserItem(Device *device, const BrowserItemAction &browserItemAction)
Device::DeviceError DevicePluginMock::executeBrowserItem(Device *device, const BrowserAction &browserAction)
{
qCDebug(dcMockDevice()) << "ExecuteBrowserItem called";
bool broken = device->paramValue(mockDeviceBrokenParamTypeId).toBool();
bool async = device->paramValue(mockDeviceAsyncParamTypeId).toBool();
@ -405,12 +414,46 @@ Device::DeviceError DevicePluginMock::executeBrowserItem(Device *device, const B
return Device::DeviceErrorNoError;
}
QTimer::singleShot(2000, device, [this, broken, browserItemAction](){
emit this->browserItemExecutionFinished(browserItemAction.id(), broken ? Device::DeviceErrorHardwareFailure : Device::DeviceErrorNoError);
QTimer::singleShot(2000, device, [this, broken, browserAction](){
emit this->browserItemExecutionFinished(browserAction.id(), broken ? Device::DeviceErrorHardwareFailure : Device::DeviceErrorNoError);
});
return Device::DeviceErrorAsync;
}
Device::DeviceError DevicePluginMock::executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction)
{
qCDebug(dcMockDevice()) << "TODO" << device << browserItemAction.id();
if (browserItemAction.actionTypeId() == mockAddToFavoritesBrowserItemActionTypeId) {
VirtualFsNode *node = m_virtualFs->findNode(browserItemAction.itemId());
if (!node) {
return Device::DeviceErrorInvalidParameter;
}
VirtualFsNode *favoritesNode = m_virtualFs->findNode("favorites");
if (favoritesNode->findNode(browserItemAction.itemId())) {
return Device::DeviceErrorDeviceInUse;
}
BrowserItem newItem = node->item;
newItem.setActionTypeIs({mockRemoveFromFavoritesBrowserItemActionTypeId});
VirtualFsNode *newNode = new VirtualFsNode(newItem);
favoritesNode->addChild(newNode);
return Device::DeviceErrorNoError;
}
if (browserItemAction.actionTypeId() == mockRemoveFromFavoritesBrowserItemActionTypeId) {
VirtualFsNode *favoritesNode = m_virtualFs->findNode("favorites");
VirtualFsNode *nodeToRemove = favoritesNode->findNode(browserItemAction.itemId());
if (!nodeToRemove) {
return Device::DeviceErrorItemNotFound;
}
int idx = favoritesNode->childs.indexOf(nodeToRemove);
delete favoritesNode->childs.takeAt(idx);
return Device::DeviceErrorNoError;
}
return Device::DeviceErrorActionTypeNotFound;
}
void DevicePluginMock::setState(const StateTypeId &stateTypeId, const QVariant &value)
{
HttpDaemon *daemon = qobject_cast<HttpDaemon*>(sender());
@ -609,58 +652,42 @@ void DevicePluginMock::onPluginConfigChanged()
}
Device::BrowseResult DevicePluginMock::generateBrowseItems(const QString &itemId, Device::BrowseResult result)
void DevicePluginMock::generateBrowseItems()
{
result.status = Device::DeviceErrorNoError;
m_virtualFs = new VirtualFsNode(BrowserItem());
if (itemId.isEmpty()) {
BrowserItem item = BrowserItem("0", "Item 0", true);
item.setDescription("I'm a folder");
item.setIcon(BrowserItem::BrowserIconFolder);
result.items.append(item);
BrowserItem item = BrowserItem(QUuid::createUuid().toString(), "Item 0", true);
item.setDescription("I'm a folder");
item.setIcon(BrowserItem::BrowserIconFolder);
m_virtualFs->addChild(new VirtualFsNode(item));
item = BrowserItem("1", "Item 1", false, true);
item.setDescription("I'm executable");
item.setIcon(BrowserItem::BrowserIconApplication);
result.items.append(item);
item = BrowserItem(QUuid::createUuid().toString(), "Item 1", false, true);
item.setDescription("I'm executable");
item.setIcon(BrowserItem::BrowserIconApplication);
item.setActionTypeIs({mockAddToFavoritesBrowserItemActionTypeId});
m_virtualFs->addChild(new VirtualFsNode(item));
item = BrowserItem("2", "Item 2", false, true);
item.setDescription("I'm a file");
item.setIcon(BrowserItem::BrowserIconFile);
result.items.append(item);
item = BrowserItem(QUuid::createUuid().toString(), "Item 2", false, true);
item.setDescription("I'm a file");
item.setIcon(BrowserItem::BrowserIconFile);
item.setActionTypeIs({mockAddToFavoritesBrowserItemActionTypeId});
m_virtualFs->addChild(new VirtualFsNode(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(QUuid::createUuid().toString(), "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");
item.setActionTypeIs({mockAddToFavoritesBrowserItemActionTypeId});
m_virtualFs->addChild(new VirtualFsNode(item));
item = BrowserItem("4", "Item 4", false, false);
item.setDescription("I'm disabled");
item.setIcon(BrowserItem::BrowserIconFile);
result.items.append(item);
item = BrowserItem(QUuid::createUuid().toString(), "Item 4", false, false);
item.setDescription("I'm disabled");
item.setDisabled(true);
item.setIcon(BrowserItem::BrowserIconFile);
m_virtualFs->addChild(new VirtualFsNode(item));
}
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 (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 (itemId == "10") {
result.items.append(BrowserItem("15", "Item 15"));
result.items.append(BrowserItem("16", "Item 16"));
} else {
result.status = Device::DeviceErrorInvalidParameter;
}
return result;
item = BrowserItem("favorites", "Favorites", true, false);
item.setDescription("Yay! I'm the best!");
item.setIcon(BrowserItem::BrowserIconFavorites);
m_virtualFs->addChild(new VirtualFsNode(item));
}

View File

@ -52,11 +52,12 @@ public:
Device::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) override;
Device::DeviceError displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) override;
Device::BrowseResult browseDevice(Device *device, Device::BrowseResult result, const QString &nodeId = QString()) override;
Device::BrowseResult browseDevice(Device *device, Device::BrowseResult result, const QString &itemId = QString()) override;
public slots:
Device::DeviceError executeAction(Device *device, const Action &action) override;
Device::DeviceError executeBrowserItem(Device *device, const BrowserItemAction &browserItemAction) override;
Device::DeviceError executeBrowserItem(Device *device, const BrowserAction &browserAction) override;
Device::DeviceError executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction) override;
private slots:
void setState(const StateTypeId &stateTypeId, const QVariant &value);
@ -76,9 +77,25 @@ private slots:
void onPluginConfigChanged();
private:
Device::BrowseResult generateBrowseItems(const QString &itemId, Device::BrowseResult result);
void generateBrowseItems();
private:
class VirtualFsNode {
public:
VirtualFsNode(const BrowserItem &item):item(item) {}
BrowserItem item;
QList<VirtualFsNode*> childs;
void addChild(VirtualFsNode* child) {childs.append(child); }
VirtualFsNode *findNode(const QString &id) {
if (item.id() == id) return this;
foreach (VirtualFsNode *child, childs) {
VirtualFsNode *node = child->findNode(id);
if (node) return node;
}
return nullptr;
}
};
QHash<Device*, HttpDaemon*> m_daemons;
QList<Device*> m_asyncSetupDevices;
QList<QPair<Action, Device*> > m_asyncActions;
@ -87,6 +104,8 @@ private:
int m_discoveredDeviceCount;
bool m_pushbuttonPressed;
VirtualFsNode* m_virtualFs = nullptr;
};
#endif // DEVICEPLUGINMOCK_H

View File

@ -195,11 +195,16 @@
"displayName": "Mock Action 5 (async, broken)"
}
],
"brwserItemActionTypes": [
"browserItemActionTypes": [
{
"id": "00b8f0a8-99ca-4aa4-833d-59eb8d4d6de3",
"name": "addToFolder",
"displayName": "Add to Favorites"
"name": "addToFavorites",
"displayName": "Add to favorites"
},
{
"id": "da6faef8-2816-430e-93bb-57e8f9582d29",
"name": "removeFromFavorites",
"displayName": "Remove from favorites"
}
]
},

View File

@ -50,6 +50,8 @@ extern ActionTypeId mockWithoutParamsActionTypeId;
extern ActionTypeId mockAsyncActionTypeId;
extern ActionTypeId mockFailingActionTypeId;
extern ActionTypeId mockAsyncFailingActionTypeId;
extern ActionTypeId mockAddToFavoritesBrowserItemActionTypeId;
extern ActionTypeId mockRemoveFromFavoritesBrowserItemActionTypeId;
extern DeviceClassId mockDeviceAutoDeviceClassId;
extern ParamTypeId mockDeviceAutoDeviceHttpportParamTypeId;
extern ParamTypeId mockDeviceAutoDeviceAsyncParamTypeId;

View File

@ -54,6 +54,8 @@ ActionTypeId mockWithoutParamsActionTypeId = ActionTypeId("{defd3ed6-1a0d-400b-8
ActionTypeId mockAsyncActionTypeId = ActionTypeId("{fbae06d3-7666-483e-a39e-ec50fe89054e}");
ActionTypeId mockFailingActionTypeId = ActionTypeId("{df3cf33d-26d5-4577-9132-9823bd33fad0}");
ActionTypeId mockAsyncFailingActionTypeId = ActionTypeId("{bfe89a1d-3497-4121-8318-e77c37537219}");
ActionTypeId mockAddToFavoritesBrowserItemActionTypeId = ActionTypeId("{00b8f0a8-99ca-4aa4-833d-59eb8d4d6de3}");
ActionTypeId mockRemoveFromFavoritesBrowserItemActionTypeId = ActionTypeId("{da6faef8-2816-430e-93bb-57e8f9582d29}");
DeviceClassId mockDeviceAutoDeviceClassId = DeviceClassId("{ab4257b3-7548-47ee-9bd4-7dc3004fd197}");
ParamTypeId mockDeviceAutoDeviceHttpportParamTypeId = ParamTypeId("{bfeb0613-dab6-408c-aa27-c362c921d0d1}");
ParamTypeId mockDeviceAutoDeviceAsyncParamTypeId = ParamTypeId("{a5c4315f-0624-4971-87c1-4bbfbfdbd16e}");
@ -247,6 +249,9 @@ ActionTypeId mockInputTypeWritableTimestampUIntActionTypeId = ActionTypeId("{45d
ParamTypeId mockInputTypeWritableTimestampUIntActionWritableTimestampUIntParamTypeId = ParamTypeId("{45d0069a-63ac-4265-8170-8152778608ee}");
const QString translations[] {
//: The name of the Browser Item ActionType ({00b8f0a8-99ca-4aa4-833d-59eb8d4d6de3}) of DeviceClass mock
QT_TRANSLATE_NOOP("mockDevice", "Add to favorites"),
//: The name of the ParamType (DeviceClass: mockInputType, EventType: bool, ID: {3bad3a09-5826-4ed7-a832-10e3e2ee2a7d})
QT_TRANSLATE_NOOP("mockDevice", "Bool"),
@ -412,6 +417,9 @@ const QString translations[] {
//: The pairing info of deviceClass mockDisplayPin
QT_TRANSLATE_NOOP("mockDevice", "Please enter the secret which normaly will be displayed on the device. For the mockdevice the pin is 243681."),
//: The name of the Browser Item ActionType ({da6faef8-2816-430e-93bb-57e8f9582d29}) of DeviceClass mock
QT_TRANSLATE_NOOP("mockDevice", "Remove from favorites"),
//: The name of the ParamType (DeviceClass: mockInputType, Type: device, ID: {22add8c9-ee4f-43ad-8931-58e999313ac3})
QT_TRANSLATE_NOOP("mockDevice", "Search text"),

View File

@ -228,6 +228,7 @@ void PluginInfoCompiler::writeDeviceClass(const DeviceClass &deviceClass)
writeStateTypes(deviceClass.stateTypes(), deviceClass.name());
writeEventTypes(deviceClass.eventTypes(), deviceClass.name());
writeActionTypes(deviceClass.actionTypes(), deviceClass.name());
writeBrowserItemActionTypes(deviceClass.browserItemActionTypes(), deviceClass.name());
}
void PluginInfoCompiler::writeStateTypes(const StateTypes &stateTypes, const QString &deviceClassName)
@ -276,8 +277,24 @@ void PluginInfoCompiler::writeActionTypes(const ActionTypes &actionTypes, const
writeExtern(QString("extern ActionTypeId %1;").arg(variableName));
writeParams(actionType.paramTypes(), deviceClassName, "Action", actionType.name());
}
}
}
void PluginInfoCompiler::writeBrowserItemActionTypes(const ActionTypes &actionTypes, const QString &deviceClassName)
{
foreach (const ActionType &actionType, actionTypes) {
QString variableName = QString("%1%2BrowserItemActionTypeId").arg(deviceClassName, actionType.name()[0].toUpper() + actionType.name().right(actionType.name().length() - 1));
if (m_variableNames.contains(variableName)) {
qWarning().nospace() << "Error: Duplicate name " << variableName << " for Browser Item ActionType " << actionType.name() << " in DeviceClass " << deviceClassName << ". Skipping entry.";
return;
}
m_variableNames.append(variableName);
write(QString("ActionTypeId %1 = ActionTypeId(\"%2\");").arg(variableName).arg(actionType.id().toString()));
m_translationStrings.insert(actionType.displayName(), QString("The name of the Browser Item ActionType (%1) of DeviceClass %2").arg(actionType.id().toString()).arg(deviceClassName));
writeExtern(QString("extern ActionTypeId %1;").arg(variableName));
writeParams(actionType.paramTypes(), deviceClassName, "BrowserItemAction", actionType.name());
}
}
void PluginInfoCompiler::write(const QString &line)

View File

@ -45,6 +45,7 @@ private:
void writeStateTypes(const StateTypes &stateTypes, const QString &deviceClassName);
void writeEventTypes(const EventTypes &eventTypes, const QString &deviceClassName);
void writeActionTypes(const ActionTypes &actionTypes, const QString &deviceClassName);
void writeBrowserItemActionTypes(const ActionTypes &actionTypes, const QString &deviceClassName);
void write(const QString &line = QString());
void writeExtern(const QString &line = QString());