More work on adding a Device browser

pull/183/head
Michael Zanetti 2019-07-04 13:32:47 +02:00
parent 933d92ab06
commit 57f68bcdc0
21 changed files with 382 additions and 20 deletions

View File

@ -710,12 +710,40 @@ Device::DeviceError DeviceManagerImplementation::removeConfiguredDevice(const De
return Device::DeviceErrorNoError;
}
BrowserItems DeviceManagerImplementation::browseDevice(const DeviceId &deviceId, const QString &browser, const BrowserItemId &node)
Device::BrowseResult DeviceManagerImplementation::browseDevice(const DeviceId &deviceId, const QString &nodeId)
{
Q_UNUSED(deviceId)
Q_UNUSED(browser)
Q_UNUSED(node)
return BrowserItems();
Q_UNUSED(nodeId)
Device::BrowseResult result = createBrowseResult();
Device *device = m_configuredDevices.value(deviceId);
if (!device) {
qCWarning(dcDeviceManager()) << "Cannot browse device. No such device:" << deviceId.toString();
result.status = Device::DeviceErrorDeviceNotFound;
return result;
}
if (!device->deviceClass().browsable()) {
qCWarning(dcDeviceManager()) << "Cannot browse device. DeviceClass" << device->deviceClass().name() << "is not browsable.";
result.status = Device::DeviceErrorUnsupportedFeature;
return result;
}
result = device->plugin()->browseDevice(device, result, nodeId);
return result;
}
Device::DeviceError DeviceManagerImplementation::executeBrowserItem(const DeviceId &deviceId, const QString &nodeId)
{
Device *device = m_configuredDevices.value(deviceId);
if (!device) {
return Device::DeviceErrorDeviceNotFound;
}
if (!device->deviceClass().browsable()) {
return Device::DeviceErrorUnsupportedFeature;
}
return device->plugin()->executeBrowserItem(device, nodeId);
}
QString DeviceManagerImplementation::translate(const PluginId &pluginId, const QString &string, const QLocale &locale)
@ -980,6 +1008,7 @@ void DeviceManagerImplementation::loadPlugin(DevicePlugin *pluginIface, const Pl
connect(pluginIface, &DevicePlugin::pairingFinished, this, &DeviceManagerImplementation::slotPairingFinished);
connect(pluginIface, &DevicePlugin::autoDevicesAppeared, this, &DeviceManagerImplementation::onAutoDevicesAppeared);
connect(pluginIface, &DevicePlugin::autoDeviceDisappeared, this, &DeviceManagerImplementation::onAutoDeviceDisappeared);
connect(pluginIface, &DevicePlugin::browseRequestFinished, this, &DeviceManagerImplementation::browseRequestFinished);
}

View File

@ -97,7 +97,8 @@ public:
Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) override;
BrowserItems browseDevice(const DeviceId &deviceId, const QString &browser, const BrowserItemId &node = BrowserItemId()) override;
Device::BrowseResult browseDevice(const DeviceId &deviceId, const QString &nodeId = QString()) override;
Device::DeviceError executeBrowserItem(const DeviceId &deviceId, const QString &nodeId) override;
QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override;

View File

