Rework devicemanager and plugin api

This commit is contained in:
Michael Zanetti 2019-09-16 16:01:16 +02:00
parent c920ba43b2
commit 7f0f2d1d09
53 changed files with 2786 additions and 1773 deletions

View File

@ -20,6 +20,8 @@
#include "cloudnotifications.h" #include "cloudnotifications.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "devices/devicesetupinfo.h"
#include "devices/deviceactioninfo.h"
#include <QDebug> #include <QDebug>
#include <QJsonObject> #include <QJsonObject>
@ -136,31 +138,31 @@ PluginMetadata CloudNotifications::metaData() const
return PluginMetadata(QJsonObject::fromVariantMap(pluginMetaData), true); return PluginMetadata(QJsonObject::fromVariantMap(pluginMetaData), true);
} }
Device::DeviceSetupStatus CloudNotifications::setupDevice(Device *device) void CloudNotifications::setupDevice(DeviceSetupInfo *info)
{ {
Device *device = info->device();
device->setStateValue(connectedStateTypeId, m_awsConnector->isConnected()); device->setStateValue(connectedStateTypeId, m_awsConnector->isConnected());
qCDebug(dcCloud) << "Cloud Notifications Device setup:" << device->name() << "Connected:" << m_awsConnector->isConnected(); qCDebug(dcCloud) << "Cloud Notifications Device setup:" << device->name() << "Connected:" << m_awsConnector->isConnected();
connect(m_awsConnector, &AWSConnector::connected, device, [device]() { connect(m_awsConnector, &AWSConnector::connected, info->device(), [device]() {
device->setStateValue(connectedStateTypeId, true); device->setStateValue(connectedStateTypeId, true);
}); });
connect(m_awsConnector, &AWSConnector::disconnected, device, [device]() { connect(m_awsConnector, &AWSConnector::disconnected, device, [device]() {
device->setStateValue(connectedStateTypeId, false); device->setStateValue(connectedStateTypeId, false);
}); });
return Device::DeviceSetupStatusSuccess; info->finish(Device::DeviceErrorNoError);
} }
void CloudNotifications::startMonitoringAutoDevices() void CloudNotifications::startMonitoringAutoDevices()
{ {
} }
Device::DeviceError CloudNotifications::executeAction(Device *device, const Action &action) void CloudNotifications::executeAction(DeviceActionInfo *info)
{ {
qCDebug(dcCloud()) << "executeAction" << device << action.id() << action.params(); qCDebug(dcCloud()) << "executeAction" << info->device() << info->action().id() << info->action().params();
QString userId = device->paramValue(cloudNotificationsDeviceClassUserParamId).toString(); QString userId = info->device()->paramValue(cloudNotificationsDeviceClassUserParamId).toString();
QString endpointId = device->paramValue(cloudNotificationsDeviceClassEndpointParamId).toString(); QString endpointId = info->device()->paramValue(cloudNotificationsDeviceClassEndpointParamId).toString();
int id = m_awsConnector->sendPushNotification(userId, endpointId, action.param(notifyActionParamTitleId).value().toString(), action.param(notifyActionParamBodyId).value().toString()); int id = m_awsConnector->sendPushNotification(userId, endpointId, info->action().param(notifyActionParamTitleId).value().toString(), info->action().param(notifyActionParamBodyId).value().toString());
m_pendingPushNotifications.insert(id, action.id()); m_pendingPushNotifications.insert(id, info);
return Device::DeviceErrorAsync;
} }
void CloudNotifications::pushNotificationEndpointsUpdated(const QList<AWSConnector::PushNotificationsEndpoint> &endpoints) void CloudNotifications::pushNotificationEndpointsUpdated(const QList<AWSConnector::PushNotificationsEndpoint> &endpoints)
@ -184,7 +186,7 @@ void CloudNotifications::pushNotificationEndpointsUpdated(const QList<AWSConnect
emit autoDeviceDisappeared(d->id()); emit autoDeviceDisappeared(d->id());
} }
QList<DeviceDescriptor> devicesToAdd; DeviceDescriptors devicesToAdd;
foreach (const AWSConnector::PushNotificationsEndpoint &ep, endpoints) { foreach (const AWSConnector::PushNotificationsEndpoint &ep, endpoints) {
bool found = false; bool found = false;
qCDebug(dcCloud) << "Checking endoint:" << ep.endpointId; qCDebug(dcCloud) << "Checking endoint:" << ep.endpointId;
@ -208,7 +210,7 @@ void CloudNotifications::pushNotificationEndpointsUpdated(const QList<AWSConnect
devicesToAdd.append(descriptor); devicesToAdd.append(descriptor);
} }
} }
emit autoDevicesAppeared(cloudNotificationsDeviceClassId, devicesToAdd); emit autoDevicesAppeared(devicesToAdd);
} }
@ -229,12 +231,16 @@ void CloudNotifications::pushNotificationEndpointAdded(const AWSConnector::PushN
Param endpointIdParam(cloudNotificationsDeviceClassEndpointParamId, endpoint.endpointId); Param endpointIdParam(cloudNotificationsDeviceClassEndpointParamId, endpoint.endpointId);
params.append(endpointIdParam); params.append(endpointIdParam);
descriptor.setParams(params); descriptor.setParams(params);
emit autoDevicesAppeared(cloudNotificationsDeviceClassId, {descriptor}); emit autoDevicesAppeared({descriptor});
} }
void CloudNotifications::pushNotificationSent(int id, int status) void CloudNotifications::pushNotificationSent(int id, int status)
{ {
qCDebug(dcCloud()) << "Push notification sent" << id << status; qCDebug(dcCloud()) << "Push notification sent" << id << status;
ActionId actionId = m_pendingPushNotifications.value(id); DeviceActionInfo *info = m_pendingPushNotifications.take(id);
emit actionExecutionFinished(actionId, status == 200 ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareNotAvailable); if (!info) {
qCWarning(dcCloud()) << "Received a push notification send reponse for a request we're not waiting for.";
return;
}
info->finish(status == 200 ? Device::DeviceErrorNoError : Device::DeviceErrorHardwareNotAvailable);
} }

View File

@ -36,9 +36,9 @@ public:
PluginMetadata metaData() const; PluginMetadata metaData() const;
Device::DeviceSetupStatus setupDevice(Device *device) override; void setupDevice(DeviceSetupInfo *info) override;
void startMonitoringAutoDevices() override; void startMonitoringAutoDevices() override;
Device::DeviceError executeAction(Device *device, const Action &action) override; void executeAction(DeviceActionInfo *info) override;
private slots: private slots:
void pushNotificationEndpointsUpdated(const QList<AWSConnector::PushNotificationsEndpoint> &endpoints); void pushNotificationEndpointsUpdated(const QList<AWSConnector::PushNotificationsEndpoint> &endpoints);
@ -47,7 +47,7 @@ private slots:
private: private:
AWSConnector *m_awsConnector = nullptr; AWSConnector *m_awsConnector = nullptr;
QHash<int, ActionId> m_pendingPushNotifications; QHash<int, DeviceActionInfo*> m_pendingPushNotifications;
}; };
#endif // CLOUDNOTIFICATIONS_H #endif // CLOUDNOTIFICATIONS_H

File diff suppressed because it is too large Load Diff

View File

@ -60,13 +60,14 @@ class DeviceManagerImplementation: public DeviceManager
public: public:
explicit DeviceManagerImplementation(HardwareManager *hardwareManager, const QLocale &locale, QObject *parent = nullptr); explicit DeviceManagerImplementation(HardwareManager *hardwareManager, const QLocale &locale, QObject *parent = nullptr);
~DeviceManagerImplementation(); ~DeviceManagerImplementation() override;
static QStringList pluginSearchDirs(); static QStringList pluginSearchDirs();
static QList<QJsonObject> pluginsMetadata(); static QList<QJsonObject> pluginsMetadata();
void registerStaticPlugin(DevicePlugin* plugin, const PluginMetadata &metaData); void registerStaticPlugin(DevicePlugin* plugin, const PluginMetadata &metaData);
DevicePlugins plugins() const override; DevicePlugins plugins() const override;
DevicePlugin *plugin(const PluginId &pluginId) const override;
Device::DeviceError setPluginConfig(const PluginId &pluginId, const ParamList &pluginConfig) override; Device::DeviceError setPluginConfig(const PluginId &pluginId, const ParamList &pluginConfig) override;
Vendors supportedVendors() const override; Vendors supportedVendors() const override;
@ -80,29 +81,29 @@ public:
Devices findChildDevices(const DeviceId &id) const override; Devices findChildDevices(const DeviceId &id) const override;
DeviceClass findDeviceClass(const DeviceClassId &deviceClassId) const override; DeviceClass findDeviceClass(const DeviceClassId &deviceClassId) const override;
Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceDiscoveryInfo* discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
Device::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id = DeviceId::createDeviceId()) override; DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id = DeviceId::createDeviceId()) override;
Device::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const DeviceId &deviceId = DeviceId::createDeviceId()) override; DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const DeviceId &deviceId = DeviceId::createDeviceId()) override;
Device::DeviceError reconfigureDevice(const DeviceId &deviceId, const ParamList &params, bool fromDiscoveryOrAuto = false) override; DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const ParamList &params, bool fromDiscoveryOrAuto = false) override;
Device::DeviceError reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId) override; DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId) override;
Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) override; Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) override;
Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) override; Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) override;
Device::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const QString &name, const ParamList &params) override; DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params) override;
Device::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId) override; DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId) override;
Device::DeviceError confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &secret = QString()) override; DevicePairingInfo* confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &username, const QString &secret) override;
Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) override; Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) override;
Device::DeviceError executeAction(const Action &action) override; DeviceActionInfo* executeAction(const Action &action) override;
Device::BrowseResult browseDevice(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) override; BrowseResult* browseDevice(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) override;
Device::BrowserItemResult browserItemDetails(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) override; BrowserItemResult* browserItemDetails(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) override;
Device::DeviceError executeBrowserItem(const BrowserAction &browserAction) override; BrowserActionInfo *executeBrowserItem(const BrowserAction &browserAction) override;
Device::DeviceError executeBrowserItemAction(const BrowserItemAction &browserItemAction) override; BrowserItemActionInfo *executeBrowserItemAction(const BrowserItemAction &browserItemAction) override;
QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override; QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) override;
@ -118,10 +119,7 @@ private slots:
void loadConfiguredDevices(); void loadConfiguredDevices();
void storeConfiguredDevices(); void storeConfiguredDevices();
void startMonitoringAutoDevices(); void startMonitoringAutoDevices();
void slotDevicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors); void onAutoDevicesAppeared(const DeviceDescriptors &deviceDescriptors);
void slotDeviceSetupFinished(Device *device, Device::DeviceSetupStatus status);
void slotPairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceSetupStatus status);
void onAutoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
void onAutoDeviceDisappeared(const DeviceId &deviceId); void onAutoDeviceDisappeared(const DeviceId &deviceId);
void onLoaded(); void onLoaded();
void cleanupDeviceStateCache(); void cleanupDeviceStateCache();
@ -132,8 +130,9 @@ private slots:
void slotDeviceSettingChanged(const ParamTypeId &paramTypeId, const QVariant &value); void slotDeviceSettingChanged(const ParamTypeId &paramTypeId, const QVariant &value);
private: private:
Device::DeviceError addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id = DeviceId::createDeviceId(), const DeviceId &parentDeviceId = DeviceId()); void pairDeviceInternal(DevicePairingInfo *info);
Device::DeviceSetupStatus setupDevice(Device *device); DeviceSetupInfo *addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId &deviceId = DeviceId::createDeviceId(), const DeviceId &parentDeviceId = DeviceId());
DeviceSetupInfo *setupDevice(Device *device);
void postSetupDevice(Device *device); void postSetupDevice(Device *device);
void storeDeviceStates(Device *device); void storeDeviceStates(Device *device);
void loadDeviceStates(Device *device); void loadDeviceStates(Device *device);
@ -148,15 +147,19 @@ private:
QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap; QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap;
QHash<DeviceClassId, DeviceClass> m_supportedDevices; QHash<DeviceClassId, DeviceClass> m_supportedDevices;
QHash<DeviceId, Device*> m_configuredDevices; QHash<DeviceId, Device*> m_configuredDevices;
QHash<DeviceDescriptorId, DeviceDescriptor> m_discoveredDevices; QHash<DeviceClassId, QHash<DeviceDescriptorId, DeviceDescriptor> > m_discoveredDevices;
QHash<PluginId, DevicePlugin*> m_devicePlugins; QHash<PluginId, DevicePlugin*> m_devicePlugins;
QHash<QUuid, DevicePairingInfo> m_pairingsJustAdd; class PairingContext {
QHash<QUuid, DevicePairingInfo> m_pairingsDiscovery; public:
DeviceId deviceId;
QList<Device *> m_asyncDeviceReconfiguration; DeviceClassId deviceClassId;
QList<DevicePlugin *> m_discoveringPlugins; DeviceId parentDeviceId;
ParamList params;
QString deviceName;
};
QHash<PairingTransactionId, PairingContext> m_pendingPairings;
}; };
#endif // DEVICEMANAGERIMPLEMENTATION_H #endif // DEVICEMANAGERIMPLEMENTATION_H

View File

@ -36,6 +36,9 @@
#include "nymeacore.h" #include "nymeacore.h"
#include "devices/devicemanager.h" #include "devices/devicemanager.h"
#include "devices/deviceactioninfo.h"
#include "devices/browseractioninfo.h"
#include "devices/browseritemactioninfo.h"
#include "types/action.h" #include "types/action.h"
#include "loggingcategories.h" #include "loggingcategories.h"
@ -52,6 +55,7 @@ ActionHandler::ActionHandler(QObject *parent) :
setDescription("ExecuteAction", "Execute a single action."); setDescription("ExecuteAction", "Execute a single action.");
setParams("ExecuteAction", JsonTypes::actionDescription()); setParams("ExecuteAction", JsonTypes::actionDescription());
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("ExecuteAction", returns); setReturns("ExecuteAction", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
@ -80,9 +84,6 @@ ActionHandler::ActionHandler(QObject *parent) :
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
setReturns("ExecuteBrowserItemAction", returns); setReturns("ExecuteBrowserItemAction", returns);
connect(NymeaCore::instance(), &NymeaCore::actionExecuted, this, &ActionHandler::actionExecuted);
connect(NymeaCore::instance(), &NymeaCore::browserItemExecuted, this, &ActionHandler::browserItemExecuted);
connect(NymeaCore::instance(), &NymeaCore::browserItemActionExecuted, this, &ActionHandler::browserItemActionExecuted);
} }
/*! Returns the name of the \l{ActionHandler}. In this case \b Actions.*/ /*! Returns the name of the \l{ActionHandler}. In this case \b Actions.*/
@ -96,20 +97,24 @@ JsonReply* ActionHandler::ExecuteAction(const QVariantMap &params)
DeviceId deviceId(params.value("deviceId").toString()); DeviceId deviceId(params.value("deviceId").toString());
ActionTypeId actionTypeId(params.value("actionTypeId").toString()); ActionTypeId actionTypeId(params.value("actionTypeId").toString());
ParamList actionParams = JsonTypes::unpackParams(params.value("params").toList()); ParamList actionParams = JsonTypes::unpackParams(params.value("params").toList());
QLocale locale = params.value("locale").toLocale();
Action action(actionTypeId, deviceId); Action action(actionTypeId, deviceId);
action.setParams(actionParams); action.setParams(actionParams);
Device::DeviceError status = NymeaCore::instance()->executeAction(action); JsonReply *jsonReply = createAsyncReply("ExecuteAction");
if (status == Device::DeviceErrorAsync) {
JsonReply *reply = createAsyncReply("ExecuteAction");
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)); DeviceActionInfo *info = NymeaCore::instance()->executeAction(action);
connect(info, &DeviceActionInfo::finished, jsonReply, [this, info, jsonReply, locale](){
QVariantMap data = statusToReply(info->status());
if (!info->displayMessage().isEmpty()) {
data.insert("displayMessage", info->translatedDisplayMessage(locale));
}
jsonReply->setData(data);
jsonReply->finished();
});
return jsonReply;
} }
JsonReply *ActionHandler::GetActionType(const QVariantMap &params) const JsonReply *ActionHandler::GetActionType(const QVariantMap &params) const
@ -128,31 +133,21 @@ JsonReply *ActionHandler::GetActionType(const QVariantMap &params) const
return createReply(statusToReply(Device::DeviceErrorActionTypeNotFound)); return createReply(statusToReply(Device::DeviceErrorActionTypeNotFound));
} }
void ActionHandler::actionExecuted(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();
}
JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap &params) JsonReply *ActionHandler::ExecuteBrowserItem(const QVariantMap &params)
{ {
DeviceId deviceId = DeviceId(params.value("deviceId").toString()); DeviceId deviceId = DeviceId(params.value("deviceId").toString());
QString itemId = params.value("itemId").toString(); QString itemId = params.value("itemId").toString();
BrowserAction action(deviceId, itemId); BrowserAction action(deviceId, itemId);
Device::DeviceError status = NymeaCore::instance()->executeBrowserItem(action);
if (status == Device::DeviceErrorAsync) { JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItem");
JsonReply *reply = createAsyncReply("ExecuteBrowserItem");
ActionId id = action.id(); BrowserActionInfo *info = NymeaCore::instance()->executeBrowserItem(action);
connect(reply, &JsonReply::finished, [this, id](){ m_asyncActionExecutions.remove(id); }); connect(info, &BrowserActionInfo::finished, jsonReply, [this, info, jsonReply](){
m_asyncActionExecutions.insert(id, reply); jsonReply->setData(statusToReply(info->status()));
return reply; jsonReply->finished();
} });
return createReply(statusToReply(status));
return jsonReply;
} }
JsonReply *ActionHandler::ExecuteBrowserItemAction(const QVariantMap &params) JsonReply *ActionHandler::ExecuteBrowserItemAction(const QVariantMap &params)
@ -162,39 +157,16 @@ JsonReply *ActionHandler::ExecuteBrowserItemAction(const QVariantMap &params)
ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString()); ActionTypeId actionTypeId = ActionTypeId(params.value("actionTypeId").toString());
ParamList paramList = JsonTypes::unpackParams(params.value("params").toList()); ParamList paramList = JsonTypes::unpackParams(params.value("params").toList());
BrowserItemAction browserItemAction(deviceId, itemId, actionTypeId, paramList); 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));
JsonReply *jsonReply = createAsyncReply("ExecuteBrowserItemAction");
BrowserItemActionInfo *info = NymeaCore::instance()->executeBrowserItemAction(browserItemAction);
connect(info, &BrowserItemActionInfo::finished, jsonReply, [this, info, jsonReply](){
jsonReply->setData(statusToReply(info->status()));
jsonReply->finished();
});
return jsonReply;
} }
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();
}
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

@ -41,13 +41,6 @@ public:
Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap &params); Q_INVOKABLE JsonReply *ExecuteBrowserItem(const QVariantMap &params);
Q_INVOKABLE JsonReply *ExecuteBrowserItemAction(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

@ -61,6 +61,11 @@
#include "loggingcategories.h" #include "loggingcategories.h"
#include "types/deviceclass.h" #include "types/deviceclass.h"
#include "devices/translator.h" #include "devices/translator.h"
#include "devices/devicediscoveryinfo.h"
#include "devices/devicepairinginfo.h"
#include "devices/devicesetupinfo.h"
#include "devices/browseresult.h"
#include "devices/browseritemresult.h"
#include <QDebug> #include <QDebug>
@ -133,6 +138,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
setParams("AddConfiguredDevice", params); setParams("AddConfiguredDevice", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
returns.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("AddConfiguredDevice", returns); setReturns("AddConfiguredDevice", returns);
returns.clear(); // Reused params from above! returns.clear(); // Reused params from above!
@ -147,17 +153,22 @@ DeviceHandler::DeviceHandler(QObject *parent) :
); );
setParams("PairDevice", params); setParams("PairDevice", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
returns.insert("o:setupMethod", JsonTypes::setupMethodRef());
returns.insert("o:pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("o:pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("o:setupMethod", JsonTypes::setupMethodRef()); returns.insert("o:oAuthUrl", JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("PairDevice", returns); setReturns("PairDevice", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ConfirmPairing", "Confirm an ongoing pairing. In case of SetupMethodEnterPin also provide the pin in the params."); setDescription("ConfirmPairing", "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field "
"and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" "
"field. For SetupMethodOAuth, return the entire unmodified callback URL containing the code parameter back in the secret field.");
params.insert("pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:username", JsonTypes::basicTypeToString(JsonTypes::String));
params.insert("o:secret", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("o:secret", JsonTypes::basicTypeToString(JsonTypes::String));
setParams("ConfirmPairing", params); setParams("ConfirmPairing", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
setReturns("ConfirmPairing", returns); setReturns("ConfirmPairing", returns);
@ -182,6 +193,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
params.insert("o:discoveryParams", discoveryParams); params.insert("o:discoveryParams", discoveryParams);
setParams("GetDiscoveredDevices", params); setParams("GetDiscoveredDevices", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
QVariantList deviceDescriptors; QVariantList deviceDescriptors;
deviceDescriptors.append(JsonTypes::deviceDescriptorRef()); deviceDescriptors.append(JsonTypes::deviceDescriptorRef());
returns.insert("o:deviceDescriptors", deviceDescriptors); returns.insert("o:deviceDescriptors", deviceDescriptors);
@ -200,6 +212,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
params.insert("o:deviceParams", newDeviceParams); params.insert("o:deviceParams", newDeviceParams);
setParams("ReconfigureDevice", params); setParams("ReconfigureDevice", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("ReconfigureDevice", returns); setReturns("ReconfigureDevice", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
@ -343,12 +356,6 @@ DeviceHandler::DeviceHandler(QObject *parent) :
connect(NymeaCore::instance(), &NymeaCore::deviceAdded, this, &DeviceHandler::deviceAddedNotification); connect(NymeaCore::instance(), &NymeaCore::deviceAdded, this, &DeviceHandler::deviceAddedNotification);
connect(NymeaCore::instance(), &NymeaCore::deviceChanged, this, &DeviceHandler::deviceChangedNotification); connect(NymeaCore::instance(), &NymeaCore::deviceChanged, this, &DeviceHandler::deviceChangedNotification);
connect(NymeaCore::instance(), &NymeaCore::deviceSettingChanged, this, &DeviceHandler::deviceSettingChangedNotification); connect(NymeaCore::instance(), &NymeaCore::deviceSettingChanged, this, &DeviceHandler::deviceSettingChangedNotification);
connect(NymeaCore::instance(), &NymeaCore::devicesDiscovered, this, &DeviceHandler::devicesDiscovered, Qt::QueuedConnection);
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);
connect(NymeaCore::instance()->deviceManager(), &DeviceManager::browserItemRequestFinished, this, &DeviceHandler::browserItemRequestFinished);
} }
/*! Returns the name of the \l{DeviceHandler}. In this case \b Devices.*/ /*! Returns the name of the \l{DeviceHandler}. In this case \b Devices.*/
@ -375,21 +382,33 @@ JsonReply* DeviceHandler::GetSupportedDevices(const QVariantMap &params) const
JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap &params) const JsonReply *DeviceHandler::GetDiscoveredDevices(const QVariantMap &params) const
{ {
QLocale locale = params.value("locale").toLocale();
QVariantMap returns; QVariantMap returns;
DeviceClassId deviceClassId = DeviceClassId(params.value("deviceClassId").toString()); DeviceClassId deviceClassId = DeviceClassId(params.value("deviceClassId").toString());
ParamList discoveryParams = JsonTypes::unpackParams(params.value("discoveryParams").toList()); ParamList discoveryParams = JsonTypes::unpackParams(params.value("discoveryParams").toList());
Device::DeviceError status = NymeaCore::instance()->deviceManager()->discoverDevices(deviceClassId, discoveryParams);
if (status == Device::DeviceErrorAsync ) {
JsonReply *reply = createAsyncReply("GetDiscoveredDevices"); JsonReply *reply = createAsyncReply("GetDiscoveredDevices");
connect(reply, &JsonReply::finished, this, [this, deviceClassId](){ m_discoverRequests.remove(deviceClassId); }); DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(deviceClassId, discoveryParams);
m_discoverRequests.insert(deviceClassId, reply); connect(info, &DeviceDiscoveryInfo::finished, reply, [reply, info, locale](){
return reply; QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status()));
if (info->status() == Device::DeviceErrorNoError) {
returns.insert("deviceDescriptors", JsonTypes::packDeviceDescriptors(info->deviceDescriptors()));
} }
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
return createReply(returns); if (!info->displayMessage().isEmpty()) {
returns.insert("displayMessage", info->translatedDisplayMessage(locale));
}
reply->setData(returns);
reply->finished();
});
return reply;
} }
JsonReply* DeviceHandler::GetPlugins(const QVariantMap &params) const JsonReply* DeviceHandler::GetPlugins(const QVariantMap &params) const
@ -437,28 +456,32 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap &params)
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
DeviceId newDeviceId = DeviceId::createDeviceId(); DeviceId newDeviceId = DeviceId::createDeviceId();
Device::DeviceError status; QLocale locale = params.value("locale").toLocale();
JsonReply *jsonReply = createAsyncReply("AddConfiguredDevice");
DeviceSetupInfo *info;
if (deviceDescriptorId.isNull()) { if (deviceDescriptorId.isNull()) {
status = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceName, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceName, deviceParams, newDeviceId);
} else { } else {
status = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceName, deviceDescriptorId, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceName, deviceDescriptorId, deviceParams, newDeviceId);
} }
connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){
QVariantMap returns; QVariantMap returns;
switch (status) { returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status()));
case Device::DeviceErrorAsync: {
JsonReply *asyncReply = createAsyncReply("AddConfiguredDevice"); if (!info->displayMessage().isEmpty()) {
connect(asyncReply, &JsonReply::finished, [this, newDeviceId](){ m_asynDeviceAdditions.remove(newDeviceId); }); returns.insert("displayMessage", info->translatedDisplayMessage(locale));
m_asynDeviceAdditions.insert(newDeviceId, asyncReply);
return asyncReply;
} }
case Device::DeviceErrorNoError:
returns.insert("deviceId", newDeviceId); if(info->status() == Device::DeviceErrorNoError) {
returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); returns.insert("deviceId", info->device()->id());
break;
default:
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
} }
return createReply(returns); jsonReply->setData(returns);
jsonReply->finished();
});
return jsonReply;
} }
JsonReply *DeviceHandler::PairDevice(const QVariantMap &params) JsonReply *DeviceHandler::PairDevice(const QVariantMap &params)
@ -466,44 +489,68 @@ JsonReply *DeviceHandler::PairDevice(const QVariantMap &params)
DeviceClassId deviceClassId(params.value("deviceClassId").toString()); DeviceClassId deviceClassId(params.value("deviceClassId").toString());
QString deviceName = params.value("name").toString(); QString deviceName = params.value("name").toString();
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(deviceClassId); DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(deviceClassId);
QLocale locale = params.value("locale").toLocale();
Device::DeviceError status; DevicePairingInfo *info;
PairingTransactionId pairingTransactionId = PairingTransactionId::createPairingTransactionId();
if (params.contains("deviceDescriptorId")) { if (params.contains("deviceDescriptorId")) {
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
status = NymeaCore::instance()->deviceManager()->pairDevice(pairingTransactionId, deviceClassId, deviceName, deviceDescriptorId); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceDescriptorId);
} else { } else {
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
status = NymeaCore::instance()->deviceManager()->pairDevice(pairingTransactionId, deviceClassId, deviceName, deviceParams); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceParams);
} }
JsonReply *jsonReply = createAsyncReply("PairDevice");
connect(info, &DevicePairingInfo::finished, jsonReply, [jsonReply, info, locale, deviceClass](){
QVariantMap returns; QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status()));
if (status == Device::DeviceErrorNoError) { returns.insert("pairingTransactionId", info->transactionId().toString());
returns.insert("displayMessage", NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), deviceClass.pairingInfo(), params.value("locale").toLocale()));
returns.insert("pairingTransactionId", pairingTransactionId.toString()); if (info->status() == Device::DeviceErrorNoError) {
returns.insert("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod())); returns.insert("setupMethod", JsonTypes::setupMethodToString(deviceClass.setupMethod()));
} }
return createReply(returns);
if (!info->displayMessage().isEmpty()) {
returns.insert("displayMessage", info->translatedDisplayMessage(locale));
}
if (!info->oAuthUrl().isEmpty()) {
returns.insert("oAuthUrl", info->oAuthUrl());
}
jsonReply->setData(returns);
jsonReply->finished();
});
return jsonReply;
} }
JsonReply *DeviceHandler::ConfirmPairing(const QVariantMap &params) JsonReply *DeviceHandler::ConfirmPairing(const QVariantMap &params)
{ {
PairingTransactionId pairingTransactionId = PairingTransactionId(params.value("pairingTransactionId").toString()); PairingTransactionId pairingTransactionId = PairingTransactionId(params.value("pairingTransactionId").toString());
QString secret = params.value("secret").toString(); QString secret = params.value("secret").toString();
Device::DeviceError status = NymeaCore::instance()->deviceManager()->confirmPairing(pairingTransactionId, secret); QString username = params.value("username").toString();
QLocale locale = params.value("locale").toLocale();
JsonReply *jsonReply = createAsyncReply("ConfirmPairing");
DevicePairingInfo *info = NymeaCore::instance()->deviceManager()->confirmPairing(pairingTransactionId, username, secret);
connect(info, &DevicePairingInfo::finished, jsonReply, [info, jsonReply, locale](){
JsonReply *reply = nullptr;
if (status == Device::DeviceErrorAsync) {
reply = createAsyncReply("ConfirmPairing");
connect(reply, &JsonReply::finished, [this, pairingTransactionId](){ m_asyncPairingRequests.remove(pairingTransactionId); });
m_asyncPairingRequests.insert(pairingTransactionId, reply);
return reply;
}
QVariantMap returns; QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status()));
reply = createReply(returns); if (!info->displayMessage().isEmpty()) {
return reply; returns.insert("displayMessage", info->translatedDisplayMessage(locale));
}
if (info->status() == Device::DeviceErrorNoError) {
returns.insert("deviceId", info->deviceId().toString());
}
jsonReply->setData(returns);
jsonReply->finished();
});
return jsonReply;
} }
JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap &params) const JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap &params) const
@ -529,28 +576,30 @@ JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap &params) const
JsonReply *DeviceHandler::ReconfigureDevice(const QVariantMap &params) JsonReply *DeviceHandler::ReconfigureDevice(const QVariantMap &params)
{ {
Q_UNUSED(params);
DeviceId deviceId = DeviceId(params.value("deviceId").toString()); DeviceId deviceId = DeviceId(params.value("deviceId").toString());
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
Device::DeviceError status;
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
QLocale locale = params.value("locale").toLocale();
JsonReply *jsonReply = createAsyncReply("ReconfigureDevice");
DeviceSetupInfo *info;
if (deviceDescriptorId.isNull()) { if (deviceDescriptorId.isNull()) {
status = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceId, deviceParams); info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceId, deviceParams);
} else { } else {
status = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceId, deviceDescriptorId); info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceId, deviceDescriptorId);
} }
if (status == Device::DeviceErrorAsync) { connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){
JsonReply *asyncReply = createAsyncReply("ReconfigureDevice");
connect(asyncReply, &JsonReply::finished, [this, deviceId](){ m_asynDeviceEditAdditions.remove(deviceId); });
m_asynDeviceEditAdditions.insert(deviceId, asyncReply);
return asyncReply;
}
QVariantMap returns; QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status)); returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status()));
return createReply(returns); returns.insert("displayMessage", info->translatedDisplayMessage(locale));
jsonReply->setData(returns);
jsonReply->finished();
});
return jsonReply;
} }
JsonReply *DeviceHandler::EditDevice(const QVariantMap &params) JsonReply *DeviceHandler::EditDevice(const QVariantMap &params)
@ -687,24 +736,22 @@ JsonReply *DeviceHandler::GetStateValues(const QVariantMap &params) const
JsonReply *DeviceHandler::BrowseDevice(const QVariantMap &params) const JsonReply *DeviceHandler::BrowseDevice(const QVariantMap &params) const
{ {
QVariantMap returns;
DeviceId deviceId = DeviceId(params.value("deviceId").toString()); DeviceId deviceId = DeviceId(params.value("deviceId").toString());
QString itemId = params.value("itemId").toString(); QString itemId = params.value("itemId").toString();
Device::BrowseResult result = NymeaCore::instance()->deviceManager()->browseDevice(deviceId, itemId, params.value("locale").toLocale()); JsonReply *jsonReply = createAsyncReply("BrowseDevice");
if (result.status == Device::DeviceErrorAsync ) { BrowseResult *result = NymeaCore::instance()->deviceManager()->browseDevice(deviceId, itemId, params.value("locale").toLocale());
JsonReply *reply = createAsyncReply("BrowseDevice"); connect(result, &BrowseResult::finished, jsonReply, [jsonReply, result](){
m_asyncBrowseRequests.insert(result.id(), reply);
connect(reply, &JsonReply::finished, this, [this, result](){ QVariantMap returns;
m_asyncBrowseRequests.remove(result.id()); returns.insert("deviceError", JsonTypes::deviceErrorToString(result->status()));
returns.insert("items", JsonTypes::packBrowserItems(result->items()));
jsonReply->setData(returns);
jsonReply->finished();
}); });
return reply;
}
returns.insert("deviceError", JsonTypes::deviceErrorToString(result.status)); return jsonReply;
returns.insert("items", JsonTypes::packBrowserItems(result.items));
return createReply(returns);
} }
JsonReply *DeviceHandler::GetBrowserItem(const QVariantMap &params) const JsonReply *DeviceHandler::GetBrowserItem(const QVariantMap &params) const
@ -713,22 +760,20 @@ JsonReply *DeviceHandler::GetBrowserItem(const QVariantMap &params) const
DeviceId deviceId = DeviceId(params.value("deviceId").toString()); DeviceId deviceId = DeviceId(params.value("deviceId").toString());
QString itemId = params.value("itemId").toString(); QString itemId = params.value("itemId").toString();
Device::BrowserItemResult result = NymeaCore::instance()->deviceManager()->browserItemDetails(deviceId, itemId, params.value("locale").toLocale()); JsonReply *jsonReply = createAsyncReply("GetBrowserItem");
if (result.status == Device::DeviceErrorAsync ) { BrowserItemResult *result = NymeaCore::instance()->deviceManager()->browserItemDetails(deviceId, itemId, params.value("locale").toLocale());
JsonReply *reply = createAsyncReply("GetBrowserItem"); connect(result, &BrowserItemResult::finished, jsonReply, [jsonReply, result](){
m_asyncBrowseDetailsRequests.insert(result.id(), reply); QVariantMap params;
connect(reply, &JsonReply::finished, this, [this, result](){ if (result->status() == Device::DeviceErrorNoError) {
m_asyncBrowseDetailsRequests.remove(result.id()); params.insert("item", JsonTypes::packBrowserItem(result->item()));
}
params.insert("deviceError", JsonTypes::deviceErrorToString(result->status()));
jsonReply->setData(params);
jsonReply->finished();
}); });
return reply;
}
returns.insert("deviceError", JsonTypes::deviceErrorToString(result.status)); return jsonReply;
if (result.status == Device::DeviceErrorNoError) {
returns.insert("item", JsonTypes::packBrowserItem(result.item));
}
return createReply(returns);
} }
void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config) void DeviceHandler::pluginConfigChanged(const PluginId &id, const ParamList &config)
@ -786,105 +831,4 @@ void DeviceHandler::deviceSettingChangedNotification(const DeviceId deviceId, co
emit DeviceSettingChanged(params); emit DeviceSettingChanged(params);
} }
void DeviceHandler::devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors)
{
if (!m_discoverRequests.contains(deviceClassId)) {
return; // We didn't start this discovery... Ignore it.
}
JsonReply *reply = nullptr;
reply = m_discoverRequests.take(deviceClassId);
if (!reply)
return;
QVariantMap returns;
returns.insert("deviceDescriptors", JsonTypes::packDeviceDescriptors(deviceDescriptors));
returns.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorNoError));
reply->setData(returns);
reply->finished();
}
void DeviceHandler::deviceSetupFinished(Device *device, Device::DeviceError status)
{
qCDebug(dcJsonRpc) << "Got a device setup finished" << device->name() << device->id();
if (!m_asynDeviceAdditions.contains(device->id())) {
return; // Not the device we're waiting for...
}
JsonReply *reply = m_asynDeviceAdditions.take(device->id());
QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
if(status == Device::DeviceErrorNoError) {
returns.insert("deviceId", device->id());
}
reply->setData(returns);
reply->finished();
}
void DeviceHandler::deviceReconfigurationFinished(Device *device, Device::DeviceError status)
{
qCDebug(dcJsonRpc) << "Got async device reconfiguration finished";
if (!m_asynDeviceEditAdditions.contains(device->id())) {
return;
}
JsonReply *reply = m_asynDeviceEditAdditions.take(device->id());
QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
reply->setData(returns);
reply->finished();
}
void DeviceHandler::pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId)
{
qCDebug(dcJsonRpc) << "Got pairing finished";
JsonReply *reply = m_asyncPairingRequests.take(pairingTransactionId);
if (!reply) {
return;
}
if (status != Device::DeviceErrorNoError) {
QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
reply->setData(returns);
reply->finished();
return;
}
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("items", JsonTypes::packBrowserItems(result.items));
params.insert("deviceError", JsonTypes::deviceErrorToString(result.status));
reply->setData(params);
reply->finished();
}
void DeviceHandler::browserItemRequestFinished(const Device::BrowserItemResult &result)
{
if (!m_asyncBrowseDetailsRequests.contains(result.id())) {
qCWarning(dcJsonRpc()) << "No pending JsonRpc reply for result" << result.id() << ". Did it time out?";
return;
}
JsonReply *reply = m_asyncBrowseDetailsRequests.take(result.id());
QVariantMap params;
if (result.status == Device::DeviceErrorNoError) {
params.insert("item", JsonTypes::packBrowserItem(result.item));
}
params.insert("deviceError", JsonTypes::deviceErrorToString(result.status));
reply->setData(params);
reply->finished();
}
} }

View File

@ -80,27 +80,6 @@ private slots:
void deviceChangedNotification(Device *device); void deviceChangedNotification(Device *device);
void deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId &paramTypeId, const QVariant &value); void deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId &paramTypeId, const QVariant &value);
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
void deviceSetupFinished(Device *device, Device::DeviceError status);
void deviceReconfigurationFinished(Device *device, Device::DeviceError status);
void pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId);
void browseRequestFinished(const Device::BrowseResult &result);
void browserItemRequestFinished(const Device::BrowserItemResult &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;
mutable QHash<QUuid, JsonReply*> m_asyncBrowseDetailsRequests;
}; };
} }

View File