@ -283,6 +283,23 @@ DeviceHandler::DeviceHandler(QObject *parent) :
returns.insert("o:values", states);
setReturns("GetStateValues", returns);
params.clear(); returns.clear();
setDescription("BrowseDevice", "Browse a device. If a DeviceClass indicates a device is browsable, this method will return the BrowserItems. If no parameter besides the deviceId is used, the root node of this device will be returned. Any returned item which is browsable can be passed as node. Results will be children of the given node.");
params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:nodeId", 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.");
@ -329,6 +346,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
connect(NymeaCore::instance(), &NymeaCore::deviceSetupFinished, this, &DeviceHandler::deviceSetupFinished);
connect(NymeaCore::instance(), &NymeaCore::deviceReconfigurationFinished, this, &DeviceHandler::deviceReconfigurationFinished);
connect(NymeaCore::instance(), &NymeaCore::pairingFinished, this, &DeviceHandler::pairingFinished);
connect(NymeaCore::instance()->deviceManager(), &DeviceManager::browseRequestFinished, this, &DeviceHandler::browseRequestFinished);
}
/*! Returns the name of the \l{DeviceHandler}. In this case \b Devices.*/
@ -669,14 +687,31 @@ JsonReply *DeviceHandler::BrowseDevice(const QVariantMap &params) const
{
QVariantMap returns;
DeviceId deviceId = DeviceId(params.value("deviceId").toString());
QString browser = params.value("browser").toString();
QString nodeId = params.value("nodeId").toString();
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(deviceId);
if (!device) {
returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorDeviceNotFound));
return createReply(returns);
Device::BrowseResult result = NymeaCore::instance()->deviceManager()->browseDevice(deviceId, nodeId);
if (result.status == Device::DeviceErrorAsync ) {
JsonReply *reply = createAsyncReply("BrowseDevice");
m_asyncBrowseRequests.insert(result.id, reply);
connect(reply, &JsonReply::finished, this, [this, result](){
m_asyncBrowseRequests.remove(result.id);
});
return reply;
}
NymeaCore::instance()->deviceManager()->browseDevice(device->id(), browser);
returns.insert("deviceError", JsonTypes::deviceErrorToString(result.status));
returns.insert("items", JsonTypes::packBrowserItems(result.items));
return createReply(returns);
}
JsonReply *DeviceHandler::ExecuteBrowserItem(const QVariantMap &params)
{
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);
}
@ -805,4 +840,18 @@ void DeviceHandler::pairingFinished(const PairingTransactionId &pairingTransacti
m_asynDeviceAdditions.insert(deviceId, reply);
}
void DeviceHandler::browseRequestFinished(const Device::BrowseResult &result)
{
if (!m_asyncBrowseRequests.contains(result.id)) {
qCWarning(dcJsonRpc()) << "No pending JsonRpc reply. Did it time out?";
return;
}
JsonReply *reply = m_asyncBrowseRequests.take(result.id);
QVariantMap params;
params.insert("deviceError", JsonTypes::deviceErrorToString(result.status));
params.insert("items", JsonTypes::packBrowserItems(result.items));
reply->setData(params);
reply->finished();
}
}

View File

@ -58,6 +58,7 @@ public:
Q_INVOKABLE JsonReply *GetStateValues(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *BrowseDevice(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap &params);
signals:
void PluginConfigurationChanged(const QVariantMap &params);
@ -88,12 +89,15 @@ private slots:
void pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId);
void browseRequestFinished(const Device::BrowseResult &result);
private:
// A cache for async replies
mutable QHash<DeviceClassId, JsonReply*> m_discoverRequests;
mutable QHash<DeviceId, JsonReply*> m_asynDeviceAdditions;
mutable QHash<DeviceId, JsonReply*> m_asynDeviceEditAdditions;
mutable QHash<QUuid, JsonReply*> m_asyncPairingRequests;
mutable QHash<QUuid, JsonReply*> m_asyncBrowseRequests;
};
}

View File