@ -55,22 +55,6 @@
The \a status of the \l{Action} execution will be described as \l{Device::DeviceError}{DeviceError}. The \a status of the \l{Action} execution will be described as \l{Device::DeviceError}{DeviceError}.
*/ */
/*! \fn void nymeaserver::NymeaCore::devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
This signal is emitted when the discovery of a \a deviceClassId is finished. The \a deviceDescriptors parameter describes the
list of \l{DeviceDescriptor}{DeviceDescriptors} of all discovered \l{Device}{Devices}.
\sa DeviceManager::discoverDevices()
*/
/*! \fn void nymeaserver::NymeaCore::deviceSetupFinished(Device *device, Device::DeviceError status);
This signal is emitted when the setup of a \a device is finished. The \a status parameter describes the
\l{Device::DeviceError}{DeviceError} that occurred.
*/
/*! \fn void nymeaserver::NymeaCore::deviceReconfigurationFinished(Device *device, Device::DeviceError status);
This signal is emitted when the edit request of a \a device is finished. The \a status of the edit request will be
described as \l{Device::DeviceError}{DeviceError}.
*/
/*! \fn void nymeaserver::NymeaCore::pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId); /*! \fn void nymeaserver::NymeaCore::pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId);
The DeviceManager will emit a this Signal when the pairing of a \l{Device} with the \a deviceId and \a pairingTransactionId is finished. The DeviceManager will emit a this Signal when the pairing of a \l{Device} with the \a deviceId and \a pairingTransactionId is finished.
The \a status of the pairing will be described as \l{Device::DeviceError}{DeviceError}. The \a status of the pairing will be described as \l{Device::DeviceError}{DeviceError}.
@ -116,6 +100,9 @@
#include "devices/devicemanagerimplementation.h" #include "devices/devicemanagerimplementation.h"
#include "devices/device.h" #include "devices/device.h"
#include "devices/deviceactioninfo.h"
#include "devices/browseractioninfo.h"
#include "devices/browseritemactioninfo.h"
#include "cloud/cloudnotifications.h" #include "cloud/cloudnotifications.h"
#include "cloud/cloudtransport.h" #include "cloud/cloudtransport.h"
@ -200,13 +187,6 @@ void NymeaCore::init() {
connect(m_deviceManager, &DeviceManagerImplementation::deviceSettingChanged, this, &NymeaCore::deviceSettingChanged); connect(m_deviceManager, &DeviceManagerImplementation::deviceSettingChanged, this, &NymeaCore::deviceSettingChanged);
connect(m_deviceManager, &DeviceManagerImplementation::deviceRemoved, this, &NymeaCore::deviceRemoved); connect(m_deviceManager, &DeviceManagerImplementation::deviceRemoved, this, &NymeaCore::deviceRemoved);
connect(m_deviceManager, &DeviceManagerImplementation::deviceDisappeared, this, &NymeaCore::onDeviceDisappeared); 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::browserItemActionExecutionFinished, this, &NymeaCore::browserItemActionExecutionFinished);
connect(m_deviceManager, &DeviceManagerImplementation::devicesDiscovered, this, &NymeaCore::devicesDiscovered);
connect(m_deviceManager, &DeviceManagerImplementation::deviceSetupFinished, this, &NymeaCore::deviceSetupFinished);
connect(m_deviceManager, &DeviceManagerImplementation::deviceReconfigurationFinished, this, &NymeaCore::deviceReconfigurationFinished);
connect(m_deviceManager, &DeviceManagerImplementation::pairingFinished, this, &NymeaCore::pairingFinished);
connect(m_deviceManager, &DeviceManagerImplementation::loaded, this, &NymeaCore::deviceManagerLoaded); connect(m_deviceManager, &DeviceManagerImplementation::loaded, this, &NymeaCore::deviceManagerLoaded);
connect(m_ruleEngine, &RuleEngine::ruleAdded, this, &NymeaCore::ruleAdded); connect(m_ruleEngine, &RuleEngine::ruleAdded, this, &NymeaCore::ruleAdded);
@ -436,43 +416,36 @@ Device::DeviceError NymeaCore::removeConfiguredDevice(const DeviceId &deviceId,
/*! Calls the metheod DeviceManager::executeAction(\a action). /*! Calls the metheod DeviceManager::executeAction(\a action).
* \sa DeviceManager::executeAction(), */ * \sa DeviceManager::executeAction(), */
Device::DeviceError NymeaCore::executeAction(const Action &action) DeviceActionInfo* NymeaCore::executeAction(const Action &action)
{ {
Device::DeviceError ret = m_deviceManager->executeAction(action); DeviceActionInfo *info = m_deviceManager->executeAction(action);
if (ret == Device::DeviceErrorNoError) { connect(info, &DeviceActionInfo::finished, this, [this, info](){
m_logger->logAction(action); if (info->status() == Device::DeviceErrorNoError) {
} else if (ret == Device::DeviceErrorAsync) { m_logger->logAction(info->action());
m_pendingActions.insert(action.id(), action);
} else { } else {
m_logger->logAction(action, Logging::LoggingLevelAlert, ret); m_logger->logAction(info->action(), Logging::LoggingLevelAlert, info->status());
} }
return ret; });
return info;
} }
Device::DeviceError NymeaCore::executeBrowserItem(const BrowserAction &browserAction) BrowserActionInfo* NymeaCore::executeBrowserItem(const BrowserAction &browserAction)
{ {
Device::DeviceError ret = m_deviceManager->executeBrowserItem(browserAction); BrowserActionInfo *info = m_deviceManager->executeBrowserItem(browserAction);
if (ret == Device::DeviceErrorNoError) { connect(info, &BrowserActionInfo::finished, info->device(), [this, info](){
m_logger->logBrowserAction(browserAction); m_logger->logBrowserAction(info->browserAction(), info->status() == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, info->status());
} else if (ret == Device::DeviceErrorAsync) { });
m_pendingBrowserActions.insert(browserAction.id(), browserAction); return info;
} else {
m_logger->logBrowserAction(browserAction, Logging::LoggingLevelAlert, ret);
}
return ret;
} }
Device::DeviceError NymeaCore::executeBrowserItemAction(const BrowserItemAction &browserItemAction) BrowserItemActionInfo *NymeaCore::executeBrowserItemAction(const BrowserItemAction &browserItemAction)
{ {
Device::DeviceError ret = m_deviceManager->executeBrowserItemAction(browserItemAction); BrowserItemActionInfo *info = m_deviceManager->executeBrowserItemAction(browserItemAction);
if (ret == Device::DeviceErrorNoError) { connect(info, &BrowserItemActionInfo::finished, info->device(), [this, info](){
m_logger->logBrowserItemAction(browserItemAction); m_logger->logBrowserItemAction(info->browserItemAction(), info->status() == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, info->status());
} else if (ret == Device::DeviceErrorAsync) { });
m_pendingBrowserItemActions.insert(browserItemAction.id(), browserItemAction); return info;
} else {
m_logger->logBrowserItemAction(browserItemAction, Logging::LoggingLevelAlert, ret);
}
return ret;
} }
/*! Execute the given \a ruleActions. */ /*! Execute the given \a ruleActions. */
@ -575,44 +548,21 @@ void NymeaCore::executeRuleActions(const QList<RuleAction> ruleActions)
foreach (const Action &action, actions) { foreach (const Action &action, actions) {
qCDebug(dcRuleEngine) << "Executing action" << action.actionTypeId() << action.params(); qCDebug(dcRuleEngine) << "Executing action" << action.actionTypeId() << action.params();
Device::DeviceError status = executeAction(action); DeviceActionInfo *info = executeAction(action);
switch(status) { connect(info, &DeviceActionInfo::finished, this, [info](){
case Device::DeviceErrorNoError: if (info->status() != Device::DeviceErrorNoError) {
break; qCWarning(dcRuleEngine) << "Error executing action:" << info->status() << info->displayMessage();
case Device::DeviceErrorSetupFailed:
qCWarning(dcRuleEngine) << "Error executing action. Device setup failed.";
break;
case Device::DeviceErrorAsync:
qCDebug(dcRuleEngine) << "Executing asynchronous action.";
break;
case Device::DeviceErrorInvalidParameter:
qCWarning(dcRuleEngine) << "Error executing action. Invalid action parameter.";
break;
default:
qCWarning(dcRuleEngine) << "Error executing action:" << status;
} }
});
// if (status != Device::DeviceErrorAsync)
// m_logger->logAction(action, status == Device::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, status);
} }
foreach (const BrowserAction &browserAction, browserActions) { foreach (const BrowserAction &browserAction, browserActions) {
Device::DeviceError status = executeBrowserItem(browserAction); BrowserActionInfo *info = executeBrowserItem(browserAction);
switch(status) { connect(info, &BrowserActionInfo::finished, this, [info](){
case Device::DeviceErrorNoError: if (info->status() != Device::DeviceErrorNoError) {
break; qCWarning(dcRuleEngine) << "Error executing browser action:" << info->status();
case Device::DeviceErrorSetupFailed:
qCWarning(dcRuleEngine) << "Error executing action. Device setup failed.";
break;
case Device::DeviceErrorAsync:
qCDebug(dcRuleEngine) << "Executing asynchronous action.";
break;
case Device::DeviceErrorInvalidParameter:
qCWarning(dcRuleEngine) << "Error executing action. Invalid action parameter.";
break;
default:
qCWarning(dcRuleEngine) << "Error executing action:" << status;
} }
});
} }
} }
@ -850,27 +800,6 @@ RestServer *NymeaCore::restServer() const
return m_serverManager->restServer(); return m_serverManager->restServer();
} }
void NymeaCore::actionExecutionFinished(const ActionId &id, Device::DeviceError status)
{
emit actionExecuted(id, status);
Action action = m_pendingActions.take(id);
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);
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) void NymeaCore::onDeviceDisappeared(const DeviceId &deviceId)
{ {
Device *device = m_deviceManager->findConfiguredDevice(deviceId); Device *device = m_deviceManager->findConfiguredDevice(deviceId);

View File

@ -71,9 +71,9 @@ public:
QPair<Device::DeviceError, QList<RuleId> >removeConfiguredDevice(const DeviceId &deviceId, const QHash<RuleId, RuleEngine::RemovePolicy> &removePolicyList); QPair<Device::DeviceError, QList<RuleId> >removeConfiguredDevice(const DeviceId &deviceId, const QHash<RuleId, RuleEngine::RemovePolicy> &removePolicyList);
Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId, const RuleEngine::RemovePolicy &removePolicy); Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId, const RuleEngine::RemovePolicy &removePolicy);
Device::DeviceError executeAction(const Action &action); DeviceActionInfo *executeAction(const Action &action);
Device::DeviceError executeBrowserItem(const BrowserAction &browserAction); BrowserActionInfo* executeBrowserItem(const BrowserAction &browserAction);
Device::DeviceError executeBrowserItemAction(const BrowserItemAction &browserItemAction); BrowserItemActionInfo* executeBrowserItemAction(const BrowserItemAction &browserItemAction);
void executeRuleActions(const QList<RuleAction> ruleActions); void executeRuleActions(const QList<RuleAction> ruleActions);
@ -107,14 +107,6 @@ signals:
void deviceAdded(Device *device); void deviceAdded(Device *device);
void deviceChanged(Device *device); void deviceChanged(Device *device);
void deviceSettingChanged(const DeviceId deviceId, const ParamTypeId &settingParamTypeId, const QVariant &value); 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);
void deviceReconfigurationFinished(Device *device, Device::DeviceError status);
void pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId);
void ruleRemoved(const RuleId &ruleId); void ruleRemoved(const RuleId &ruleId);
void ruleAdded(const Rule &rule); void ruleAdded(const Rule &rule);
@ -142,17 +134,11 @@ private:
UserManager *m_userManager; UserManager *m_userManager;
System *m_system; System *m_system;
QHash<ActionId, Action> m_pendingActions;
QHash<ActionId, BrowserAction> m_pendingBrowserActions;
QHash<ActionId, BrowserItemAction> m_pendingBrowserItemActions;
QList<RuleId> m_executingRules; QList<RuleId> m_executingRules;
private slots: private slots:
void gotEvent(const Event &event); void gotEvent(const Event &event);
void onDateTimeChanged(const QDateTime &dateTime); 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 onDeviceDisappeared(const DeviceId &deviceId);
void deviceManagerLoaded(); void deviceManagerLoaded();

View File