@ -127,6 +127,7 @@ QVariantMap JsonTypes::s_tag;
QVariantMap JsonTypes::s_mqttPolicy;
QVariantMap JsonTypes::s_package;
QVariantMap JsonTypes::s_repository;
QVariantMap JsonTypes::s_browserItem;
void JsonTypes::init()
{
@ -273,6 +274,7 @@ void JsonTypes::init()
s_deviceClass.insert("name", basicTypeToString(String));
s_deviceClass.insert("displayName", basicTypeToString(String));
s_deviceClass.insert("interfaces", QVariantList() << basicTypeToString(String));
s_deviceClass.insert("browsable", basicTypeToString(Bool));
s_deviceClass.insert("setupMethod", setupMethodRef());
s_deviceClass.insert("createMethods", QVariantList() << createMethodRef());
s_deviceClass.insert("stateTypes", QVariantList() << stateTypeRef());
@ -403,6 +405,7 @@ void JsonTypes::init()
s_tag.insert("tagId", basicTypeToString(QVariant::String));
s_tag.insert("o:value", basicTypeToString(QVariant::String));
// Package
s_package.insert("id", basicTypeToString(QVariant::String));
s_package.insert("displayName", basicTypeToString(QVariant::String));
s_package.insert("summary", basicTypeToString(QVariant::String));
@ -413,10 +416,19 @@ void JsonTypes::init()
s_package.insert("rollbackAvailable", basicTypeToString(QVariant::Bool));
s_package.insert("canRemove", basicTypeToString(QVariant::Bool));
// Repository
s_repository.insert("id", basicTypeToString(QVariant::String));
s_repository.insert("displayName", basicTypeToString(QVariant::String));
s_repository.insert("enabled", basicTypeToString(QVariant::Bool));
// BrowserItem
s_browserItem.insert("id", basicTypeToString(QVariant::String));
s_browserItem.insert("displayName", basicTypeToString(QVariant::String));
s_browserItem.insert("description", basicTypeToString(QVariant::String));
s_browserItem.insert("thumbnail", basicTypeToString(QVariant::String));
s_browserItem.insert("executable", basicTypeToString(QVariant::Bool));
s_browserItem.insert("browsable", basicTypeToString(QVariant::Bool));
s_initialized = true;
}
@ -706,6 +718,18 @@ QVariantMap JsonTypes::packParam(const Param &param)
return variantMap;
}
QVariantMap JsonTypes::packBrowserItem(const BrowserItem &item)
{
QVariantMap ret;
ret.insert("id", item.id());
ret.insert("displayName", item.displayName());
ret.insert("description", item.description());
ret.insert("thumbnail", item.thumbnail());
ret.insert("executable", item.executable());
ret.insert("browsable", item.browsable());
return ret;
}
QVariantList JsonTypes::packParams(const ParamList &paramList)
{
QVariantList ret;
@ -790,6 +814,7 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass, const QLo
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())
@ -1186,6 +1211,15 @@ QVariantList JsonTypes::packDeviceDescriptors(const QList<DeviceDescriptor> devi
return deviceDescriptorList;
}
QVariantList JsonTypes::packBrowserItems(const BrowserItems &items)
{
QVariantList ret;
foreach (const BrowserItem &item, items) {
ret.append(packBrowserItem(item));
}
return ret;
}
/*! Returns a variant map with the current basic configuration of the server. */
QVariantMap JsonTypes::packBasicConfiguration()
{
@ -2080,6 +2114,12 @@ QPair<bool, QString> JsonTypes::validateVariant(const QVariant &templateVariant,
qCWarning(dcJsonRpc) << "Repository not matching";
return result;
}
} else if (refName == browserItemRef()) {
QPair<bool, QString> result = validateMap(browserItemDescription(), variant.toMap());
if (!result.first) {
qCWarning(dcJsonRpc) << "BrowserItem not matching";
return result;
}
} else if (refName == basicTypeRef()) {
QPair<bool, QString> result = validateBasicType(variant);
if (!result.first) {

View File

@ -180,6 +180,7 @@ public:
DECLARE_OBJECT(mqttPolicy, "MqttPolicy")
DECLARE_OBJECT(package, "Package")
DECLARE_OBJECT(repository, "Repository")
DECLARE_OBJECT(browserItem, "BrowserItem")
// pack types
static QVariantMap packEventType(const EventType &eventType, const PluginId &pluginId, const QLocale &locale);
@ -194,7 +195,7 @@ public:
static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor);
static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator);
static QVariantMap packParam(const Param &param);
static QVariantList packParams(const ParamList &paramList);
static QVariantMap packBrowserItem(const BrowserItem &item);
static QVariantMap packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packParamDescriptor(const ParamDescriptor &paramDescriptor);
static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale);
@ -214,6 +215,8 @@ public:
static QVariantMap packWiredNetworkDevice(WiredNetworkDevice *networkDevice);
static QVariantMap packWirelessNetworkDevice(WirelessNetworkDevice *networkDevice);
static QVariantList packParams(const ParamList &paramList);
static QVariantList packBrowserItems(const BrowserItems &items);
static QVariantList packRules(const QList<Rule> rules);
static QVariantList packCreateMethods(DeviceClass::CreateMethods createMethods);
static QVariantList packSupportedVendors(const QLocale &locale);