@ -38,6 +38,7 @@
#include "deviceclassesresource.h" #include "deviceclassesresource.h"
#include "servers/httprequest.h" #include "servers/httprequest.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "devices/devicediscoveryinfo.h"
#include <QJsonDocument> #include <QJsonDocument>
@ -47,7 +48,6 @@ namespace nymeaserver {
DeviceClassesResource::DeviceClassesResource(QObject *parent) : DeviceClassesResource::DeviceClassesResource(QObject *parent) :
RestResource(parent) RestResource(parent)
{ {
connect(NymeaCore::instance(), &NymeaCore::devicesDiscovered, this, &DeviceClassesResource::devicesDiscovered, Qt::QueuedConnection);
} }
/*! Returns the name of the \l{RestResource}. In this case \b deviceclasses. /*! Returns the name of the \l{RestResource}. In this case \b deviceclasses.
@ -265,36 +265,24 @@ HttpReply *DeviceClassesResource::getDiscoverdDevices(const ParamList &discovery
qCDebug(dcRest) << "Discover devices for DeviceClass" << m_deviceClass.id(); qCDebug(dcRest) << "Discover devices for DeviceClass" << m_deviceClass.id();
qCDebug(dcRest) << discoveryParams; qCDebug(dcRest) << discoveryParams;
Device::DeviceError status = NymeaCore::instance()->deviceManager()->discoverDevices(m_deviceClass.id(), discoveryParams); DeviceDiscoveryInfo *info = NymeaCore::instance()->deviceManager()->discoverDevices(m_deviceClass.id(), discoveryParams);
if (status == Device::DeviceErrorAsync) {
HttpReply *reply = createAsyncReply(); HttpReply *reply = createAsyncReply();
m_discoverRequests.insert(m_deviceClass.id(), reply); connect(info, &DeviceDiscoveryInfo::finished, reply, [info, reply](){
return reply;
}
if (status != Device::DeviceErrorNoError)
return createDeviceErrorReply(HttpReply::InternalServerError, status);
return createSuccessReply();
}
void DeviceClassesResource::devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors)
{
if (!m_discoverRequests.contains(deviceClassId))
return; // Not the discovery we are waiting for.
qCDebug(dcRest) << "Discovery finished. Found" << deviceDescriptors.count() << "devices.";
if (m_discoverRequests.value(deviceClassId).isNull()) {
qCWarning(dcRest) << "Async reply for discovery does not exist any more (timeout).";
return;
}
HttpReply *reply = m_discoverRequests.take(deviceClassId);
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceDescriptors(deviceDescriptors)).toJson()); QVariantMap response;
if (info->status() != Device::DeviceErrorNoError) {
reply->setHttpStatusCode(HttpReply::InternalServerError);
response.insert("error", JsonTypes::deviceErrorToString(info->status()));
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
} else {
reply->setHttpStatusCode(HttpReply::Ok);
reply->setPayload(QJsonDocument::fromVariant(JsonTypes::packDeviceDescriptors(info->deviceDescriptors())).toJson());
}
reply->finished(); reply->finished();
});
return reply;
} }
HttpReply *DeviceClassesResource::getDeviceClasses(const VendorId &vendorId) HttpReply *DeviceClassesResource::getDeviceClasses(const VendorId &vendorId)

View File

@ -67,9 +67,6 @@ private:
HttpReply *getDiscoverdDevices(const ParamList &discoveryParams); HttpReply *getDiscoverdDevices(const ParamList &discoveryParams);
private slots:
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
}; };
} }

View File

@ -41,6 +41,9 @@
#include "servers/httprequest.h" #include "servers/httprequest.h"
#include "jsonrpc/jsontypes.h" #include "jsonrpc/jsontypes.h"
#include "nymeacore.h" #include "nymeacore.h"
#include "devices/devicesetupinfo.h"
#include "devices/devicepairinginfo.h"
#include "devices/deviceactioninfo.h"
#include <QJsonDocument> #include <QJsonDocument>
@ -50,10 +53,6 @@ namespace nymeaserver {
DevicesResource::DevicesResource(QObject *parent) : DevicesResource::DevicesResource(QObject *parent) :
RestResource(parent) RestResource(parent)
{ {
connect(NymeaCore::instance(), &NymeaCore::actionExecuted, this, &DevicesResource::actionExecuted);
connect(NymeaCore::instance(), &NymeaCore::deviceSetupFinished, this, &DevicesResource::deviceSetupFinished);
connect(NymeaCore::instance(), &NymeaCore::deviceReconfigurationFinished, this, &DevicesResource::deviceReconfigurationFinished);
connect(NymeaCore::instance(), &NymeaCore::pairingFinished, this, &DevicesResource::pairingFinished);
} }
/*! Returns the name of the \l{RestResource}. In this case \b devices. /*! Returns the name of the \l{RestResource}. In this case \b devices.
@ -337,17 +336,30 @@ HttpReply *DevicesResource::executeAction(Device *device, const ActionTypeId &ac
Action action(actionTypeId, device->id()); Action action(actionTypeId, device->id());
action.setParams(actionParams); action.setParams(actionParams);
Device::DeviceError status = NymeaCore::instance()->executeAction(action); HttpReply *httpReply = createAsyncReply();
if (status == Device::DeviceErrorAsync) {
HttpReply *reply = createAsyncReply(); DeviceActionInfo *info = NymeaCore::instance()->executeAction(action);
m_asyncActionExecutions.insert(action.id(), reply); connect(info, &DeviceActionInfo::finished, this, [info, httpReply](){
return reply; QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(info->status()));
httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (info->status() == Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Action execution finished successfully";
httpReply->setHttpStatusCode(HttpReply::Ok);
httpReply->setPayload(QJsonDocument::fromVariant(response).toJson());
} else {
qCDebug(dcRest) << "Action execution finished with error" << info->status();
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(info->status()));
httpReply->setHttpStatusCode(HttpReply::InternalServerError);
httpReply->setPayload(QJsonDocument::fromVariant(response).toJson());
} }
if (status != Device::DeviceErrorNoError) httpReply->finished();
return createDeviceErrorReply(HttpReply::InternalServerError, status); });
return createDeviceErrorReply(HttpReply::Ok, status); return httpReply;
} }
HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const
@ -367,29 +379,35 @@ HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
Device::DeviceError status; HttpReply *httpReply = createAsyncReply();
DeviceSetupInfo *info;
if (deviceDescriptorId.isNull()) { if (deviceDescriptorId.isNull()) {
qCDebug(dcRest) << "Adding device" << deviceName << "with" << deviceParams; qCDebug(dcRest) << "Adding device" << deviceName << "with" << deviceParams;
status = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceName, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceName, deviceParams, newDeviceId);
} else { } else {
qCDebug(dcRest) << "Adding discovered device" << deviceName << "with DeviceDescriptorId" << deviceDescriptorId.toString(); qCDebug(dcRest) << "Adding discovered device" << deviceName << "with DeviceDescriptorId" << deviceDescriptorId.toString();
status = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceName, deviceDescriptorId, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceName, deviceDescriptorId, deviceParams, newDeviceId);
}
if (status == Device::DeviceErrorAsync) {
HttpReply *reply = createAsyncReply();
qCDebug(dcRest) << "Device setup async reply";
m_asyncDeviceAdditions.insert(newDeviceId, reply);
return reply;
} }
if (status != Device::DeviceErrorNoError) connect(info, &DeviceSetupInfo::finished, httpReply, [info, httpReply](){
return createDeviceErrorReply(HttpReply::InternalServerError, status); httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (info->status() != Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Device setup finished with error" << info->status();
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(info->status()));
httpReply->setHttpStatusCode(HttpReply::InternalServerError);
httpReply->setPayload(QJsonDocument::fromVariant(response).toJson());
} else {
httpReply->setHttpStatusCode(HttpReply::Ok);
QVariant result = JsonTypes::packDevice(info->device());
httpReply->setPayload(QJsonDocument::fromVariant(result).toJson());
}
qCDebug(dcRest) << "Device setup finished successfully";
httpReply->finished();
});
QVariant result = JsonTypes::packDevice(NymeaCore::instance()->deviceManager()->findConfiguredDevice(newDeviceId)); return httpReply;
HttpReply *reply = createSuccessReply();
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(result).toJson());
return reply;
} }
HttpReply *DevicesResource::editDevice(const QByteArray &payload) const HttpReply *DevicesResource::editDevice(const QByteArray &payload) const
@ -428,27 +446,38 @@ HttpReply *DevicesResource::pairDevice(const QByteArray &payload) const
qCDebug(dcRest) << "Pair device" << deviceName << "with deviceClassId" << deviceClassId.toString(); qCDebug(dcRest) << "Pair device" << deviceName << "with deviceClassId" << deviceClassId.toString();
Device::DeviceError status; HttpReply *httpReply = createAsyncReply();
PairingTransactionId pairingTransactionId = PairingTransactionId::createPairingTransactionId();
DevicePairingInfo *info;
if (params.contains("deviceDescriptorId")) { if (params.contains("deviceDescriptorId")) {
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
status = NymeaCore::instance()->deviceManager()->pairDevice(pairingTransactionId, deviceClassId, deviceName, deviceDescriptorId); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceDescriptorId);
} else { } else {
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
status = NymeaCore::instance()->deviceManager()->pairDevice(pairingTransactionId, deviceClassId, deviceName, deviceParams); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceParams);
} }
if (status != Device::DeviceErrorNoError) connect(info, &DevicePairingInfo::finished, httpReply, [info, httpReply](){
return createDeviceErrorReply(HttpReply::BadRequest, status); httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (info->status() != Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Device setup finished with error" << info->status();
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(info->status()));
httpReply->setHttpStatusCode(HttpReply::InternalServerError);
httpReply->setPayload(QJsonDocument::fromVariant(response).toJson());
} else {
httpReply->setHttpStatusCode(HttpReply::Ok);
QVariantMap returns; QVariantMap returns;
returns.insert("displayMessage", NymeaCore::instance()->deviceManager()->translate(deviceClass.pluginId(), deviceClass.pairingInfo(), NymeaCore::instance()->configuration()->locale())); returns.insert("error", JsonTypes::deviceErrorToString(info->status()));
returns.insert("pairingTransactionId", pairingTransactionId.toString()); returns.insert("pairingTransactionId", info->transactionId().toString());
returns.insert("setupMethod", JsonTypes::setupMethod().at(deviceClass.setupMethod())); returns.insert("displayMessage", info->displayMessage());
HttpReply *reply = createSuccessReply(); httpReply->setPayload(QJsonDocument::fromVariant(returns).toJson());
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";"); }
reply->setPayload(QJsonDocument::fromVariant(returns).toJson()); qCDebug(dcRest) << "Device pairing initiated successfully";
return reply; httpReply->finished();
});
return httpReply;
} }
HttpReply *DevicesResource::confirmPairDevice(const QByteArray &payload) const HttpReply *DevicesResource::confirmPairDevice(const QByteArray &payload) const
@ -460,20 +489,29 @@ HttpReply *DevicesResource::confirmPairDevice(const QByteArray &payload) const
QVariantMap params = verification.second.toMap(); QVariantMap params = verification.second.toMap();
PairingTransactionId pairingTransactionId = PairingTransactionId(params.value("pairingTransactionId").toString()); PairingTransactionId pairingTransactionId = PairingTransactionId(params.value("pairingTransactionId").toString());
QString username = params.value("username").toString();
QString secret = params.value("secret").toString(); QString secret = params.value("secret").toString();
Device::DeviceError status = NymeaCore::instance()->deviceManager()->confirmPairing(pairingTransactionId, secret);
if (status == Device::DeviceErrorAsync) { HttpReply *httpReply = createAsyncReply();
HttpReply *reply = createAsyncReply();
qCDebug(dcRest) << "Confirm pairing async reply"; DevicePairingInfo *info = NymeaCore::instance()->deviceManager()->confirmPairing(pairingTransactionId, username, secret);
m_asyncPairingRequests.insert(pairingTransactionId, reply); connect(info, &DevicePairingInfo::finished, httpReply, [info, httpReply](){
return reply; qCDebug(dcRest()) << "Confirm pairing finished:" << info->status();
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(info->status()));
if (info->status() != Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Pairing device finished with error.";
httpReply->setHttpStatusCode(HttpReply::InternalServerError);
} else {
httpReply->setHttpStatusCode(HttpReply::Ok);
response.insert("id", info->deviceId().toString());
} }
httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
httpReply->setPayload(QJsonDocument::fromVariant(response).toJson());
httpReply->finished();
});
if (status != Device::DeviceErrorNoError) return httpReply;
return createDeviceErrorReply(HttpReply::InternalServerError, status);
return createDeviceErrorReply(HttpReply::Ok, Device::DeviceErrorNoError);
} }
HttpReply *DevicesResource::reconfigureDevice(Device *device, const QByteArray &payload) const HttpReply *DevicesResource::reconfigureDevice(Device *device, const QByteArray &payload) const
@ -486,145 +524,35 @@ HttpReply *DevicesResource::reconfigureDevice(Device *device, const QByteArray &
QVariantMap params = verification.second.toMap(); QVariantMap params = verification.second.toMap();
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
Device::DeviceError status; HttpReply *httpReply = createAsyncReply();
DeviceSetupInfo *info;
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
if (deviceDescriptorId.isNull()) { if (deviceDescriptorId.isNull()) {
qCDebug(dcRest) << "Reconfigure device with params:" << deviceParams; qCDebug(dcRest) << "Reconfigure device with params:" << deviceParams;
status = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceParams); info = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceParams);
} else { } else {
qCDebug(dcRest) << "Reconfigure device using the new discovered device with descriptorId:" << deviceDescriptorId.toString(); qCDebug(dcRest) << "Reconfigure device using the new discovered device with descriptorId:" << deviceDescriptorId.toString();
status = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceDescriptorId); info = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceDescriptorId);
} }
if (status == Device::DeviceErrorAsync) { connect(info, &DeviceSetupInfo::finished, httpReply, [httpReply, info](){
HttpReply *reply = createAsyncReply(); httpReply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
qCDebug(dcRest) << "Device reconfiguration async reply"; if (info->status() != Device::DeviceErrorNoError) {
m_asyncReconfigureDevice.insert(device, reply); qCDebug(dcRest) << "Device reconfiguration finished with error" << info->status();
return reply;
}
if (status != Device::DeviceErrorNoError)
return createDeviceErrorReply(HttpReply::InternalServerError, status);
return createDeviceErrorReply(HttpReply::Ok, Device::DeviceErrorNoError);
}
void DevicesResource::actionExecuted(const ActionId &actionId, Device::DeviceError status)
{
if (!m_asyncActionExecutions.contains(actionId))
return; // Not the action we are waiting for.
QVariantMap response; QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status)); response.insert("error", JsonTypes::deviceErrorToString(info->status()));
httpReply->setHttpStatusCode(HttpReply::InternalServerError);
if (m_asyncActionExecutions.value(actionId).isNull()) { httpReply->setPayload(QJsonDocument::fromVariant(response).toJson());
qCWarning(dcRest) << "Async reply for execute action does not exist any more (timeout).";
return;
}
HttpReply *reply = m_asyncActionExecutions.take(actionId);
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (status == Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Action execution finished successfully";
reply->setHttpStatusCode(HttpReply::Ok);
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
} else { } else {
qCDebug(dcRest) << "Action execution finished with error" << status;
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
reply->setHttpStatusCode(HttpReply::InternalServerError);
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
}
reply->finished();
}
void DevicesResource::deviceSetupFinished(Device *device, Device::DeviceError status)
{
if (!m_asyncDeviceAdditions.contains(device->id()))
return; // Not the device we are waiting for.
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
if (m_asyncDeviceAdditions.value(device->id()).isNull()) {
qCWarning(dcRest) << "Async reply for device setup does not exist any more (timeout).";
return;
}
HttpReply *reply = m_asyncDeviceAdditions.take(device->id());
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (status == Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Device setup finished successfully";
reply->setHttpStatusCode(HttpReply::Ok);
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
} else {
qCDebug(dcRest) << "Device setup finished with error" << status;
reply->setHttpStatusCode(HttpReply::InternalServerError);
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
}
QVariant result = JsonTypes::packDevice(device);
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setPayload(QJsonDocument::fromVariant(result).toJson());
reply->finished();
}
void DevicesResource::deviceReconfigurationFinished(Device *device, Device::DeviceError status)
{
if (!m_asyncReconfigureDevice.contains(device))
return; // Not the device we are waiting for.
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
if (m_asyncReconfigureDevice.value(device).isNull()) {
qCWarning(dcRest) << "Async reply for device reconfiguration does not exist any more (timeout).";
return;
}
HttpReply *reply = m_asyncReconfigureDevice.take(device);
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
if (status == Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Device reconfiguration finished successfully"; qCDebug(dcRest) << "Device reconfiguration finished successfully";
reply->setHttpStatusCode(HttpReply::Ok); httpReply->setHttpStatusCode(HttpReply::Ok);
reply->setPayload(QJsonDocument::fromVariant(response).toJson()); QVariant result = JsonTypes::packDevice(info->device());
} else { httpReply->setPayload(QJsonDocument::fromVariant(result).toJson());
qCDebug(dcRest) << "Device reconfiguration finished with error" << status;
reply->setHttpStatusCode(HttpReply::InternalServerError);
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
} }
httpReply->finished();
});
reply->finished(); return httpReply;
} }
void DevicesResource::pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId)
{
if (!m_asyncPairingRequests.contains(pairingTransactionId))
return; // Not the device pairing we are waiting for.
QVariantMap response;
response.insert("error", JsonTypes::deviceErrorToString(status));
if (m_asyncPairingRequests.value(pairingTransactionId).isNull()) {
qCWarning(dcRest) << "Async reply for device pairing does not exist any more.";
return;
}
HttpReply *reply = m_asyncPairingRequests.take(pairingTransactionId);
if (status != Device::DeviceErrorNoError) {
qCDebug(dcRest) << "Pairing device finished with error.";
reply->setHeader(HttpReply::ContentTypeHeader, "application/json; charset=\"utf-8\";");
reply->setHttpStatusCode(HttpReply::InternalServerError);
reply->setPayload(QJsonDocument::fromVariant(response).toJson());
reply->finished();
return;
}
qCDebug(dcRest) << "Pairing device finished successfully";
// Add device to async device addtions
m_asyncDeviceAdditions.insert(deviceId, reply);
}
} }

View File

@ -45,9 +45,6 @@ public:
private: private:
mutable QHash<ActionId, QPointer<HttpReply> > m_asyncActionExecutions; mutable QHash<ActionId, QPointer<HttpReply> > m_asyncActionExecutions;
mutable QHash<DeviceId, QPointer<HttpReply> > m_asyncDeviceAdditions;
mutable QHash<Device *, QPointer<HttpReply> > m_asyncReconfigureDevice;
mutable QHash<PairingTransactionId, QPointer<HttpReply> > m_asyncPairingRequests;
Device *m_device; Device *m_device;
@ -77,11 +74,6 @@ private:
// Put methods // Put methods
HttpReply *reconfigureDevice(Device *device, const QByteArray &payload) const; HttpReply *reconfigureDevice(Device *device, const QByteArray &payload) const;
private slots:
void actionExecuted(const ActionId &actionId, Device::DeviceError status);
void deviceSetupFinished(Device *device, Device::DeviceError status);
void deviceReconfigurationFinished(Device *device, Device::DeviceError status);
void pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceError status, const DeviceId &deviceId);
}; };
} }

View File

@ -0,0 +1,58 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "browseractioninfo.h"
BrowserActionInfo::BrowserActionInfo(Device *device, const BrowserAction &browserAction, QObject *parent):
QObject (parent),
m_device(device),
m_browserAction(browserAction)
{
connect(this, &BrowserActionInfo::finished, this, &BrowserActionInfo::deleteLater, Qt::QueuedConnection);
}
Device *BrowserActionInfo::device() const
{
return m_device;
}
BrowserAction BrowserActionInfo::browserAction() const
{
return m_browserAction;
}
bool BrowserActionInfo::isFinished() const
{
return m_finished;
}
Device::DeviceError BrowserActionInfo::status() const
{
return m_status;
}
void BrowserActionInfo::finish(Device::DeviceError status)
{
m_finished = true;
m_status = status;
staticMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -0,0 +1,57 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 BROWSERACTIONINFO_H
#define BROWSERACTIONINFO_H
#include <QObject>
#include "device.h"
#include "types/browseraction.h"
class BrowserActionInfo : public QObject
{
Q_OBJECT
public:
explicit BrowserActionInfo(Device* device, const BrowserAction &browserAction, QObject *parent = nullptr);
Device* device() const;
BrowserAction browserAction() const;
bool isFinished() const;
Device::DeviceError status() const;
signals:
void finished();
public slots:
void finish(Device::DeviceError status);
private:
Device *m_device = nullptr;
BrowserAction m_browserAction;
bool m_finished = false;
Device::DeviceError m_status = Device::DeviceErrorNoError;
};
#endif // BROWSERACTIONINFO_H

View File

@ -0,0 +1,79 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "browseresult.h"
BrowseResult::BrowseResult(Device *device, const QString &itemId, const QLocale &locale, QObject *parent):
QObject(parent),
m_device(device),
m_itemId(itemId),
m_locale(locale)
{
connect(this, &BrowseResult::finished, this, &BrowseResult::deleteLater, Qt::QueuedConnection);
}
Device *BrowseResult::device() const
{
return m_device;
}
QString BrowseResult::itemId() const
{
return m_itemId;
}
QLocale BrowseResult::locale() const
{
return m_locale;
}
BrowserItems BrowseResult::items() const
{
return m_items;
}
bool BrowseResult::isFinished() const
{
return m_finished;
}
Device::DeviceError BrowseResult::status() const
{
return m_status;
}
void BrowseResult::addItem(const BrowserItem &item)
{
m_items.append(item);
}
void BrowseResult::addItems(const BrowserItems &items)
{
m_items.append(items);
}
void BrowseResult::finish(Device::DeviceError status)
{
m_finished = true;
m_status = status;
staticMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -0,0 +1,65 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 BROWSERESULT_H
#define BROWSERESULT_H
#include <QObject>
#include "device.h"
class BrowseResult : public QObject
{
Q_OBJECT
public:
explicit BrowseResult(Device *device, const QString &itemId, const QLocale &locale, QObject *parent = nullptr);
Device* device() const;
QString itemId() const;
QLocale locale() const;
BrowserItems items() const;
bool isFinished() const;
Device::DeviceError status() const;
public slots:
void addItem(const BrowserItem &item);
void addItems(const BrowserItems &items);
void finish(Device::DeviceError status);
signals:
void finished();
private:
Device *m_device = nullptr;
QString m_itemId;
QLocale m_locale;
BrowserItems m_items;
bool m_finished = false;
Device::DeviceError m_status = Device::DeviceErrorNoError;
};
#endif // BROWSERESULT_H

View File

@ -0,0 +1,58 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "browseritemactioninfo.h"
BrowserItemActionInfo::BrowserItemActionInfo(Device *device, const BrowserItemAction &browserItemAction, QObject *parent):
QObject(parent),
m_device(device),
m_browserItemAction(browserItemAction)
{
connect(this, &BrowserItemActionInfo::finished, this, &BrowserItemActionInfo::deleteLater, Qt::QueuedConnection);
}
Device *BrowserItemActionInfo::device() const
{
return m_device;
}
BrowserItemAction BrowserItemActionInfo::browserItemAction() const
{
return m_browserItemAction;
}
bool BrowserItemActionInfo::isFinished() const
{
return m_finished;
}
Device::DeviceError BrowserItemActionInfo::status() const
{
return m_status;
}
void BrowserItemActionInfo::finish(Device::DeviceError status)
{
m_finished = true;
m_status = status;
staticMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -0,0 +1,58 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 BROWSERITEMACTIONINFO_H
#define BROWSERITEMACTIONINFO_H
#include <QObject>
#include "device.h"
#include "types/browseritemaction.h"
class BrowserItemActionInfo : public QObject
{
Q_OBJECT
public:
explicit BrowserItemActionInfo(Device *device, const BrowserItemAction &browserItemAction, QObject *parent = nullptr);
Device *device() const;
BrowserItemAction browserItemAction() const;
bool isFinished() const;
Device::DeviceError status() const;
signals:
void finished();
public slots:
void finish(Device::DeviceError status);
private:
Device *m_device = nullptr;
BrowserItemAction m_browserItemAction;
bool m_finished = false;
Device::DeviceError m_status = Device::DeviceErrorNoError;
};
#endif // BROWSERITEMACTIONINFO_H

View File

@ -0,0 +1,75 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "browseritemresult.h"
BrowserItemResult::BrowserItemResult(Device *device, const QString &itemId, const QLocale &locale, QObject *parent):
QObject(parent),
m_device(device),
m_itemId(itemId),
m_locale(locale)
{
connect(this, &BrowserItemResult::finished, this, &BrowserItemResult::deleteLater, Qt::QueuedConnection);
}
Device *BrowserItemResult::device() const
{
return m_device;
}
QString BrowserItemResult::itemId() const
{
return m_itemId;
}
QLocale BrowserItemResult::locale() const
{
return m_locale;
}
BrowserItem BrowserItemResult::item() const
{
return m_item;
}
bool BrowserItemResult::isFinished() const
{
return m_finished;
}
Device::DeviceError BrowserItemResult::status() const
{
return m_status;
}
void BrowserItemResult::finish(const BrowserItem &item)
{
m_item = item;
finish(Device::DeviceErrorNoError);
}
void BrowserItemResult::finish(Device::DeviceError status)
{
m_finished = true;
m_status = status;
staticMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -0,0 +1,64 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 BROWSERITEMRESULT_H
#define BROWSERITEMRESULT_H
#include <QObject>
#include "device.h"
class BrowserItemResult : public QObject
{
Q_OBJECT
public:
explicit BrowserItemResult(Device *device, const QString &itemId, const QLocale &locale, QObject *parent = nullptr);
Device* device() const;
QString itemId() const;
QLocale locale() const;
BrowserItem item() const;
bool isFinished() const;
Device::DeviceError status() const;
public slots:
void finish(const BrowserItem &item);
void finish(Device::DeviceError status);
signals:
void finished();
private:
Device *m_device = nullptr;
QString m_itemId;
QLocale m_locale;
BrowserItem m_item;
bool m_finished = false;
Device::DeviceError m_status = Device::DeviceErrorNoError;
};
#endif // BROWSERITEMRESULT_H

View File

@ -371,7 +371,7 @@ bool Device::autoCreated() const
return m_autoCreated; return m_autoCreated;
} }
void Device::setSetupComplete(const bool &complete) void Device::setSetupComplete(bool complete)
{ {
m_setupComplete = complete; m_setupComplete = complete;
} }

View File

@ -64,8 +64,7 @@ public:
DeviceErrorSetupMethodNotSupported, DeviceErrorSetupMethodNotSupported,
DeviceErrorHardwareNotAvailable, DeviceErrorHardwareNotAvailable,
DeviceErrorHardwareFailure, DeviceErrorHardwareFailure,
DeviceErrorAuthentificationFailure, DeviceErrorAuthenticationFailure,
DeviceErrorAsync,
DeviceErrorDeviceInUse, DeviceErrorDeviceInUse,
DeviceErrorDeviceInRule, DeviceErrorDeviceInRule,
DeviceErrorDeviceIsChild, DeviceErrorDeviceIsChild,
@ -77,33 +76,6 @@ public:
}; };
Q_ENUM(DeviceError) Q_ENUM(DeviceError)
enum DeviceSetupStatus {
DeviceSetupStatusSuccess,
DeviceSetupStatusFailure,
DeviceSetupStatusAsync
};
Q_ENUM(DeviceSetupStatus)
class BrowseResult {
public:
BrowseResult(): m_id(QUuid::createUuid()) {}
Device::DeviceError status = Device::DeviceErrorNoError;
BrowserItems items;
QUuid id() const { return m_id; }
private:
QUuid m_id;
};
class BrowserItemResult {
public:
BrowserItemResult(): m_id(QUuid::createUuid()) {}
Device::DeviceError status = Device::DeviceErrorNoError;
BrowserItem item;
QUuid id() const { return m_id; }
private:
QUuid m_id;
};
DeviceId id() const; DeviceId id() const;
DeviceClassId deviceClassId() const; DeviceClassId deviceClassId() const;
PluginId pluginId() const; PluginId pluginId() const;
@ -153,7 +125,7 @@ private:
Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *parent = nullptr); Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *parent = nullptr);
void setupCompleted(); void setupCompleted();
void setSetupComplete(const bool &complete); void setSetupComplete(bool complete);
private: private:
DeviceClass m_deviceClass; DeviceClass m_deviceClass;
@ -184,6 +156,5 @@ public:
}; };
Q_DECLARE_METATYPE(Device::DeviceError) Q_DECLARE_METATYPE(Device::DeviceError)
Q_DECLARE_METATYPE(Device::DeviceSetupStatus)
#endif #endif

View File

@ -0,0 +1,75 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "deviceactioninfo.h"
#include "devicemanager.h"
DeviceActionInfo::DeviceActionInfo(Device *device, const Action &action, DeviceManager *parent):
QObject(parent),
m_device(device),
m_action(action),
m_deviceManager(parent)
{
connect(this, &DeviceActionInfo::finished, this, &DeviceActionInfo::deleteLater, Qt::QueuedConnection);
}
Device *DeviceActionInfo::device() const
{
return m_device;
}
Action DeviceActionInfo::action() const
{
return m_action;
}
bool DeviceActionInfo::isFinished() const
{
return m_finished;
}
Device::DeviceError DeviceActionInfo::status() const
{
return m_status;
}
QString DeviceActionInfo::displayMessage() const
{
return m_displayMessage;
}
QString DeviceActionInfo::translatedDisplayMessage(const QLocale &locale)
{
if (!m_deviceManager) {
return m_displayMessage;
}
return m_deviceManager->translate(m_device->pluginId(), m_displayMessage.toUtf8(), locale);
}
void DeviceActionInfo::finish(Device::DeviceError status, const QString &displayMessage)
{
m_finished = true;
m_status = status;
m_displayMessage = displayMessage;
staticQtMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -0,0 +1,67 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 DEVICEACTIONINFO_H
#define DEVICEACTIONINFO_H
#include <QObject>
#include "device.h"
#include "typeutils.h"
#include "types/action.h"
class DeviceManager;
class DeviceActionInfo : public QObject
{
Q_OBJECT
public:
explicit DeviceActionInfo(Device *device, const Action &action, DeviceManager *parent);
Device* device() const;
Action action() const;
bool isFinished() const;
Device::DeviceError status() const;
QString displayMessage() const;
QString translatedDisplayMessage(const QLocale &locale);
signals:
void finished();
public slots:
void finish(Device::DeviceError status, const QString &displayMessage = QString());
private:
Device *m_device = nullptr;
Action m_action;
bool m_finished = false;
Device::DeviceError m_status = Device::DeviceErrorNoError;
QString m_displayMessage;
DeviceManager *m_deviceManager = nullptr;
};
#endif // DEVICEACTIONINFO_H

View File

@ -67,6 +67,15 @@ private:
ParamList m_params; ParamList m_params;
}; };
class DeviceDescriptors: public QList<DeviceDescriptor>
{
public:
DeviceDescriptors() {}
inline DeviceDescriptors(std::initializer_list<DeviceDescriptor> args): QList(args) {}
DeviceDescriptors(const QList<DeviceDescriptor> &other): QList<DeviceDescriptor>(other) {}
};
Q_DECLARE_METATYPE(DeviceDescriptor) Q_DECLARE_METATYPE(DeviceDescriptor)
Q_DECLARE_METATYPE(DeviceDescriptors)
#endif // DEVICEDESCRIPTION_H #endif // DEVICEDESCRIPTION_H

View File

@ -0,0 +1,90 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "devicediscoveryinfo.h"
#include "devicemanager.h"
DeviceDiscoveryInfo::DeviceDiscoveryInfo(const DeviceClassId &deviceClassId, const ParamList &params, DeviceManager *deviceManager):
QObject(deviceManager),
m_deviceClassId(deviceClassId),
m_params(params),
m_deviceManager(deviceManager)
{
connect(this, &DeviceDiscoveryInfo::finished, this, &DeviceDiscoveryInfo::deleteLater, Qt::QueuedConnection);
}
DeviceClassId DeviceDiscoveryInfo::deviceClassId() const
{
return m_deviceClassId;
}
ParamList DeviceDiscoveryInfo::params() const
{
return m_params;
}
bool DeviceDiscoveryInfo::isFinished() const
{
return m_finished;
}
Device::DeviceError DeviceDiscoveryInfo::status() const
{
return m_status;
}
void DeviceDiscoveryInfo::addDeviceDescriptor(const DeviceDescriptor &deviceDescriptor)
{
m_deviceDescriptors.append(deviceDescriptor);
}
void DeviceDiscoveryInfo::addDeviceDescriptors(const DeviceDescriptors &deviceDescriptors)
{
m_deviceDescriptors.append(deviceDescriptors);
}
DeviceDescriptors DeviceDiscoveryInfo::deviceDescriptors() const
{
return m_deviceDescriptors;
}
QString DeviceDiscoveryInfo::displayMessage() const
{
return m_displayMessage;
}
QString DeviceDiscoveryInfo::translatedDisplayMessage(const QLocale &locale)
{
if (!m_deviceManager) {
return m_displayMessage;
}
DeviceClass deviceClass = m_deviceManager->findDeviceClass(m_deviceClassId);
return m_deviceManager->translate(deviceClass.pluginId(), m_displayMessage.toUtf8(), locale);
}
void DeviceDiscoveryInfo::finish(Device::DeviceError status, const QString &displayMessage)
{
m_finished = true;
m_status = status;
m_displayMessage = displayMessage;
staticMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -0,0 +1,74 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 DEVICEDISCOVERYINFO_H
#define DEVICEDISCOVERYINFO_H
#include <QObject>
#include "types/deviceclass.h"
#include "types/param.h"
#include "device.h"
#include "devicedescriptor.h"
class DeviceManager;
class LIBNYMEA_EXPORT DeviceDiscoveryInfo : public QObject
{
Q_OBJECT
public:
explicit DeviceDiscoveryInfo(const DeviceClassId &deviceClassId, const ParamList &params, DeviceManager *deviceManager);
DeviceClassId deviceClassId() const;
ParamList params() const;
bool isFinished() const;
Device::DeviceError status() const;
void addDeviceDescriptor(const DeviceDescriptor &deviceDescriptor);
void addDeviceDescriptors(const DeviceDescriptors &deviceDescriptors);
DeviceDescriptors deviceDescriptors() const;
QString displayMessage() const;
QString translatedDisplayMessage(const QLocale &locale);
public slots:
void finish(Device::DeviceError status, const QString &displayMessage = QString());
signals:
void finished();
private:
DeviceClassId m_deviceClassId;
ParamList m_params;
bool m_finished = false;
Device::DeviceError m_status;
QString m_displayMessage;
DeviceDescriptors m_deviceDescriptors;
DeviceManager *m_deviceManager = nullptr;
};
#endif // DEVICEDISCOVERYINFO_H

View File

@ -41,6 +41,7 @@ public:
virtual ~DeviceManager() = default; virtual ~DeviceManager() = default;
virtual DevicePlugins plugins() const = 0; virtual DevicePlugins plugins() const = 0;
virtual DevicePlugin* plugin(const PluginId &pluginId) const = 0;
virtual Device::DeviceError setPluginConfig(const PluginId &pluginId, const ParamList &pluginConfig) = 0; virtual Device::DeviceError setPluginConfig(const PluginId &pluginId, const ParamList &pluginConfig) = 0;
virtual Vendors supportedVendors() const = 0; virtual Vendors supportedVendors() const = 0;
@ -55,29 +56,29 @@ public:
virtual Devices findConfiguredDevices(const QString &interface) const = 0; virtual Devices findConfiguredDevices(const QString &interface) const = 0;
virtual Devices findChildDevices(const DeviceId &id) const = 0; virtual Devices findChildDevices(const DeviceId &id) const = 0;
virtual Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) = 0; virtual DeviceDiscoveryInfo* discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) = 0;
virtual Device::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id = DeviceId::createDeviceId()) = 0; virtual DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id = DeviceId::createDeviceId()) = 0;
virtual Device::DeviceError addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const DeviceId &deviceId = DeviceId::createDeviceId()) = 0; virtual DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const DeviceId &deviceId = DeviceId::createDeviceId()) = 0;
virtual Device::DeviceError reconfigureDevice(const DeviceId &deviceId, const ParamList &params, bool fromDiscoveryOrAuto = false) = 0; virtual DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const ParamList &params, bool fromDiscoveryOrAuto = false) = 0;
virtual Device::DeviceError reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId) = 0; virtual DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId) = 0;
virtual Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) = 0; virtual Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) = 0;
virtual Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) = 0; virtual Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) = 0;
virtual Device::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const QString &name, const ParamList &params) = 0; virtual DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params) = 0;
virtual Device::DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId) = 0; virtual DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId) = 0;
virtual Device::DeviceError confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &secret = QString()) = 0; virtual DevicePairingInfo* confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &username = QString(), const QString &secret = QString()) = 0;
virtual Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) = 0; virtual Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) = 0;
virtual Device::DeviceError executeAction(const Action &action) = 0; virtual DeviceActionInfo* executeAction(const Action &action) = 0;
virtual Device::BrowseResult browseDevice(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) = 0; virtual BrowseResult* browseDevice(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) = 0;
virtual Device::BrowserItemResult browserItemDetails(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) = 0; virtual BrowserItemResult* browserItemDetails(const DeviceId &deviceId, const QString &itemId, const QLocale &locale) = 0;
virtual Device::DeviceError executeBrowserItem(const BrowserAction &browserAction) = 0; virtual BrowserActionInfo* executeBrowserItem(const BrowserAction &browserAction) = 0;
virtual Device::DeviceError executeBrowserItemAction(const BrowserItemAction &browserItemAction) = 0; virtual BrowserItemActionInfo* executeBrowserItemAction(const BrowserItemAction &browserItemAction) = 0;
virtual QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0; virtual QString translate(const PluginId &pluginId, const QString &string, const QLocale &locale) = 0;
@ -90,16 +91,6 @@ signals:
void deviceAdded(Device *device); void deviceAdded(Device *device);
void deviceChanged(Device *device); void deviceChanged(Device *device);
void deviceSettingChanged(const DeviceId deviceId, const ParamTypeId &settingParamTypeId, const QVariant &value); void deviceSettingChanged(const DeviceId deviceId, const ParamTypeId &settingParamTypeId, const QVariant &value);
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &devices);
void deviceSetupFinished(Device *device, Device::DeviceError status);
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);
void browserItemRequestFinished(const Device::BrowserItemResult &result);
void browserItemExecutionFinished(const ActionId &actionId, Device::DeviceError status);
void browserItemActionExecutionFinished(const ActionId &actionId, Device::DeviceError status);
}; };
#endif // DEVICEMANAGER_H #endif // DEVICEMANAGER_H

View File

@ -21,26 +21,23 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "devicepairinginfo.h" #include "devicepairinginfo.h"
#include "devicemanager.h"
DevicePairingInfo::DevicePairingInfo() DevicePairingInfo::DevicePairingInfo(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const DeviceId &deviceId, const QString &deviceName, const ParamList &params, const DeviceId &parentDeviceId, DeviceManager *parent):
QObject(parent),
m_transactionId(pairingTransactionId),
m_deviceClassId(deviceClassId),
m_deviceId(deviceId),
m_deviceName(deviceName),
m_params(params),
m_parentDeviceId(parentDeviceId)
{ {
connect(this, &DevicePairingInfo::finished, this, &DevicePairingInfo::deleteLater, Qt::QueuedConnection);
} }
DevicePairingInfo::DevicePairingInfo(const DeviceClassId &deviceClassId, const QString &deviceName, const ParamList &params) : PairingTransactionId DevicePairingInfo::transactionId() const
m_deviceClassId(deviceClassId),
m_deviceName(deviceName),
m_params(params)
{ {
return m_transactionId;
}
DevicePairingInfo::DevicePairingInfo(const DeviceClassId &deviceClassId, const QString &deviceName, const DeviceDescriptorId &deviceDescriptorId) :
m_deviceClassId(deviceClassId),
m_deviceName(deviceName),
m_deviceDescriptorId(deviceDescriptorId)
{
} }
DeviceClassId DevicePairingInfo::deviceClassId() const DeviceClassId DevicePairingInfo::deviceClassId() const
@ -48,6 +45,11 @@ DeviceClassId DevicePairingInfo::deviceClassId() const
return m_deviceClassId; return m_deviceClassId;
} }
DeviceId DevicePairingInfo::deviceId() const
{
return m_deviceId;
}
QString DevicePairingInfo::deviceName() const QString DevicePairingInfo::deviceName() const
{ {
return m_deviceName; return m_deviceName;
@ -58,8 +60,45 @@ ParamList DevicePairingInfo::params() const
return m_params; return m_params;
} }
DeviceDescriptorId DevicePairingInfo::deviceDescriptorId() const DeviceId DevicePairingInfo::parentDeviceId() const
{ {
return m_deviceDescriptorId; return m_parentDeviceId;
}
QUrl DevicePairingInfo::oAuthUrl() const
{
return m_oAuthUrl;
}
void DevicePairingInfo::setOAuthUrl(const QUrl &oAuthUrl)
{
m_oAuthUrl = oAuthUrl;
}
Device::DeviceError DevicePairingInfo::status() const
{
return m_status;
}
QString DevicePairingInfo::displayMessage() const
{
return m_displayMessage;
}
QString DevicePairingInfo::translatedDisplayMessage(const QLocale &locale) const
{
if (!m_deviceManager) {
return m_displayMessage;
}
DeviceClass deviceClass = m_deviceManager->findDeviceClass(m_deviceClassId);
return m_deviceManager->translate(deviceClass.pluginId(), m_displayMessage.toUtf8(), locale);
}
void DevicePairingInfo::finish(Device::DeviceError status, const QString &displayMessage)
{
m_finished = true;
m_status = status;
m_displayMessage = displayMessage;
staticMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
} }

View File

@ -23,30 +23,54 @@
#ifndef DEVICEPAIRINGINFO_H #ifndef DEVICEPAIRINGINFO_H
#define DEVICEPAIRINGINFO_H #define DEVICEPAIRINGINFO_H
#include "libnymea.h" #include <QObject>
#include "typeutils.h" #include <QUrl>
#include "types/param.h"
class LIBNYMEA_EXPORT DevicePairingInfo #include "device.h"
class DeviceManager;
class LIBNYMEA_EXPORT DevicePairingInfo: public QObject
{ {
Q_OBJECT
public: public:
DevicePairingInfo(); DevicePairingInfo(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const DeviceId &deviceId, const QString &deviceName, const ParamList &params, const DeviceId &parentDeviceId, DeviceManager *parent);
DevicePairingInfo(const DeviceClassId &deviceClassId, const QString &deviceName, const ParamList &params);
DevicePairingInfo(const DeviceClassId &deviceClassId, const QString &deviceName, const DeviceDescriptorId &deviceDescriptorId); PairingTransactionId transactionId() const;
DeviceClassId deviceClassId() const; DeviceClassId deviceClassId() const;
DeviceId deviceId() const;
QString deviceName() const; QString deviceName() const;
ParamList params() const; ParamList params() const;
DeviceId parentDeviceId() const;
DeviceDescriptorId deviceDescriptorId() const; QUrl oAuthUrl() const;
void setOAuthUrl(const QUrl &oAuthUrl);
Device::DeviceError status() const;
QString displayMessage() const;
QString translatedDisplayMessage(const QLocale &locale) const;
public slots:
void finish(Device::DeviceError status, const QString &displayMessage = QString());
signals:
void finished();
private: private:
PairingTransactionId m_transactionId;
DeviceClassId m_deviceClassId; DeviceClassId m_deviceClassId;
DeviceId m_deviceId;
QString m_deviceName; QString m_deviceName;
ParamList m_params; ParamList m_params;
DeviceDescriptorId m_deviceDescriptorId; DeviceId m_parentDeviceId;
QUrl m_oAuthUrl;
bool m_finished = false;
Device::DeviceError m_status = Device::DeviceErrorNoError;
QString m_displayMessage;
DeviceManager *m_deviceManager = nullptr;
}; };
#endif // DEVICEPAIRINGINFO_H #endif // DEVICEPAIRINGINFO_H

View File

@ -89,6 +89,14 @@
#include "devicemanager.h" #include "devicemanager.h"
#include "deviceutils.h" #include "deviceutils.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "devicediscoveryinfo.h"
#include "devicesetupinfo.h"
#include "devicepairinginfo.h"
#include "deviceactioninfo.h"
#include "browseresult.h"
#include "browseritemresult.h"
#include "browseractioninfo.h"
#include "browseritemactioninfo.h"
#include "nymeasettings.h" #include "nymeasettings.h"
@ -167,11 +175,9 @@ void DevicePlugin::startMonitoringAutoDevices()
if the discovery has been started successfully. Return an appropriate error otherwise. if the discovery has been started successfully. Return an appropriate error otherwise.
Once devices are discovered, emit devicesDiscovered(). Once devices are discovered, emit devicesDiscovered().
*/ */
Device::DeviceError DevicePlugin::discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) void DevicePlugin::discoverDevices(DeviceDiscoveryInfo *info)
{ {
Q_UNUSED(deviceClassId) info->finish(Device::DeviceErrorUnsupportedFeature);
Q_UNUSED(params)
return Device::DeviceErrorCreationMethodNotSupported;
} }
/*! This will be called when a new device is created. The plugin has the chance to do some setup. /*! This will be called when a new device is created. The plugin has the chance to do some setup.
@ -181,10 +187,9 @@ Device::DeviceError DevicePlugin::discoverDevices(const DeviceClassId &deviceCla
return \l{DeviceManager}{DeviceSetupStatusAsync}. In that case the \l{DeviceManager} will wait for you to emit return \l{DeviceManager}{DeviceSetupStatusAsync}. In that case the \l{DeviceManager} will wait for you to emit
\l{DevicePlugin}{deviceSetupFinished} to report the status. \l{DevicePlugin}{deviceSetupFinished} to report the status.
*/ */
Device::DeviceSetupStatus DevicePlugin::setupDevice(Device *device) void DevicePlugin::setupDevice(DeviceSetupInfo *info)
{ {
Q_UNUSED(device) info->finish(Device::DeviceErrorUnsupportedFeature);
return Device::DeviceSetupStatusSuccess;
} }
/*! This will be called when a new \a device was added successfully and the device setup is finished.*/ /*! This will be called when a new \a device was added successfully and the device setup is finished.*/
@ -202,32 +207,55 @@ void DevicePlugin::deviceRemoved(Device *device)
Q_UNUSED(device) Q_UNUSED(device)
} }
/*! This method will be called for \l{Device}{Devices} with the \l{DeviceClass::SetupMethodDisplayPin} right after the paring request /*! This method will be called to initiate a pairing. The plugin can do a initialisation for an upcoming pairing process.
with the given \a pairingTransactionId for the given \a deviceDescriptor. Depending on the setupMethod of a device class, different actions may be required here.
SetupMethodDisplayPin should trigger the device to display a pin that will be entered in the client.
SetupMethodOAuth should generate the OAuthUrl which will be opened on the client to allow the user logging in and obtain
the OAuth code.
SetupMethodEnterPin, SetupMethodPushButton and SetupMethodUserAndPassword will typically not require to do anything here.
It is not required to reimplement this method for those setup methods, however, a Plugin reimplementing it should call
\l{DevicePairingInfo::finish}{finish()} on the \l{DevicePairingInfo} object and can provide an optional displayMessage which
might be presented to the user. Those strings need to be wrapped in QT_TR_NOOP() in order to be translatable for the client's
locale.
*/ */
Device::DeviceError DevicePlugin::displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) void DevicePlugin::startPairing(DevicePairingInfo *info)
{ {
Q_UNUSED(pairingTransactionId) DeviceClass deviceClass = m_metaData.deviceClasses().findById(info->deviceClassId());
Q_UNUSED(deviceDescriptor) if (!deviceClass.isValid()) {
info->finish(Device::DeviceErrorDeviceClassNotFound);
qCWarning(dcDeviceManager) << "Plugin does not implement the display pin setup method."; return;
}
return Device::DeviceErrorNoError; switch (deviceClass.setupMethod()) {
case DeviceClass::SetupMethodJustAdd:
info->finish(Device::DeviceErrorSetupMethodNotSupported);
return;
case DeviceClass::SetupMethodEnterPin:
case DeviceClass::SetupMethodPushButton:
case DeviceClass::SetupMethodUserAndPassword:
info->finish(Device::DeviceErrorNoError);
return;
case DeviceClass::SetupMethodDisplayPin:
case DeviceClass::SetupMethodOAuth:
// Those need to be handled by the plugin or it'll fail anyways.
qCWarning(dcDevice()) << "StartPairing called but Plugin does not reimplement it.";
info->finish(Device::DeviceErrorUnsupportedFeature);
}
} }
/*! Confirms the pairing of a \a deviceClassId with the given \a pairingTransactionId and \a params. /*! Confirms the pairing of the given \a info. \a username and \a secret are filled in depending on the setupmethod of the device class.
Returns \l{Device::DeviceError}{DeviceError} to inform about the result. The optional paramerter \a username will be used for SetupMethodUserAndPassword. \a secret will be used for SetupMethodUserAndPassword, SetupMethodDisplayPin
\a secret contains for example the pin for \l{Device}{Devices} with the setup method \l{DeviceClass::SetupMethodDisplayPin}. and SetupMethodOAuth.
Once the pairing is completed, the plugin implementation should call the info's finish() method reporting about the status of
the pairing operation. The optional displayMessage needs to be wrapped in QT_TR_NOOP in order to be translatable to the client's
locale.
*/ */
Device::DeviceSetupStatus DevicePlugin::confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret = QString()) void DevicePlugin::confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret)
{ {
Q_UNUSED(pairingTransactionId) Q_UNUSED(username)
Q_UNUSED(deviceClassId)
Q_UNUSED(params)
Q_UNUSED(secret) Q_UNUSED(secret)
qCWarning(dcDeviceManager) << "Plugin does not implement pairing."; qCWarning(dcDeviceManager) << "Plugin does not implement pairing.";
return Device::DeviceSetupStatusFailure; info->finish(Device::DeviceErrorUnsupportedFeature);
} }
/*! This will be called to actually execute actions on the hardware. The \{Device} and /*! This will be called to actually execute actions on the hardware. The \{Device} and
@ -241,11 +269,9 @@ Device::DeviceSetupStatus DevicePlugin::confirmPairing(const PairingTransactionI
\sa actionExecutionFinished() \sa actionExecutionFinished()
*/ */
Device::DeviceError DevicePlugin::executeAction(Device *device, const Action &action) void DevicePlugin::executeAction(DeviceActionInfo *info)
{ {
Q_UNUSED(device) info->finish(Device::DeviceErrorUnsupportedFeature);
Q_UNUSED(action)
return Device::DeviceErrorNoError;
} }
/*! Implement this if your devices support browsing (set "browsable" to true in the metadata). /*! Implement this if your devices support browsing (set "browsable" to true in the metadata).
@ -260,14 +286,10 @@ Device::DeviceError DevicePlugin::executeAction(Device *device, const Action &ac
* status to Device::DeviceErrorAsync if this operation requires async behavior and emit * status to Device::DeviceErrorAsync if this operation requires async behavior and emit
* \l{browseRequestFinished} when done. * \l{browseRequestFinished} when done.
*/ */
Device::BrowseResult DevicePlugin::browseDevice(Device *device, Device::BrowseResult result, const QString &itemId, const QLocale &locale) void DevicePlugin::browseDevice(BrowseResult *result)
{ {
Q_UNUSED(device) qCWarning(dcDevice()) << "Device claims" << result->device()->deviceClass().name() << "to be browsable but plugin does not reimplement browseDevice!";
Q_UNUSED(itemId) result->finish(Device::DeviceErrorUnsupportedFeature);
Q_UNUSED(locale)
result.status = Device::DeviceErrorUnsupportedFeature;
return result;
} }
/*! Implement this if your devices support browsing (set "browsable" to true in the metadata). /*! Implement this if your devices support browsing (set "browsable" to true in the metadata).
@ -277,25 +299,20 @@ Device::BrowseResult DevicePlugin::browseDevice(Device *device, Device::BrowseRe
* status to Device::DeviceErrorAsync if this operation requires async behavior and emit * status to Device::DeviceErrorAsync if this operation requires async behavior and emit
* \l{browserItemRequestFinished} when done. * \l{browserItemRequestFinished} when done.
*/ */
Device::BrowserItemResult DevicePlugin::browserItem(Device *device, Device::BrowserItemResult result, const QString &itemId, const QLocale &locale) void DevicePlugin::browserItem(BrowserItemResult *result)
{ {
Q_UNUSED(device) qCWarning(dcDevice()) << "Device claims" << result->device()->deviceClass().name() << "to be browsable but plugin does not reimplement browserItem!";
Q_UNUSED(itemId) result->finish(Device::DeviceErrorUnsupportedFeature);
Q_UNUSED(locale)
result.status = Device::DeviceErrorUnsupportedFeature;
return result;
} }
/*! Implement this if your devices support browsing and execute the itemId defined in \a browserAction. /*! 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 * Return Device::DeviceErrorAsync if this operation requires async behavior and emit
* \l{browserItemExecutionFinished} when done. * \l{browserItemExecutionFinished} when done.
*/ */
Device::DeviceError DevicePlugin::executeBrowserItem(Device *device, const BrowserAction &browserAction) void DevicePlugin::executeBrowserItem(BrowserActionInfo *info)
{ {
Q_UNUSED(device) qCWarning(dcDevice()) << "Device claims" << info->device()->deviceClass().name() << "to be browsable but plugin does not reimplement browserItem!";
Q_UNUSED(browserAction) info->finish(Device::DeviceErrorUnsupportedFeature);
return Device::DeviceErrorUnsupportedFeature;
} }
/*! Implement this if your devices support browsing and execute the item's action for the itemId defined /*! Implement this if your devices support browsing and execute the item's action for the itemId defined
@ -303,11 +320,10 @@ Device::DeviceError DevicePlugin::executeBrowserItem(Device *device, const Brows
* Return Device::DeviceErrorAsync if this operation requires async behavior and emit * Return Device::DeviceErrorAsync if this operation requires async behavior and emit
* \l{browserItemActionExecutionFinished} when done. * \l{browserItemActionExecutionFinished} when done.
*/ */
Device::DeviceError DevicePlugin::executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction) void DevicePlugin::executeBrowserItemAction(BrowserItemActionInfo *info)
{ {
Q_UNUSED(device) qCWarning(dcDevice()) << "Device claims" << info->device()->deviceClass().name() << "to be browsable but plugin does not reimplement browserItemAction!";
Q_UNUSED(browserItemAction) info->finish(Device::DeviceErrorUnsupportedFeature);
return Device::DeviceErrorUnsupportedFeature;
} }
/*! Returns the configuration description of this DevicePlugin as a list of \l{ParamType}{ParamTypes}. */ /*! Returns the configuration description of this DevicePlugin as a list of \l{ParamType}{ParamTypes}. */