View File

@ -154,6 +154,18 @@ PluginId Device::pluginId() const
return m_plugin->pluginId();
}
/*! Returns the \l{DeviceClass} of this device. */
DeviceClass Device::deviceClass() const
{
return m_deviceClass;
}
/*! Returns the the \l{DevicePlugin} this Device is managed by. */
DevicePlugin *Device::plugin() const
{
return m_plugin;
}
/*! Returns the name of this Device. This is visible to the user. */
QString Device::name() const
{

View File

@ -30,6 +30,7 @@
#include "types/deviceclass.h"
#include "types/state.h"
#include "types/param.h"
#include "types/browseritem.h"
#include <QObject>
#include <QUuid>
@ -69,7 +70,8 @@ public:
DeviceErrorDeviceInRule,
DeviceErrorDeviceIsChild,
DeviceErrorPairingTransactionIdNotFound,
DeviceErrorParameterNotWritable
DeviceErrorParameterNotWritable,
DeviceErrorUnsupportedFeature,
};
Q_ENUM(DeviceError)
@ -80,12 +82,22 @@ public:
};
Q_ENUM(DeviceSetupStatus)
class BrowseResult {
public:
QUuid id;
Device::DeviceError status = Device::DeviceErrorNoError;
BrowserItems items;
private:
BrowseResult(): id(QUuid::createUuid()) {}
friend class DeviceManager;
};
DeviceId id() const;
DeviceClassId deviceClassId() const;
PluginId pluginId() const;
DeviceClass deviceClass() const;
DevicePlugin* plugin();
DevicePlugin* plugin() const;
QString name() const;
void setName(const QString &name);

View File

@ -39,3 +39,14 @@ DeviceManager::DeviceManager(QObject *parent) : QObject(parent)
{
}
Device::BrowseResult DeviceManager::createBrowseResult()
{
Device::BrowseResult result = Device::BrowseResult();
return result;
}
QUuid DeviceManager::browseResultId(const Device::BrowseResult &result)
{
return result.id;
}

View File

@ -70,7 +70,8 @@ public:
virtual Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) = 0;
virtual BrowserItems browseDevice(const DeviceId &deviceId, const QString &browser, const BrowserItemId &node = BrowserItemId()) = 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 QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0;
@ -88,7 +89,11 @@ signals:
void deviceReconfigurationFinished(Device *device, Device::DeviceError status);
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);
protected:
Device::BrowseResult createBrowseResult();
QUuid browseResultId(const Device::BrowseResult &result);
};
#endif // DEVICEMANAGER_H

View File

@ -248,6 +248,22 @@ Device::DeviceError DevicePlugin::executeAction(Device *device, const Action &ac
return Device::DeviceErrorNoError;
}
Device::BrowseResult DevicePlugin::browseDevice(Device *device, Device::BrowseResult result, const QString &nodeId)
{
Q_UNUSED(device)
Q_UNUSED(nodeId)
result.status = Device::DeviceErrorUnsupportedFeature;
return result;
}
Device::DeviceError DevicePlugin::executeBrowserItem(Device *device, const QString &nodeId)
{
Q_UNUSED(device)
Q_UNUSED(nodeId)
return Device::DeviceErrorUnsupportedFeature;
}
/*! Returns the configuration description of this DevicePlugin as a list of \l{ParamType}{ParamTypes}. */
ParamTypes DevicePlugin::configurationDescription() const
{

View File

@ -78,6 +78,9 @@ 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);
// Configuration
ParamTypes configurationDescription() const;
Device::DeviceError setConfiguration(const ParamList &configuration);
@ -96,6 +99,7 @@ signals:
void configValueChanged(const ParamTypeId &paramTypeId, const QVariant &value);
void autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
void autoDeviceDisappeared(const DeviceId &deviceId);
void browseRequestFinished(const Device::BrowseResult &result);
protected:
Devices myDevices() const;