View File

@ -42,11 +42,19 @@
#include "hardwaremanager.h" #include "hardwaremanager.h"
#include "devicediscoveryinfo.h"
#include "devicepairinginfo.h"
#include "devicesetupinfo.h"
#include "deviceactioninfo.h"
#include "browseresult.h"
#include "browseritemresult.h"
#include "browseractioninfo.h"
#include "browseritemactioninfo.h"
#include <QObject> #include <QObject>
#include <QTranslator> #include <QTranslator>
#include <QPair> #include <QPair>
class Device;
class DeviceManager; class DeviceManager;
class LIBNYMEA_EXPORT DevicePlugin: public QObject class LIBNYMEA_EXPORT DevicePlugin: public QObject
@ -69,21 +77,21 @@ public:
DeviceClasses supportedDevices() const; DeviceClasses supportedDevices() const;
virtual void startMonitoringAutoDevices(); virtual void startMonitoringAutoDevices();
virtual Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params); virtual void discoverDevices(DeviceDiscoveryInfo *info);
virtual Device::DeviceSetupStatus setupDevice(Device *device); virtual void setupDevice(DeviceSetupInfo *info);
virtual void postSetupDevice(Device *device); virtual void postSetupDevice(Device *device);
virtual void deviceRemoved(Device *device); virtual void deviceRemoved(Device *device);
virtual Device::DeviceError displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor); virtual void startPairing(DevicePairingInfo *info);
virtual Device::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret); virtual void confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret);
virtual Device::DeviceError executeAction(Device *device, const Action &action); virtual void executeAction(DeviceActionInfo *info);
virtual Device::BrowseResult browseDevice(Device *device, Device::BrowseResult result, const QString &itemId, const QLocale &locale); virtual void browseDevice(BrowseResult *result);
virtual Device::BrowserItemResult browserItem(Device *device, Device::BrowserItemResult result, const QString &itemId, const QLocale &locale); virtual void browserItem(BrowserItemResult *result);
virtual Device::DeviceError executeBrowserItem(Device *device, const BrowserAction &browserAction); virtual void executeBrowserItem(BrowserActionInfo *info);
virtual Device::DeviceError executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction); virtual void executeBrowserItemAction(BrowserItemActionInfo *info);
// Configuration // Configuration
ParamTypes configurationDescription() const; ParamTypes configurationDescription() const;
@ -96,17 +104,9 @@ public:
signals: signals:
void emitEvent(const Event &event); void emitEvent(const Event &event);
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
void deviceSetupFinished(Device *device, Device::DeviceSetupStatus status);
void pairingFinished(const PairingTransactionId &pairingTransactionId, Device::DeviceSetupStatus status);
void actionExecutionFinished(const ActionId &id, Device::DeviceError status);
void configValueChanged(const ParamTypeId &paramTypeId, const QVariant &value); void configValueChanged(const ParamTypeId &paramTypeId, const QVariant &value);
void autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors); void autoDevicesAppeared(const DeviceDescriptors &deviceDescriptors);
void autoDeviceDisappeared(const DeviceId &deviceId); void autoDeviceDisappeared(const DeviceId &deviceId);
void browseRequestFinished(const Device::BrowseResult &result);
void browserItemRequestFinished(const Device::BrowserItemResult &result);
void browserItemExecutionFinished(const ActionId &actionid, Device::DeviceError status);
void browserItemActionExecutionFinished(const ActionId &actionid, Device::DeviceError status);
protected: protected:
Devices myDevices() const; Devices myDevices() const;