View File

@ -162,7 +162,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
QJsonObject deviceClassObject = deviceClassJson.toObject();
/*! Returns a list of all valid JSON properties a DeviceClass JSON definition can have. */
QStringList deviceClassProperties = QStringList() << "id" << "name" << "displayName" << "createMethods" << "setupMethod"
<< "interfaces" << "pairingInfo" << "discoveryParamTypes" << "discoveryParamTypes"
<< "interfaces" << "browsable" << "pairingInfo" << "discoveryParamTypes" << "discoveryParamTypes"
<< "paramTypes" << "settingsTypes" << "stateTypes" << "actionTypes" << "eventTypes";
QStringList mandatoryDeviceClassProperties = QStringList() << "id" << "name" << "displayName";
@ -192,6 +192,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
DeviceClass deviceClass(pluginId(), vendorId, deviceClassId);
deviceClass.setName(deviceClassName);
deviceClass.setDisplayName(deviceClassObject.value("displayName").toString());
deviceClass.setBrowsable(deviceClassObject.value("browsable").toBool());
// Read create methods
DeviceClass::CreateMethods createMethods;

View File

@ -1,6 +1,70 @@
#include "browseritem.h"
BrowserItem::BrowserItem()
BrowserItem::BrowserItem(const QString &id, const QString &displayName, bool browsable):
m_id(id),
m_displayName(displayName),
m_browsable(browsable)
{
}
QString BrowserItem::id() const
{
return m_id;
}
QString BrowserItem::displayName() const
{
return m_displayName;
}
QString BrowserItem::description() const
{
return m_description;
}
void BrowserItem::setDescription(const QString &description)
{
m_description = description;
}
bool BrowserItem::executable() const
{
return m_executable;
}
void BrowserItem::setExecutable(bool executable)
{
m_executable = executable;
}
bool BrowserItem::browsable() const
{
return m_browsable;
}
void BrowserItem::setBrowsable(bool browsable)
{
m_browsable = browsable;
}
QString BrowserItem::thumbnail() const
{
return m_thumbnail;
}
void BrowserItem::setThumbnail(const QString &thumbnail)
{
m_thumbnail = thumbnail;
}
BrowserItems::BrowserItems()
{
}
BrowserItems::BrowserItems(const QList<BrowserItem> &other): QList<BrowserItem>(other)
{
}

View File

@ -9,12 +9,41 @@
class LIBNYMEA_EXPORT BrowserItem
{
public:
BrowserItem();
BrowserItem(const QString &id = QString(), const QString &displayName = QString(), bool browsable = false);
QString id() const;
void setId(const QString &id);
QString displayName() const;
void setDisplayName(const QString &displayName);
QString description() const;
void setDescription(const QString &description);
bool executable() const;
void setExecutable(bool executable);
bool browsable() const;
void setBrowsable(bool browsable);
QString thumbnail() const;
void setThumbnail(const QString &thumbnail);
private:
QString m_id;
QString m_displayName;
QString m_description;
bool m_executable = false;
bool m_browsable = false;
QString m_thumbnail;
};
class LIBNYMEA_EXPORT BrowserItems: public QList<BrowserItem>
{
public:
BrowserItems();
BrowserItems(const QList<BrowserItem> &other);
};

View File