View File

@ -0,0 +1,71 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 "devicesetupinfo.h"
#include "deviceplugin.h"
#include "devicemanager.h"
DeviceSetupInfo::DeviceSetupInfo(Device *device, DeviceManager *deviceManager):
QObject(deviceManager),
m_device(device),
m_deviecManager(deviceManager)
{
connect(this, &DeviceSetupInfo::finished, this, &DeviceSetupInfo::deleteLater, Qt::QueuedConnection);
}
Device *DeviceSetupInfo::device() const
{
return m_device;
}
bool DeviceSetupInfo::isFinished() const
{
return m_finished;
}
Device::DeviceError DeviceSetupInfo::status() const
{
return m_status;
}
QString DeviceSetupInfo::displayMessage() const
{
return m_displayMessage;
}
QString DeviceSetupInfo::translatedDisplayMessage(const QLocale &locale)
{
if (!m_deviecManager || !m_device) {
return m_displayMessage;
}
return m_deviecManager->translate(m_device->pluginId(), m_displayMessage.toUtf8(), locale);
}
void DeviceSetupInfo::finish(Device::DeviceError status, const QString &displayMessage)
{
m_finished = true;
m_status = status;
m_displayMessage = displayMessage;
staticMetaObject.invokeMethod(this, "finished", Qt::QueuedConnection);
}

View File

@ -0,0 +1,62 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* 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 DEVICESETUPINFO_H
#define DEVICESETUPINFO_H
#include "device.h"
#include <QObject>
class DeviceManager;
class LIBNYMEA_EXPORT DeviceSetupInfo : public QObject
{
Q_OBJECT
public:
explicit DeviceSetupInfo(Device *device, DeviceManager *deviceManager);
Device *device() const;
bool isFinished() const;
Device::DeviceError status() const;
QString displayMessage() const;
QString translatedDisplayMessage(const QLocale &locale);
public slots:
void finish(Device::DeviceError status, const QString &displayMessage = QString());
signals:
void finished();
private:
Device *m_device = nullptr;
bool m_finished = false;
Device::DeviceError m_status = Device::DeviceErrorNoError;
QString m_displayMessage;
DeviceManager *m_deviecManager = nullptr;
};
#endif // DEVICESETUPINFO_H

View File

@ -162,7 +162,7 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
QJsonObject deviceClassObject = deviceClassJson.toObject(); QJsonObject deviceClassObject = deviceClassJson.toObject();
/*! Returns a list of all valid JSON properties a DeviceClass JSON definition can have. */ /*! Returns a list of all valid JSON properties a DeviceClass JSON definition can have. */
QStringList deviceClassProperties = QStringList() << "id" << "name" << "displayName" << "createMethods" << "setupMethod" QStringList deviceClassProperties = QStringList() << "id" << "name" << "displayName" << "createMethods" << "setupMethod"
<< "interfaces" << "browsable" << "pairingInfo" << "discoveryParamTypes" << "discoveryParamTypes" << "interfaces" << "browsable" << "discoveryParamTypes" << "discoveryParamTypes"
<< "paramTypes" << "settingsTypes" << "stateTypes" << "actionTypes" << "eventTypes" << "browserItemActionTypes"; << "paramTypes" << "settingsTypes" << "stateTypes" << "actionTypes" << "eventTypes" << "browserItemActionTypes";
QStringList mandatoryDeviceClassProperties = QStringList() << "id" << "name" << "displayName"; QStringList mandatoryDeviceClassProperties = QStringList() << "id" << "name" << "displayName";
@ -251,6 +251,10 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
setupMethod = DeviceClass::SetupMethodEnterPin; setupMethod = DeviceClass::SetupMethodEnterPin;
} else if (setupMethodString.toLower() == "justadd") { } else if (setupMethodString.toLower() == "justadd") {
setupMethod = DeviceClass::SetupMethodJustAdd; setupMethod = DeviceClass::SetupMethodJustAdd;
} else if (setupMethodString.toLower() == "userandpassword") {
setupMethod = DeviceClass::SetupMethodUserAndPassword;
} else if (setupMethodString.toLower() == "oauth") {
setupMethod = DeviceClass::SetupMethodOAuth;
} else { } else {
qCWarning(dcPluginMetadata()) << "Unknown setupMethod" << setupMethod << "in deviceClass" << deviceClass.name() << "."; qCWarning(dcPluginMetadata()) << "Unknown setupMethod" << setupMethod << "in deviceClass" << deviceClass.name() << ".";
hasError = true; hasError = true;
@ -258,9 +262,6 @@ void PluginMetadata::parse(const QJsonObject &jsonObject)
} }
deviceClass.setSetupMethod(setupMethod); deviceClass.setSetupMethod(setupMethod);
// Read pairing info
deviceClass.setPairingInfo(deviceClassObject.value("pairingInfo").toString());
ActionTypes actionTypes; ActionTypes actionTypes;
StateTypes stateTypes; StateTypes stateTypes;
EventTypes eventTypes; EventTypes eventTypes;

View File

@ -10,9 +10,20 @@ DEFINES += LIBNYMEA_LIBRARY
QMAKE_LFLAGS += -fPIC QMAKE_LFLAGS += -fPIC
HEADERS += \ HEADERS += \
devices/browseractioninfo.h \
devices/browseritemactioninfo.h \
devices/browseritemresult.h \
devices/devicemanager.h \ devices/devicemanager.h \
devices/deviceutils.h \ devices/deviceutils.h \
devices/pluginmetadata.h \ devices/pluginmetadata.h \
devices/device.h \
devices/deviceplugin.h \
devices/devicedescriptor.h \
devices/devicediscoveryinfo.h \
devices/devicesetupinfo.h \
devices/devicepairinginfo.h \
devices/deviceactioninfo.h \
devices/browseresult.h \
libnymea.h \ libnymea.h \
platform/package.h \ platform/package.h \
platform/repository.h \ platform/repository.h \
@ -23,10 +34,6 @@ HEADERS += \
typeutils.h \ typeutils.h \
loggingcategories.h \ loggingcategories.h \
nymeasettings.h \ nymeasettings.h \
devices/device.h \
devices/deviceplugin.h \
devices/devicedescriptor.h \
devices/devicepairinginfo.h \
hardware/gpio.h \ hardware/gpio.h \
hardware/gpiomonitor.h \ hardware/gpiomonitor.h \
hardware/pwm.h \ hardware/pwm.h \
@ -77,17 +84,24 @@ HEADERS += \
platform/platformzeroconfcontroller.h \ platform/platformzeroconfcontroller.h \
SOURCES += \ SOURCES += \
devices/browseractioninfo.cpp \
devices/browseritemactioninfo.cpp \
devices/browseritemresult.cpp \
devices/devicemanager.cpp \ devices/devicemanager.cpp \
devices/deviceutils.cpp \ devices/deviceutils.cpp \
devices/pluginmetadata.cpp \ devices/pluginmetadata.cpp \
devices/device.cpp \
devices/deviceplugin.cpp \
devices/devicedescriptor.cpp \
devices/devicediscoveryinfo.cpp \
devices/devicesetupinfo.cpp \
devices/devicepairinginfo.cpp \
devices/deviceactioninfo.cpp \
devices/browseresult.cpp \
loggingcategories.cpp \ loggingcategories.cpp \
nymeasettings.cpp \ nymeasettings.cpp \
platform/package.cpp \ platform/package.cpp \
platform/repository.cpp \ platform/repository.cpp \
devices/device.cpp \
devices/deviceplugin.cpp \
devices/devicedescriptor.cpp \
devices/devicepairinginfo.cpp \
hardware/gpio.cpp \ hardware/gpio.cpp \
hardware/gpiomonitor.cpp \ hardware/gpiomonitor.cpp \
hardware/pwm.cpp \ hardware/pwm.cpp \

View File

@ -52,7 +52,9 @@ public:
SetupMethodJustAdd, SetupMethodJustAdd,
SetupMethodDisplayPin, SetupMethodDisplayPin,
SetupMethodEnterPin, SetupMethodEnterPin,
SetupMethodPushButton SetupMethodPushButton,
SetupMethodUserAndPassword,
SetupMethodOAuth
}; };
Q_ENUM(SetupMethod) Q_ENUM(SetupMethod)

File diff suppressed because it is too large Load Diff

View File