@ -308,6 +308,16 @@ void DeviceClass::setInterfaces(const QStringList &interfaces)
m_interfaces = interfaces;
}
bool DeviceClass::browsable() const
{
return m_browsable;
}
void DeviceClass::setBrowsable(bool browsable)
{
m_browsable = browsable;
}
/*! Compare this \a deviceClass to another. This is effectively the same as calling a.id() == b.id(). Returns true if the ids match.*/
bool DeviceClass::operator==(const DeviceClass &deviceClass) const
{

View File

@ -105,6 +105,9 @@ public:
QStringList interfaces() const;
void setInterfaces(const QStringList &interfaces);
bool browsable() const;
void setBrowsable(bool browsable);
bool operator==(const DeviceClass &device) const;
private:
@ -113,6 +116,7 @@ private:
PluginId m_pluginId;
QString m_name;
QString m_displayName;
bool m_browsable = false;
StateTypes m_stateTypes;
EventTypes m_eventTypes;
ActionTypes m_actionTypes;

View File

@ -57,11 +57,10 @@ DECLARE_TYPE_ID(ActionType)
DECLARE_TYPE_ID(Action)
DECLARE_TYPE_ID(Plugin)
DECLARE_TYPE_ID(Rule)
DECLARE_TYPE_ID(Browser)
DECLARE_TYPE_ID(PairingTransaction)
DECLARE_TYPE_ID(BrowserItem)
class LIBNYMEA_EXPORT Types
{
Q_GADGET
@ -153,6 +152,10 @@ public:
};
Q_ENUM(StateOperator)
enum BrowserType {
BrowserTypeGeneric,
};
Q_ENUM(BrowserType)
};
Q_DECLARE_METATYPE(Types::InputType)

View File

@ -239,6 +239,30 @@ Device::DeviceError DevicePluginMock::displayPin(const PairingTransactionId &pai
return Device::DeviceErrorNoError;
}
Device::BrowseResult DevicePluginMock::browseDevice(Device *device, Device::BrowseResult result, const QString &nodeId)
{
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 {
if (device->paramValue(mockDeviceBrokenParamTypeId).toBool()) {
result.status = Device::DeviceErrorHardwareFailure;
} else {
result = generateBrowseItems(nodeId, result);
}
emit browseRequestFinished(result);
});
}
else if (device->paramValue(mockDeviceBrokenParamTypeId).toBool()) {
result.status = Device::DeviceErrorHardwareFailure;
} else {
result = generateBrowseItems(nodeId, result);
}
}
return result;
}
Device::DeviceError DevicePluginMock::executeAction(Device *device, const Action &action)
{
if (!myDevices().contains(device))
@ -566,3 +590,38 @@ void DevicePluginMock::onPluginConfigChanged()
{
}
Device::BrowseResult DevicePluginMock::generateBrowseItems(const QString &nodeId, 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"));
}
else if (nodeId == "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") {
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") {
result.items.append(BrowserItem("15", "Item 15"));
result.items.append(BrowserItem("16", "Item 16"));
} else {
result.status = Device::DeviceErrorInvalidParameter;
}
return result;
}

View File

@ -52,6 +52,8 @@ 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;
public slots:
Device::DeviceError executeAction(Device *device, const Action &action) override;
@ -72,6 +74,9 @@ private slots:
void onChildDeviceDiscovered(const DeviceId &parentId);
void onPluginConfigChanged();
private:
Device::BrowseResult generateBrowseItems(const QString &nodeId, Device::BrowseResult result);
private:
QHash<Device*, HttpDaemon*> m_daemons;
QList<Device*> m_asyncSetupDevices;

View File

@ -32,6 +32,7 @@
"displayName": "Mock Device",
"interfaces": ["system", "light", "battery"],
"createMethods": ["user", "discovery"],
"browsable": true,
"discoveryParamTypes": [
{
"id": "d222adb4-2f9c-4c3f-8655-76400d0fb6ce",