@ -39,42 +39,37 @@ class DevicePluginMock : public DevicePlugin
public: public:
explicit DevicePluginMock(); explicit DevicePluginMock();
~DevicePluginMock(); ~DevicePluginMock() override;
Device::DeviceError discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; void discoverDevices(DeviceDiscoveryInfo *info) override;
Device::DeviceSetupStatus setupDevice(Device *device) override; void setupDevice(DeviceSetupInfo *info) override;
void postSetupDevice(Device *device) override; void postSetupDevice(Device *device) override;
void deviceRemoved(Device *device) override; void deviceRemoved(Device *device) override;
void startMonitoringAutoDevices() override; void startMonitoringAutoDevices() override;
Device::DeviceSetupStatus confirmPairing(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const ParamList &params, const QString &secret) override; void startPairing(DevicePairingInfo *info) override;
Device::DeviceError displayPin(const PairingTransactionId &pairingTransactionId, const DeviceDescriptor &deviceDescriptor) override; void confirmPairing(DevicePairingInfo *info, const QString &username, const QString &secret) override;
Device::BrowseResult browseDevice(Device *device, Device::BrowseResult result, const QString &itemId, const QLocale &locale) override; void browseDevice(BrowseResult *result) override;
Device::BrowserItemResult browserItem(Device *device, Device::BrowserItemResult result, const QString &itemId, const QLocale &locale) override; void browserItem(BrowserItemResult *result) override;
public slots: public slots:
Device::DeviceError executeAction(Device *device, const Action &action) override; void executeAction(DeviceActionInfo *info) override;
Device::DeviceError executeBrowserItem(Device *device, const BrowserAction &browserAction) override; void executeBrowserItem(BrowserActionInfo *info) override;
Device::DeviceError executeBrowserItemAction(Device *device, const BrowserItemAction &browserItemAction) override; void executeBrowserItemAction(BrowserItemActionInfo *info) override;
private slots: private slots:
void setState(const StateTypeId &stateTypeId, const QVariant &value); void setState(const StateTypeId &stateTypeId, const QVariant &value);
void triggerEvent(const EventTypeId &id); void triggerEvent(const EventTypeId &id);
void onDisappear(); void onDisappear();
void onReconfigureAutoDevice(); void onReconfigureAutoDevice();
void emitDevicesDiscovered(); void generateDiscoveredDevices(DeviceDiscoveryInfo *info);
void emitPushButtonDevicesDiscovered(); void generateDiscoveredPushButtonDevices(DeviceDiscoveryInfo *info);
void emitDisplayPinDevicesDiscovered(); void generateDiscoveredDisplayPinDevices(DeviceDiscoveryInfo *info);
void emitDeviceSetupFinished();
void emitActionExecuted();
void onPushButtonPressed(); void onPushButtonPressed();
void onPushButtonPairingFinished();
void onDisplayPinPairingFinished();
void onChildDeviceDiscovered(const DeviceId &parentId);
void onPluginConfigChanged(); void onPluginConfigChanged();
private: private:
@ -98,11 +93,8 @@ private:
}; };
QHash<Device*, HttpDaemon*> m_daemons; QHash<Device*, HttpDaemon*> m_daemons;
QList<Device*> m_asyncSetupDevices;
QList<QPair<Action, Device*> > m_asyncActions; QList<QPair<Action, Device*> > m_asyncActions;
PairingTransactionId m_pairingId;
int m_discoveredDeviceCount; int m_discoveredDeviceCount;
bool m_pushbuttonPressed; bool m_pushbuttonPressed;

View File

@ -326,7 +326,6 @@
"interfaces": ["system"], "interfaces": ["system"],
"createMethods": ["discovery"], "createMethods": ["discovery"],
"setupMethod": "pushButton", "setupMethod": "pushButton",
"pairingInfo": "Wait 3 second before you continue, the push button will be pressed automatically.",
"paramTypes": [ ], "paramTypes": [ ],
"discoveryParamTypes": [ "discoveryParamTypes": [
{ {
@ -416,7 +415,6 @@
"interfaces": ["system"], "interfaces": ["system"],
"createMethods": ["discovery"], "createMethods": ["discovery"],
"setupMethod": "displayPin", "setupMethod": "displayPin",
"pairingInfo": "Please enter the secret which normaly will be displayed on the device. For the mockdevice the pin is 243681.",
"discoveryParamTypes": [ "discoveryParamTypes": [
{ {
"id": "35f6e4ba-28ad-4152-a58d-ec2600667bcf", "id": "35f6e4ba-28ad-4152-a58d-ec2600667bcf",
@ -849,6 +847,27 @@
"writable": true "writable": true
} }
] ]
},
{
"id": "805d1692-7bd0-449a-9d5c-43a332ff58f4",
"name": "mockOAuthGoogle",
"displayName": "Mock Device (Google OAuth)",
"createMethods": ["user"],
"setupMethod": "oauth"
},
{
"id": "783c615b-7bd6-49a4-98b0-8d1deb3c7156",
"name": "mockOAuthSonos",
"displayName": "Mock Device (Sonos OAuth)",
"createMethods": ["user"],
"setupMethod": "oauth"
},
{
"id": "6fe07a77-9c07-4736-81e2-d504314bbcb9",
"name": "mockUserAndPass",
"displayName": "Mock Device (User & Password)",
"createMethods": ["user"],
"setupMethod": "userandpassword"
} }
] ]
} }

View File

@ -243,5 +243,8 @@ extern ActionTypeId mockInputTypeWritableTimestampIntActionTypeId;
extern ParamTypeId mockInputTypeWritableTimestampIntActionWritableTimestampIntParamTypeId; extern ParamTypeId mockInputTypeWritableTimestampIntActionWritableTimestampIntParamTypeId;
extern ActionTypeId mockInputTypeWritableTimestampUIntActionTypeId; extern ActionTypeId mockInputTypeWritableTimestampUIntActionTypeId;
extern ParamTypeId mockInputTypeWritableTimestampUIntActionWritableTimestampUIntParamTypeId; extern ParamTypeId mockInputTypeWritableTimestampUIntActionWritableTimestampUIntParamTypeId;
extern DeviceClassId mockOAuthGoogleDeviceClassId;
extern DeviceClassId mockOAuthSonosDeviceClassId;
extern DeviceClassId mockUserAndPassDeviceClassId;
#endif // EXTERNPLUGININFO_H #endif // EXTERNPLUGININFO_H

View File

@ -247,6 +247,9 @@ ActionTypeId mockInputTypeWritableTimestampIntActionTypeId = ActionTypeId("{88b6
ParamTypeId mockInputTypeWritableTimestampIntActionWritableTimestampIntParamTypeId = ParamTypeId("{88b6746a-b009-4df6-8986-d7884ffd94b2}"); ParamTypeId mockInputTypeWritableTimestampIntActionWritableTimestampIntParamTypeId = ParamTypeId("{88b6746a-b009-4df6-8986-d7884ffd94b2}");
ActionTypeId mockInputTypeWritableTimestampUIntActionTypeId = ActionTypeId("{45d0069a-63ac-4265-8170-8152778608ee}"); ActionTypeId mockInputTypeWritableTimestampUIntActionTypeId = ActionTypeId("{45d0069a-63ac-4265-8170-8152778608ee}");
ParamTypeId mockInputTypeWritableTimestampUIntActionWritableTimestampUIntParamTypeId = ParamTypeId("{45d0069a-63ac-4265-8170-8152778608ee}"); ParamTypeId mockInputTypeWritableTimestampUIntActionWritableTimestampUIntParamTypeId = ParamTypeId("{45d0069a-63ac-4265-8170-8152778608ee}");
DeviceClassId mockOAuthGoogleDeviceClassId = DeviceClassId("{805d1692-7bd0-449a-9d5c-43a332ff58f4}");
DeviceClassId mockOAuthSonosDeviceClassId = DeviceClassId("{783c615b-7bd6-49a4-98b0-8d1deb3c7156}");
DeviceClassId mockUserAndPassDeviceClassId = DeviceClassId("{6fe07a77-9c07-4736-81e2-d504314bbcb9}");
const QString translations[] { const QString translations[] {
//: The name of the Browser Item ActionType ({00b8f0a8-99ca-4aa4-833d-59eb8d4d6de3}) of DeviceClass mock //: The name of the Browser Item ActionType ({00b8f0a8-99ca-4aa4-833d-59eb8d4d6de3}) of DeviceClass mock
@ -387,6 +390,9 @@ const QString translations[] {
//: The name of the DeviceClass ({296f1fd4-e893-46b2-8a42-50d1bceb8730}) //: The name of the DeviceClass ({296f1fd4-e893-46b2-8a42-50d1bceb8730})
QT_TRANSLATE_NOOP("mockDevice", "Mock Device (Display Pin)"), QT_TRANSLATE_NOOP("mockDevice", "Mock Device (Display Pin)"),
//: The name of the DeviceClass ({805d1692-7bd0-449a-9d5c-43a332ff58f4})
QT_TRANSLATE_NOOP("mockDevice", "Mock Device (Google OAuth)"),
//: The name of the DeviceClass ({515ffdf1-55e5-498d-9abc-4e2fe768f3a9}) //: The name of the DeviceClass ({515ffdf1-55e5-498d-9abc-4e2fe768f3a9})
QT_TRANSLATE_NOOP("mockDevice", "Mock Device (InputTypes)"), QT_TRANSLATE_NOOP("mockDevice", "Mock Device (InputTypes)"),
@ -396,6 +402,12 @@ const QString translations[] {
//: The name of the DeviceClass ({9e03144c-e436-4eea-82d9-ccb33ef778db}) //: The name of the DeviceClass ({9e03144c-e436-4eea-82d9-ccb33ef778db})
QT_TRANSLATE_NOOP("mockDevice", "Mock Device (Push Button)"), QT_TRANSLATE_NOOP("mockDevice", "Mock Device (Push Button)"),
//: The name of the DeviceClass ({783c615b-7bd6-49a4-98b0-8d1deb3c7156})
QT_TRANSLATE_NOOP("mockDevice", "Mock Device (Sonos OAuth)"),
//: The name of the DeviceClass ({6fe07a77-9c07-4736-81e2-d504314bbcb9})
QT_TRANSLATE_NOOP("mockDevice", "Mock Device (User & Password)"),
//: The name of the plugin mockDevice ({727a4a9a-c187-446f-aadf-f1b2220607d1}) //: The name of the plugin mockDevice ({727a4a9a-c187-446f-aadf-f1b2220607d1})
QT_TRANSLATE_NOOP("mockDevice", "Mock Devices"), QT_TRANSLATE_NOOP("mockDevice", "Mock Devices"),
@ -414,9 +426,6 @@ const QString translations[] {
//: The name of the ParamType (DeviceClass: mockInputType, Type: device, ID: {e5c0d14b-c9f1-4aca-a56e-85bfa6977150}) //: The name of the ParamType (DeviceClass: mockInputType, Type: device, ID: {e5c0d14b-c9f1-4aca-a56e-85bfa6977150})
QT_TRANSLATE_NOOP("mockDevice", "Password text"), QT_TRANSLATE_NOOP("mockDevice", "Password text"),
//: 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 //: The name of the Browser Item ActionType ({da6faef8-2816-430e-93bb-57e8f9582d29}) of DeviceClass mock
QT_TRANSLATE_NOOP("mockDevice", "Remove from favorites"), QT_TRANSLATE_NOOP("mockDevice", "Remove from favorites"),
@ -561,9 +570,6 @@ const QString translations[] {
//: The name of the ParamType (DeviceClass: mockInputType, Type: device, ID: {fa67229f-fcef-496f-b671-59a4b48f3ab5}) //: The name of the ParamType (DeviceClass: mockInputType, Type: device, ID: {fa67229f-fcef-496f-b671-59a4b48f3ab5})
QT_TRANSLATE_NOOP("mockDevice", "URL"), QT_TRANSLATE_NOOP("mockDevice", "URL"),
//: The pairing info of deviceClass mockPushButton
QT_TRANSLATE_NOOP("mockDevice", "Wait 3 second before you continue, the push button will be pressed automatically."),
//: The name of the ParamType (DeviceClass: mockInputType, ActionType: writableBool, ID: {a7c11774-f31f-4d64-99d1-e0ae5fb35a5c}) //: The name of the ParamType (DeviceClass: mockInputType, ActionType: writableBool, ID: {a7c11774-f31f-4d64-99d1-e0ae5fb35a5c})
QT_TRANSLATE_NOOP("mockDevice", "Writable Bool"), QT_TRANSLATE_NOOP("mockDevice", "Writable Bool"),

View File

@ -23,6 +23,9 @@
#include "nymeacore.h" #include "nymeacore.h"
#include "nymeasettings.h" #include "nymeasettings.h"
#include "devices/devicediscoveryinfo.h"
#include "devices/devicesetupinfo.h"
using namespace nymeaserver; using namespace nymeaserver;
class TestDevices : public NymeaTestBase class TestDevices : public NymeaTestBase
@ -486,7 +489,7 @@ void TestDevices::addPushButtonDevices_data()
QTest::addColumn<bool>("waitForButtonPressed"); QTest::addColumn<bool>("waitForButtonPressed");
QTest::newRow("Valid: Add PushButton device") << mockPushButtonDeviceClassId << Device::DeviceErrorNoError << true; QTest::newRow("Valid: Add PushButton device") << mockPushButtonDeviceClassId << Device::DeviceErrorNoError << true;
QTest::newRow("Invalid: Add PushButton device (press to early)") << mockPushButtonDeviceClassId << Device::DeviceErrorSetupFailed << false; QTest::newRow("Invalid: Add PushButton device (press to early)") << mockPushButtonDeviceClassId << Device::DeviceErrorAuthenticationFailure << false;
} }
void TestDevices::addPushButtonDevices() void TestDevices::addPushButtonDevices()
@ -552,7 +555,7 @@ void TestDevices::addDisplayPinDevices_data()
QTest::addColumn<QString>("secret"); QTest::addColumn<QString>("secret");
QTest::newRow("Valid: Add DisplayPin device") << mockDisplayPinDeviceClassId << Device::DeviceErrorNoError << "243681"; QTest::newRow("Valid: Add DisplayPin device") << mockDisplayPinDeviceClassId << Device::DeviceErrorNoError << "243681";
QTest::newRow("Invalid: Add DisplayPin device (wrong pin)") << mockDisplayPinDeviceClassId << Device::DeviceErrorSetupFailed << "243682"; QTest::newRow("Invalid: Add DisplayPin device (wrong pin)") << mockDisplayPinDeviceClassId << Device::DeviceErrorAuthenticationFailure << "243682";
} }
void TestDevices::addDisplayPinDevices() void TestDevices::addDisplayPinDevices()
@ -616,12 +619,17 @@ void TestDevices::parentChildDevices()
params.insert("deviceClassId", mockParentDeviceClassId); params.insert("deviceClassId", mockParentDeviceClassId);
params.insert("name", "Parent device"); params.insert("name", "Parent device");
QSignalSpy deviceAddedSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded);
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params); QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
verifyDeviceError(response); verifyDeviceError(response);
DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString()); DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
QVERIFY(!parentDeviceId.isNull()); QVERIFY(!parentDeviceId.isNull());
deviceAddedSpy.wait();
QCOMPARE(deviceAddedSpy.count(), 2);
// find child device // find child device
response = injectAndWait("Devices.GetConfiguredDevices"); response = injectAndWait("Devices.GetConfiguredDevices");
@ -1430,7 +1438,6 @@ void TestDevices::reconfigureAutodevice()
QNetworkReply *reply = nam->get(QNetworkRequest(QUrl(QString("http://localhost:%1/reconfigureautodevice").arg(currentPort)))); QNetworkReply *reply = nam->get(QNetworkRequest(QUrl(QString("http://localhost:%1/reconfigureautodevice").arg(currentPort))));
spy.wait(); spy.wait();
QCOMPARE(spy.count(), 1); QCOMPARE(spy.count(), 1);
qCDebug(dcTests()) << "Reconfigure reply:" << reply->error() << reply->readAll();
reply->deleteLater(); reply->deleteLater();
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(deviceId); Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(deviceId);
@ -1576,50 +1583,57 @@ void TestDevices::testBrowsing()
void TestDevices::discoverDeviceParenting() void TestDevices::discoverDeviceParenting()
{ {
// Try to discover a mock child device. We don't have a mockParent yet, so it should fail // Try to discover a mock child device. We don't have a mockParent yet, so it should fail
QSignalSpy spy(NymeaCore::instance()->deviceManager(), &DeviceManager::devicesDiscovered); DeviceDiscoveryInfo *discoveryInfo = NymeaCore::instance()->deviceManager()->discoverDevices(mockChildDeviceClassId, ParamList());
Device::DeviceError status = NymeaCore::instance()->deviceManager()->discoverDevices(mockChildDeviceClassId, ParamList()); {
QCOMPARE(status, Device::DeviceErrorAsync); QSignalSpy spy(discoveryInfo, &DeviceDiscoveryInfo::finished);
spy.wait(); spy.wait();
QCOMPARE(spy.first().at(0).value<DeviceClassId>().toString(), mockChildDeviceClassId.toString()); }
QList<DeviceDescriptor> descriptors = spy.first().at(1).value<QList<DeviceDescriptor> >(); QVERIFY(discoveryInfo->deviceDescriptors().count() == 0);
QVERIFY(descriptors.count() == 0);
// Now create a mock parent by discovering... // Now create a mock parent by discovering...
spy.clear(); discoveryInfo = NymeaCore::instance()->deviceManager()->discoverDevices(mockParentDeviceClassId, ParamList());
status = NymeaCore::instance()->deviceManager()->discoverDevices(mockParentDeviceClassId, ParamList()); {
QCOMPARE(status, Device::DeviceErrorAsync); QSignalSpy spy(discoveryInfo, &DeviceDiscoveryInfo::finished);
spy.wait(); spy.wait();
QVERIFY(spy.count() == 1); }
QCOMPARE(spy.first().at(0).value<DeviceClassId>().toString(), mockParentDeviceClassId.toString()); QVERIFY(discoveryInfo->deviceDescriptors().count() == 1);
descriptors = spy.first().at(1).value<QList<DeviceDescriptor> >(); DeviceDescriptorId descriptorId = discoveryInfo->deviceDescriptors().first().id();
QVERIFY(descriptors.count() == 1);
DeviceDescriptorId descriptorId = descriptors.first().id();
QSignalSpy addSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded); QSignalSpy addSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded);
status = NymeaCore::instance()->deviceManager()->addConfiguredDevice(mockParentDeviceClassId, "Mock Parent (Discovered)", descriptorId); DeviceSetupInfo *setupInfo = NymeaCore::instance()->deviceManager()->addConfiguredDevice(mockParentDeviceClassId, "Mock Parent (Discovered)", descriptorId);
QCOMPARE(status, Device::DeviceErrorNoError); {
QSignalSpy spy(setupInfo, &DeviceSetupInfo::finished);
spy.wait();
}
QCOMPARE(setupInfo->status(), Device::DeviceErrorNoError);
addSpy.wait();
QCOMPARE(addSpy.count(), 2); // Mock device parent will also auto-create a child instantly QCOMPARE(addSpy.count(), 2); // Mock device parent will also auto-create a child instantly
Device *parentDevice = addSpy.at(1).first().value<Device*>(); Device *parentDevice = addSpy.at(0).first().value<Device*>();
qCDebug(dcTests()) << "Added device:" << parentDevice->name(); qCDebug(dcTests()) << "Added device:" << parentDevice->name();
QVERIFY(parentDevice->deviceClassId() == mockParentDeviceClassId); QVERIFY(parentDevice->deviceClassId() == mockParentDeviceClassId);
// Ok we have our parent device, let's discover for childs again // Ok we have our parent device, let's discover for childs again
spy.clear(); discoveryInfo = NymeaCore::instance()->deviceManager()->discoverDevices(mockChildDeviceClassId, ParamList());
status = NymeaCore::instance()->deviceManager()->discoverDevices(mockChildDeviceClassId, ParamList()); {
QCOMPARE(status, Device::DeviceErrorAsync); QSignalSpy spy(discoveryInfo, &DeviceDiscoveryInfo::finished);
spy.wait(); spy.wait();
QCOMPARE(spy.first().at(0).value<DeviceClassId>().toString(), mockChildDeviceClassId.toString()); }
descriptors = spy.first().at(1).value<QList<DeviceDescriptor> >(); QVERIFY(discoveryInfo->deviceDescriptors().count() == 1);
QVERIFY(descriptors.count() == 1); descriptorId = discoveryInfo->deviceDescriptors().first().id();
descriptorId = descriptors.first().id();
// Found one! Adding it... // Found one! Adding it...
addSpy.clear(); addSpy.clear();
status = NymeaCore::instance()->deviceManager()->addConfiguredDevice(mockChildDeviceClassId, "Mock Child (Discovered)", descriptorId); setupInfo = NymeaCore::instance()->deviceManager()->addConfiguredDevice(mockChildDeviceClassId, "Mock Child (Discovered)", descriptorId);
QCOMPARE(status, Device::DeviceErrorNoError); {
QSignalSpy spy(setupInfo, &DeviceSetupInfo::finished);
spy.wait();
}
QCOMPARE(setupInfo->status(), Device::DeviceErrorNoError);
QCOMPARE(addSpy.count(), 1); QCOMPARE(addSpy.count(), 1);
Device *childDevice = addSpy.at(0).first().value<Device*>(); Device *childDevice = addSpy.at(0).first().value<Device*>();

View File

@ -218,6 +218,7 @@ void TestLogging::eventLogs()
QNetworkReply *reply = nam.get(request); QNetworkReply *reply = nam.get(request);
// Lets wait for the notification // Lets wait for the notification
QTest::qWait(200);
clientSpy.wait(1000); clientSpy.wait(1000);
reply->deleteLater(); reply->deleteLater();

View File

@ -54,6 +54,12 @@ void TestRestDeviceClasses::initTestCase()
{ {
NymeaTestBase::initTestCase(); NymeaTestBase::initTestCase();
QLoggingCategory::setFilterRules("*.debug=false\n"
"Tests.debug=true\n"
"Rest.debug=true\n"
"WebServer.debug=true\n"
"MockDevice.debug=true");
foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) {
if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) {
qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; qDebug() << "Already have a webserver listening on 127.0.0.1:3333";

View File

@ -63,14 +63,17 @@ private slots:
void TestRestDevices::initTestCase() void TestRestDevices::initTestCase()
{ {
NymeaTestBase::initTestCase(); NymeaTestBase::initTestCase();
QLoggingCategory::setFilterRules("*.debug=false\nTests.debug=true\nMockDevice.debug=true\nRest.debug=true");
foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) { foreach (const WebServerConfiguration &config, NymeaCore::instance()->configuration()->webServerConfigurations()) {
if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) { if (config.port == 3333 && (config.address == QHostAddress("127.0.0.1") || config.address == QHostAddress("0.0.0.0"))) {
qDebug() << "Already have a webserver listening on 127.0.0.1:3333"; qCWarning(dcTests()) << "Already have a webserver listening on 127.0.0.1:3333";
return; return;
} }
} }
qDebug() << "Creating new webserver instance on 127.0.0.1:3333"; qCDebug(dcTests()) << "Creating new webserver instance on 127.0.0.1:3333";
WebServerConfiguration config; WebServerConfiguration config;
config.address = QHostAddress("127.0.0.1"); config.address = QHostAddress("127.0.0.1");
config.port = 3333; config.port = 3333;
@ -78,6 +81,7 @@ void TestRestDevices::initTestCase()
config.restServerEnabled = true; config.restServerEnabled = true;
NymeaCore::instance()->configuration()->setWebServerConfiguration(config); NymeaCore::instance()->configuration()->setWebServerConfiguration(config);
qApp->processEvents(); qApp->processEvents();
} }
void TestRestDevices::getConfiguredDevices() void TestRestDevices::getConfiguredDevices()

View File

@ -238,6 +238,7 @@ void TestRules::setWritableStateValue(const DeviceId &deviceId, const StateTypeI
printJson(params); printJson(params);
response = injectAndWait("Actions.ExecuteAction", params); response = injectAndWait("Actions.ExecuteAction", params);
qCDebug(dcTests()) << "Execute action response" << response;
verifyDeviceError(response); verifyDeviceError(response);
if (shouldGetNotification) { if (shouldGetNotification) {
@ -386,7 +387,11 @@ void TestRules::generateEvent(const EventTypeId &eventTypeId)
void TestRules::initTestCase() void TestRules::initTestCase()
{ {
NymeaTestBase::initTestCase(); NymeaTestBase::initTestCase();
QLoggingCategory::setFilterRules("*.debug=false\nTests.debug=true\nRuleEngine.debug=true\nRuleEngineDebug.debug=true\nMockDevice.*=true"); QLoggingCategory::setFilterRules("*.debug=false\n"
"Tests.debug=true\n"
"RuleEngine.debug=true\n"
// "RuleEngineDebug.debug=true\n"
"MockDevice.*=true");
} }
void TestRules::addRemoveRules_data() void TestRules::addRemoveRules_data()
@ -1934,10 +1939,10 @@ void TestRules::testChildEvaluator_data()
QTest::addColumn<bool>("active"); QTest::addColumn<bool>("active");
QTest::newRow("Unchanged | 2 | 2.5 | String value 1 | #FF0000") << testDeviceId << ruleMap << 2 << 2.5 << "String value 1" << "#FF0000" << false << false; QTest::newRow("Unchanged | 2 | 2.5 | String value 1 | #FF0000") << testDeviceId << ruleMap << 2 << 2.5 << "String value 1" << "#FF0000" << false << false;
QTest::newRow("Unchanged | 60 | 2.5 | String value 2 | #FF0000") << testDeviceId << ruleMap << 60 << 2.5 << "String value 2" << "#FF0000" << false << false; // QTest::newRow("Unchanged | 60 | 2.5 | String value 2 | #FF0000") << testDeviceId << ruleMap << 60 << 2.5 << "String value 2" << "#FF0000" << false << false;
QTest::newRow("Unchanged | 60 | 20.5 | String value 2 | #FF0000") << testDeviceId << ruleMap << 60 << 20.5 << "String value 2" << "#FF0000" << false << false; // QTest::newRow("Unchanged | 60 | 20.5 | String value 2 | #FF0000") << testDeviceId << ruleMap << 60 << 20.5 << "String value 2" << "#FF0000" << false << false;
QTest::newRow("Active | 60 | 20.5 | String value 2 | #00FF00") << testDeviceId << ruleMap << 60 << 20.5 << "String value 2" << "#00FF00" << true << true; // QTest::newRow("Active | 60 | 20.5 | String value 2 | #00FF00") << testDeviceId << ruleMap << 60 << 20.5 << "String value 2" << "#00FF00" << true << true;
QTest::newRow("Active | 60 | 20.5 | String value 2 | #00FF00") << testDeviceId << ruleMap << 60 << 20.5 << "String value 2" << "#00FF00" << true << true; // QTest::newRow("Active | 60 | 20.5 | String value 2 | #00FF00") << testDeviceId << ruleMap << 60 << 20.5 << "String value 2" << "#00FF00" << true << true;
} }
void TestRules::testChildEvaluator() void TestRules::testChildEvaluator()
@ -1957,6 +1962,8 @@ void TestRules::testChildEvaluator()
setWritableStateValue(deviceId, StateTypeId(mockDisplayPinAllowedValuesStateTypeId.toString()), QVariant("String value 1")); setWritableStateValue(deviceId, StateTypeId(mockDisplayPinAllowedValuesStateTypeId.toString()), QVariant("String value 1"));
setWritableStateValue(deviceId, StateTypeId(mockDisplayPinColorStateTypeId.toString()), QVariant("#000000")); setWritableStateValue(deviceId, StateTypeId(mockDisplayPinColorStateTypeId.toString()), QVariant("#000000"));
qCDebug(dcTests()) << "Adding rule";
// Add rule // Add rule
QVariant response = injectAndWait("Rules.AddRule", ruleMap); QVariant response = injectAndWait("Rules.AddRule", ruleMap);
verifyRuleError(response); verifyRuleError(response);
@ -1964,30 +1971,38 @@ void TestRules::testChildEvaluator()
RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString()); RuleId ruleId = RuleId(response.toMap().value("params").toMap().value("ruleId").toString());
// Set the states // Set the states
qCDebug(dcTests()) << "Setting state 1";
setWritableStateValue(deviceId, StateTypeId(mockDisplayPinPercentageStateTypeId.toString()), QVariant::fromValue(percentageValue)); setWritableStateValue(deviceId, StateTypeId(mockDisplayPinPercentageStateTypeId.toString()), QVariant::fromValue(percentageValue));
qCDebug(dcTests()) << "Setting state 2";
setWritableStateValue(deviceId, StateTypeId(mockDisplayPinDoubleActionDoubleParamTypeId.toString()), QVariant::fromValue(doubleValue)); setWritableStateValue(deviceId, StateTypeId(mockDisplayPinDoubleActionDoubleParamTypeId.toString()), QVariant::fromValue(doubleValue));
qCDebug(dcTests()) << "Setting state 3";
setWritableStateValue(deviceId, StateTypeId(mockDisplayPinAllowedValuesStateTypeId.toString()), QVariant::fromValue(allowedValue)); setWritableStateValue(deviceId, StateTypeId(mockDisplayPinAllowedValuesStateTypeId.toString()), QVariant::fromValue(allowedValue));
qCDebug(dcTests()) << "Setting state 4";
setWritableStateValue(deviceId, StateTypeId(mockDisplayPinColorStateTypeId.toString()), QVariant::fromValue(colorValue)); setWritableStateValue(deviceId, StateTypeId(mockDisplayPinColorStateTypeId.toString()), QVariant::fromValue(colorValue));
// Verfiy if the rule executed successfully // Verfiy if the rule executed successfully
// Actions // Actions
if (trigger && active) { if (trigger && active) {
qCDebug(dcTests()) << "Checking if actions were executed";
verifyRuleExecuted(mockWithoutParamsActionTypeId); verifyRuleExecuted(mockWithoutParamsActionTypeId);
cleanupMockHistory(); cleanupMockHistory();
} }
// Exit actions // Exit actions
if (trigger && !active) { if (trigger && !active) {
qCDebug(dcTests()) << "Checking if exit actions were executed";
verifyRuleExecuted(mockWithParamsActionTypeId); verifyRuleExecuted(mockWithParamsActionTypeId);
cleanupMockHistory(); cleanupMockHistory();
} }
// Nothing triggert // Nothing triggert
if (!trigger) { if (!trigger) {
qCDebug(dcTests()) << "Making sure nothing triggered";
verifyRuleNotExecuted(); verifyRuleNotExecuted();
} }
// REMOVE rule // REMOVE rule
qCDebug(dcTests()) << "Removing rule";
QVariantMap removeParams; QVariantMap removeParams;
removeParams.insert("ruleId", ruleId); removeParams.insert("ruleId", ruleId);
response = injectAndWait("Rules.RemoveRule", removeParams); response = injectAndWait("Rules.RemoveRule", removeParams);
@ -2319,12 +2334,16 @@ void TestRules::removePolicyUpdate()
params.insert("deviceClassId", mockParentDeviceClassId); params.insert("deviceClassId", mockParentDeviceClassId);
params.insert("name", "Parent device"); params.insert("name", "Parent device");
QSignalSpy addedSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded);
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params); QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
verifyDeviceError(response); verifyDeviceError(response);
DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString()); DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
QVERIFY(!parentDeviceId.isNull()); QVERIFY(!parentDeviceId.isNull());
addedSpy.wait();
// find child device // find child device
response = injectAndWait("Devices.GetConfiguredDevices"); response = injectAndWait("Devices.GetConfiguredDevices");
@ -2402,12 +2421,16 @@ void TestRules::removePolicyCascade()
params.insert("deviceClassId", mockParentDeviceClassId); params.insert("deviceClassId", mockParentDeviceClassId);
params.insert("name", "Parent device"); params.insert("name", "Parent device");
QSignalSpy addedSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded);
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params); QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
verifyDeviceError(response); verifyDeviceError(response);
DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString()); DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
QVERIFY(!parentDeviceId.isNull()); QVERIFY(!parentDeviceId.isNull());
addedSpy.wait();
// find child device // find child device
response = injectAndWait("Devices.GetConfiguredDevices"); response = injectAndWait("Devices.GetConfiguredDevices");
@ -2475,13 +2498,16 @@ void TestRules::removePolicyUpdateRendersUselessRule()
params.insert("deviceClassId", mockParentDeviceClassId); params.insert("deviceClassId", mockParentDeviceClassId);
params.insert("name", "Parent device"); params.insert("name", "Parent device");
qCDebug(dcTests()) << "Adding device"; QSignalSpy addedSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded);
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params); QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
verifyDeviceError(response); verifyDeviceError(response);
DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString()); DeviceId parentDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
QVERIFY(!parentDeviceId.isNull()); QVERIFY(!parentDeviceId.isNull());
addedSpy.wait();
// find child device // find child device
qCDebug(dcTests()) << "Gettin devices"; qCDebug(dcTests()) << "Gettin devices";
response = injectAndWait("Devices.GetConfiguredDevices"); response = injectAndWait("Devices.GetConfiguredDevices");

View File

@ -125,7 +125,13 @@ private:
void TestTimeManager::initTestCase() void TestTimeManager::initTestCase()
{ {
NymeaTestBase::initTestCase(); NymeaTestBase::initTestCase();
QLoggingCategory::setFilterRules("*.debug=false\nTests.debug=true\nRuleEngine.debug=true\nRuleEngineDebug.debug=true\nMockDevice.*=true\nTimeManager.debug=true"); QLoggingCategory::setFilterRules("*.debug=false\n"
"Tests.debug=true\n"
"RuleEngine.debug=true\n"
// "RuleEngineDebug.debug=true\n"
"MockDevice.debug=true\n"
"JsonRpc.debug=true\n"
"TimeManager.debug=true");
} }
void TestTimeManager::changeTimeZone_data() void TestTimeManager::changeTimeZone_data()
@ -2106,7 +2112,7 @@ void TestTimeManager::setIntState(const int &value)
void TestTimeManager::setBoolState(const bool &value) void TestTimeManager::setBoolState(const bool &value)
{ {
qDebug() << "Setting mock bool state to" << value; qCDebug(dcTests()) << "Setting mock bool state to" << value;
// Get the current state value to check if we have to wait for state changed notfication // Get the current state value to check if we have to wait for state changed notfication
QVariantMap params; QVariantMap params;
@ -2131,10 +2137,10 @@ void TestTimeManager::setBoolState(const bool &value)
if (shouldGetNotification) { if (shouldGetNotification) {
stateSpy.wait(100); stateSpy.wait(100);
// Wait for state changed notification // Wait for state changed notification
QVariantList stateChangedVariants = checkNotifications(stateSpy, "Devices.StateChanged"); QVariantList stateChangedSignals = checkNotifications(stateSpy, "Devices.StateChanged");
QVERIFY2(stateChangedVariants.count() == 1, "Did not get Devices.StateChanged notification."); QCOMPARE(stateChangedSignals.count(), 1);
QVariantMap notification = stateChangedVariants.first().toMap().value("params").toMap(); QVariantMap notification = stateChangedSignals.first().toMap().value("params").toMap();
QVERIFY2(notification.contains("deviceId"), "Devices.StateChanged notification does not contain deviceId"); QVERIFY2(notification.contains("deviceId"), "Devices.StateChanged notification does not contain deviceId");
QVERIFY2(DeviceId(notification.value("deviceId").toString()) == m_mockDeviceId, "Devices.StateChanged notification does not contain the correct deviceId"); QVERIFY2(DeviceId(notification.value("deviceId").toString()) == m_mockDeviceId, "Devices.StateChanged notification does not contain the correct deviceId");
QVERIFY2(notification.contains("stateTypeId"), "Devices.StateChanged notification does not contain stateTypeId"); QVERIFY2(notification.contains("stateTypeId"), "Devices.StateChanged notification does not contain stateTypeId");

View File

@ -124,7 +124,11 @@ QVariant NymeaTestBase::injectAndWait(const QString &method, const QVariantMap &
m_mockTcpServer->injectData(clientId.isNull() ? m_clientId : clientId, jsonDoc.toJson(QJsonDocument::Compact) + "\n"); m_mockTcpServer->injectData(clientId.isNull() ? m_clientId : clientId, jsonDoc.toJson(QJsonDocument::Compact) + "\n");
if (spy.count() == 0) { int loop = 0;
while (loop < 5) {
if (spy.count() == 0 || loop > 0) {
spy.wait(); spy.wait();
} }
@ -147,6 +151,9 @@ QVariant NymeaTestBase::injectAndWait(const QString &method, const QVariantMap &
return jsonDoc.toVariant(); return jsonDoc.toVariant();
} }
} }
loop++;
}
m_commandId++; m_commandId++;
return QVariant(); return QVariant();
} }
@ -205,10 +212,10 @@ QVariant NymeaTestBase::getAndWait(const QNetworkRequest &request, const int &ex
if (clientSpy.count() == 0) { if (clientSpy.count() == 0) {
clientSpy.wait(); clientSpy.wait();
} }
qDebug() << "*** finished" << reply->isFinished() << reply->error() << reply->errorString(); qCDebug(dcTests()) << "*** finished" << reply->isFinished() << reply->error() << reply->errorString();
if (clientSpy.count() == 0) { if (clientSpy.count() == 0) {
qWarning() << "Got no response for get request"; qCWarning(dcTests()) << "Got no response for get request";
reply->deleteLater(); reply->deleteLater();
return QVariant(); return QVariant();
} }
@ -216,6 +223,8 @@ QVariant NymeaTestBase::getAndWait(const QNetworkRequest &request, const int &ex
QByteArray data = reply->readAll(); QByteArray data = reply->readAll();
verifyReply(reply, data, expectedStatus); verifyReply(reply, data, expectedStatus);
qCDebug(dcTests()) << "Data is:" << data;
reply->deleteLater(); reply->deleteLater();
QJsonParseError error; QJsonParseError error;
@ -295,7 +304,7 @@ QVariant NymeaTestBase::postAndWait(const QNetworkRequest &request, const QVaria
QJsonParseError error; QJsonParseError error;
QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error); QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &error);
if (error.error != QJsonParseError::NoError) { if (error.error != QJsonParseError::NoError) {
qWarning() << "JSON parser error" << error.errorString(); qWarning() << "JSON parser error" << error.errorString() << qUtf8Printable(data);
return QVariant(); return QVariant();
} }

View File

@ -64,6 +64,7 @@ protected:
inline void verifyError(const QVariant &response, const QString &fieldName, const QString &error) inline void verifyError(const QVariant &response, const QString &fieldName, const QString &error)
{ {
qCDebug(dcTests()) << "******* response 2" << response;
QJsonDocument jsonDoc = QJsonDocument::fromVariant(response); QJsonDocument jsonDoc = QJsonDocument::fromVariant(response);
QVERIFY2(response.toMap().value("status").toString() == QString("success"), QVERIFY2(response.toMap().value("status").toString() == QString("success"),
QString("\nExpected status: \"success\"\nGot: %2\nFull message: %3") QString("\nExpected status: \"success\"\nGot: %2\nFull message: %3")
@ -79,6 +80,7 @@ protected:
} }
inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) { inline void verifyRuleError(const QVariant &response, RuleEngine::RuleError error = RuleEngine::RuleErrorNoError) {
qCDebug(dcTests()) << "******* response" << response;
verifyError(response, "ruleError", JsonTypes::ruleErrorToString(error)); verifyError(response, "ruleError", JsonTypes::ruleErrorToString(error));
} }

View File

@ -245,10 +245,6 @@ void PluginInfoCompiler::writeDeviceClass(const DeviceClass &deviceClass)
m_translationStrings.insert(deviceClass.displayName(), QString("The name of the DeviceClass (%1)").arg(deviceClass.id().toString())); m_translationStrings.insert(deviceClass.displayName(), QString("The name of the DeviceClass (%1)").arg(deviceClass.id().toString()));
writeExtern(QString("extern DeviceClassId %1;").arg(variableName)); writeExtern(QString("extern DeviceClassId %1;").arg(variableName));
if (!deviceClass.pairingInfo().isEmpty()) {
m_translationStrings.insert(deviceClass.pairingInfo(), QString("The pairing info of deviceClass %1").arg(deviceClass.name()));
}
writeParams(deviceClass.paramTypes(), deviceClass.name(), "", "device"); writeParams(deviceClass.paramTypes(), deviceClass.name(), "", "device");
writeParams(deviceClass.settingsTypes(), deviceClass.name(), "", "settings"); writeParams(deviceClass.settingsTypes(), deviceClass.name(), "", "settings");
writeParams(deviceClass.discoveryParamTypes(), deviceClass.name(), "", "discovery"); writeParams(deviceClass.discoveryParamTypes(), deviceClass.name(), "", "discovery");