Add better device setup status details to api
This commit is contained in:
parent
3015130c8f
commit
6e4a0bc84b
@ -436,7 +436,7 @@ DeviceSetupInfo *DeviceManagerImplementation::reconfigureDeviceInternal(Device *
|
||||
plugin->deviceRemoved(device);
|
||||
|
||||
// mark setup as incomplete
|
||||
device->setSetupComplete(false);
|
||||
device->setSetupStatus(Device::DeviceSetupStatusInProgress, Device::DeviceErrorNoError);
|
||||
|
||||
// set new params
|
||||
foreach (const Param ¶m, params) {
|
||||
@ -454,6 +454,7 @@ DeviceSetupInfo *DeviceManagerImplementation::reconfigureDeviceInternal(Device *
|
||||
|
||||
if (info->status() != Device::DeviceErrorNoError) {
|
||||
qCWarning(dcDeviceManager()) << "Device reconfiguration failed for" << info->device()->name() << info->device()->id().toString() << info->status() << info->displayMessage();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusFailed, info->status(), info->displayMessage());
|
||||
// TODO: recover old params.??
|
||||
return;
|
||||
}
|
||||
@ -461,7 +462,7 @@ DeviceSetupInfo *DeviceManagerImplementation::reconfigureDeviceInternal(Device *
|
||||
storeConfiguredDevices();
|
||||
|
||||
postSetupDevice(info->device());
|
||||
info->device()->setupCompleted();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusComplete, Device::DeviceErrorNoError);
|
||||
|
||||
emit deviceChanged(info->device());
|
||||
|
||||
@ -640,7 +641,7 @@ DevicePairingInfo *DeviceManagerImplementation::confirmPairing(const PairingTran
|
||||
}
|
||||
} else {
|
||||
device = m_configuredDevices.value(internalInfo->deviceId());
|
||||
device->setSetupComplete(false);
|
||||
device->setSetupStatus(Device::DeviceSetupStatusInProgress, Device::DeviceErrorNoError);
|
||||
qCDebug(dcDeviceManager()) << "Reconfiguring device" << device;
|
||||
}
|
||||
|
||||
@ -654,10 +655,17 @@ DevicePairingInfo *DeviceManagerImplementation::confirmPairing(const PairingTran
|
||||
externalInfo->finish(info->status(), info->displayMessage());
|
||||
|
||||
if (info->status() != Device::DeviceErrorNoError) {
|
||||
qCWarning(dcDeviceManager()) << "Failed to set up device" << info->device()->name() << info->status() << info->displayMessage();
|
||||
info->device()->deleteLater();
|
||||
if (addNewDevice) {
|
||||
qCWarning(dcDeviceManager()) << "Failed to set up device" << info->device()->name()
|
||||
<< "Not adding device to the system. Error:"
|
||||
<< info->status() << info->displayMessage();
|
||||
info->device()->deleteLater();
|
||||
}
|
||||
|
||||
if (!addNewDevice) {
|
||||
qCWarning(dcDeviceManager()) << "Failed to reconfigure device" << info->device()->name() <<
|
||||
"Error:" << info->status() << info->displayMessage();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusFailed, info->status(), info->displayMessage());
|
||||
// TODO: restore parameters?
|
||||
}
|
||||
|
||||
@ -665,7 +673,7 @@ DevicePairingInfo *DeviceManagerImplementation::confirmPairing(const PairingTran
|
||||
}
|
||||
|
||||
qCDebug(dcDeviceManager()) << "Setup complete for device" << info->device();
|
||||
info->device()->setupCompleted();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusComplete, Device::DeviceErrorNoError);
|
||||
|
||||
if (addNewDevice) {
|
||||
qCDebug(dcDeviceManager()) << "Device added:" << info->device();
|
||||
@ -749,7 +757,7 @@ DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDeviceInternal(const
|
||||
return;
|
||||
}
|
||||
|
||||
info->device()->setupCompleted();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusComplete, Device::DeviceErrorNoError);
|
||||
|
||||
qCDebug(dcDeviceManager) << "Device setup complete.";
|
||||
m_configuredDevices.insert(info->device()->id(), info->device());
|
||||
@ -1062,7 +1070,25 @@ void DeviceManagerImplementation::loadPlugins()
|
||||
if (!fi.exists())
|
||||
continue;
|
||||
|
||||
// Check plugin API version compatibility
|
||||
QLibrary lib(fi.absoluteFilePath());
|
||||
QFunctionPointer versionFunc = lib.resolve("libnymea_api_version");
|
||||
if (!versionFunc) {
|
||||
qCWarning(dcDeviceManager()).nospace() << "Unable to resolve version in plugin " << entry << ". Not loading plugin.";
|
||||
lib.unload();
|
||||
continue;
|
||||
}
|
||||
|
||||
QString version = reinterpret_cast<QString(*)()>(versionFunc)();
|
||||
lib.unload();
|
||||
QStringList parts = version.split('.');
|
||||
QStringList coreParts = QString(LIBNYMEA_API_VERSION).split('.');
|
||||
if (parts.length() != 3 || parts.at(0).toInt() != coreParts.at(0).toInt() || parts.at(1).toInt() > coreParts.at(1).toInt()) {
|
||||
qCWarning(dcDeviceManager()).nospace() << "Libnymea API mismatch for " << entry << ". Core API: " << LIBNYMEA_API_VERSION << ", Plugin API: " << version;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Version is ok. Now load the plugin
|
||||
QPluginLoader loader;
|
||||
loader.setFileName(fi.absoluteFilePath());
|
||||
loader.setLoadHints(QLibrary::ResolveAllSymbolsHint);
|
||||
@ -1073,29 +1099,6 @@ void DeviceManagerImplementation::loadPlugins()
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check plugin API version compatibility
|
||||
QLibrary lib(fi.absoluteFilePath());
|
||||
QFunctionPointer versionFunc = lib.resolve("libnymea_api_version");
|
||||
if (!versionFunc) {
|
||||
qCWarning(dcDeviceManager()).nospace() << "Unable to resolve version in plugin " << entry << ". Not loading plugin.";
|
||||
loader.unload();
|
||||
lib.unload();
|
||||
continue;
|
||||
|
||||
}
|
||||
QString version = reinterpret_cast<QString(*)()>(versionFunc)();
|
||||
// QString *version = reinterpret_cast<QString*>(lib.resolve("libnymea_api_version"));
|
||||
// if (!version) {
|
||||
// }
|
||||
lib.unload();
|
||||
QStringList parts = version.split('.');
|
||||
QStringList coreParts = QString(LIBNYMEA_API_VERSION).split('.');
|
||||
if (parts.length() != 3 || parts.at(0).toInt() != coreParts.at(0).toInt() || parts.at(1).toInt() > coreParts.at(1).toInt()) {
|
||||
qCWarning(dcDeviceManager()).nospace() << "Libnymea API mismatch for " << entry << ". Core API: " << LIBNYMEA_API_VERSION << ", Plugin API: " << version;
|
||||
loader.unload();
|
||||
continue;
|
||||
}
|
||||
|
||||
PluginMetadata metaData(loader.metaData().value("MetaData").toObject());
|
||||
if (!metaData.isValid()) {
|
||||
foreach (const QString &error, metaData.validationErrors()) {
|
||||
@ -1357,6 +1360,7 @@ void DeviceManagerImplementation::loadConfiguredDevices()
|
||||
}
|
||||
Q_ASSERT(device != nullptr);
|
||||
|
||||
device->setSetupStatus(Device::DeviceSetupStatusInProgress, Device::DeviceErrorNoError);
|
||||
DeviceSetupInfo *info = setupDevice(device);
|
||||
// Set receiving object to "device" because at startup we load it in any case, knowing that it worked at
|
||||
// some point. However, it'll be marked as non-working until the setup succeeds so the user might delete
|
||||
@ -1365,11 +1369,14 @@ void DeviceManagerImplementation::loadConfiguredDevices()
|
||||
|
||||
if (info->status() != Device::DeviceErrorNoError) {
|
||||
qCWarning(dcDeviceManager()) << "Error setting up device" << info->device()->name() << info->device()->id().toString() << info->status() << info->displayMessage();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusFailed, info->status(), info->displayMessage());
|
||||
emit deviceChanged(info->device());
|
||||
return;
|
||||
}
|
||||
|
||||
qCDebug(dcDeviceManager()) << "Setup complete for device" << info->device();
|
||||
info->device()->setupCompleted();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusComplete, Device::DeviceErrorNoError);
|
||||
emit deviceChanged(info->device());
|
||||
postSetupDevice(info->device());
|
||||
});
|
||||
}
|
||||
@ -1475,7 +1482,7 @@ void DeviceManagerImplementation::onAutoDevicesAppeared(const DeviceDescriptors
|
||||
return;
|
||||
}
|
||||
|
||||
info->device()->setupCompleted();
|
||||
info->device()->setSetupStatus(Device::DeviceSetupStatusComplete, Device::DeviceErrorNoError);
|
||||
m_configuredDevices.insert(info->device()->id(), info->device());
|
||||
storeConfiguredDevices();
|
||||
|
||||
|
||||
@ -88,6 +88,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
||||
{
|
||||
// Enums
|
||||
registerEnum<Device::DeviceError>();
|
||||
registerEnum<Device::DeviceSetupStatus>();
|
||||
registerEnum<DeviceClass::SetupMethod>();
|
||||
registerEnum<DeviceClass::CreateMethod, DeviceClass::CreateMethods>();
|
||||
registerEnum<Types::Unit>();
|
||||
@ -374,7 +375,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
||||
registerNotification("DeviceAdded", description, params);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
description = "Emitted whenever the params or name of a Device are changed (by EditDevice or ReconfigureDevice).";
|
||||
description = "Emitted whenever the params, name or setupStatus of a Device changes.";
|
||||
params.insert("device", objectRef<Device>());
|
||||
registerNotification("DeviceChanged", description, params);
|
||||
|
||||
@ -627,7 +628,7 @@ JsonReply *DeviceHandler::ConfirmPairing(const QVariantMap ¶ms, const JsonCo
|
||||
return jsonReply;
|
||||
}
|
||||
|
||||
JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const
|
||||
JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms, const JsonContext &context) const
|
||||
{
|
||||
QVariantMap returns;
|
||||
QVariantList configuredDeviceList;
|
||||
@ -641,7 +642,12 @@ JsonReply* DeviceHandler::GetConfiguredDevices(const QVariantMap ¶ms) const
|
||||
}
|
||||
} else {
|
||||
foreach (Device *device, NymeaCore::instance()->deviceManager()->configuredDevices()) {
|
||||
configuredDeviceList.append(pack(device));
|
||||
QVariantMap packedDevice = pack(device).toMap();
|
||||
QString translatedSetupStatus = NymeaCore::instance()->deviceManager()->translate(device->pluginId(), device->setupDisplayMessage(), context.locale());
|
||||
if (!translatedSetupStatus.isEmpty()) {
|
||||
packedDevice["setupDisplayMessage"] = translatedSetupStatus;
|
||||
}
|
||||
configuredDeviceList.append(packedDevice);
|
||||
}
|
||||
}
|
||||
returns.insert("devices", configuredDeviceList);
|
||||
@ -977,6 +983,25 @@ void DeviceHandler::deviceSettingChangedNotification(const DeviceId deviceId, co
|
||||
emit DeviceSettingChanged(params);
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::translateNotification(const QString ¬ification, const QVariantMap ¶ms, const QLocale &locale)
|
||||
{
|
||||
if (notification == "DeviceChanged") {
|
||||
QVariantMap deviceMap = params.value("device").toMap();
|
||||
DeviceId deviceId = params.value("device").toMap().value("id").toUuid();
|
||||
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(deviceId);
|
||||
QString setupDisplayMessage = params.value("device").toMap().value("setupDisplayMessage").toString();
|
||||
QString translatedSetupDisplayMessage = NymeaCore::instance()->deviceManager()->translate(device->pluginId(), setupDisplayMessage, locale);
|
||||
if (!translatedSetupDisplayMessage.isEmpty()) {
|
||||
deviceMap["setupDisplayMessage"] = translatedSetupDisplayMessage;
|
||||
}
|
||||
QVariantMap translatedParams = params;
|
||||
translatedParams["device"] = deviceMap;
|
||||
return translatedParams;
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
QVariantMap DeviceHandler::statusToReply(Device::DeviceError status) const
|
||||
{
|
||||
QVariantMap returns;
|
||||
|
||||
@ -43,6 +43,7 @@ public:
|
||||
explicit DeviceHandler(QObject *parent = nullptr);
|
||||
|
||||
QString name() const override;
|
||||
QVariantMap translateNotification(const QString ¬ification, const QVariantMap ¶ms, const QLocale &locale) override;
|
||||
|
||||
Q_INVOKABLE JsonReply *GetSupportedVendors(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
Q_INVOKABLE JsonReply *GetSupportedDevices(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
@ -54,7 +55,7 @@ public:
|
||||
Q_INVOKABLE JsonReply *AddConfiguredDevice(const QVariantMap ¶ms, const JsonContext &context);
|
||||
Q_INVOKABLE JsonReply *PairDevice(const QVariantMap ¶ms, const JsonContext &context);
|
||||
Q_INVOKABLE JsonReply *ConfirmPairing(const QVariantMap ¶ms, const JsonContext &context);
|
||||
Q_INVOKABLE JsonReply *GetConfiguredDevices(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *GetConfiguredDevices(const QVariantMap ¶ms, const JsonContext &context) const;
|
||||
Q_INVOKABLE JsonReply *ReconfigureDevice(const QVariantMap ¶ms, const JsonContext &context);
|
||||
Q_INVOKABLE JsonReply *EditDevice(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *RemoveConfiguredDevice(const QVariantMap ¶ms);
|
||||
|
||||
@ -738,26 +738,11 @@ void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms)
|
||||
JsonHandler *handler = qobject_cast<JsonHandler *>(sender());
|
||||
QMetaMethod method = handler->metaObject()->method(senderSignalIndex());
|
||||
|
||||
QList<QUuid> clientsToBeNotified;
|
||||
foreach (const QUuid &clientId, m_clientNotifications.keys()) {
|
||||
if (m_clientNotifications.value(clientId).contains(handler->name())) {
|
||||
clientsToBeNotified.append(clientId);
|
||||
}
|
||||
}
|
||||
if (clientsToBeNotified.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap notification;
|
||||
notification.insert("id", m_notificationId++);
|
||||
notification.insert("notification", handler->name() + "." + method.name());
|
||||
notification.insert("params", params);
|
||||
|
||||
JsonValidator validator;
|
||||
Q_ASSERT_X(validator.validateNotificationParams(params, handler->name() + '.' + method.name(), m_api).success(),
|
||||
validator.result().where().toUtf8(),
|
||||
validator.result().errorString().toUtf8() + "\nGot:" + QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
|
||||
|
||||
// Add deprecation warning if necessary
|
||||
if (m_api.value("notifications").toMap().value(handler->name() + '.' + method.name()).toMap().contains("deprecated")) {
|
||||
QString deprecationMessage = m_api.value("notifications").toMap().value(handler->name() + '.' + method.name()).toMap().value("deprecated").toString();
|
||||
qCWarning(dcJsonRpc()) << "Client uses deprecated API. Please update client implementation!";
|
||||
@ -765,11 +750,28 @@ void JsonRPCServerImplementation::sendNotification(const QVariantMap ¶ms)
|
||||
notification.insert("deprecationWarning", deprecationMessage);
|
||||
}
|
||||
|
||||
QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact);
|
||||
qCDebug(dcJsonRpcTraffic()) << "Notification content:" << data;
|
||||
foreach (const QUuid &clientId, m_clientNotifications.keys()) {
|
||||
|
||||
// Check if this client wants to be notified
|
||||
if (!m_clientNotifications.value(clientId).contains(handler->name())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QLocale locale = m_clientLocales.value(clientId);
|
||||
QVariantMap translatedParams = handler->translateNotification(method.name(), params, locale);
|
||||
|
||||
JsonValidator validator;
|
||||
Q_ASSERT_X(validator.validateNotificationParams(translatedParams, handler->name() + '.' + method.name(), m_api).success(),
|
||||
validator.result().where().toUtf8(),
|
||||
validator.result().errorString().toUtf8() + "\nGot:" + QJsonDocument::fromVariant(translatedParams).toJson(QJsonDocument::Indented));
|
||||
|
||||
notification.insert("params", translatedParams);
|
||||
|
||||
QByteArray data = QJsonDocument::fromVariant(notification).toJson(QJsonDocument::Compact);
|
||||
|
||||
qCDebug(dcJsonRpc()) << "Sending notification" << handler->name() + "." + method.name() << "to client" << clientId;
|
||||
qCDebug(dcJsonRpcTraffic()) << "Notification content:" << data;
|
||||
|
||||
foreach (const QUuid &clientId, clientsToBeNotified) {
|
||||
qCDebug(dcJsonRpc()) << "Sending notification:" << handler->name() + "." + method.name();
|
||||
m_clientTransports.value(clientId)->sendData(clientId, data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ JsonValidator::Result JsonValidator::validateMap(const QVariantMap &map, const Q
|
||||
continue;
|
||||
}
|
||||
QString trimmedKey = key;
|
||||
trimmedKey.remove(QRegExp("^(o:|r:|d:)"));
|
||||
trimmedKey.remove(QRegExp("^(o:|r:|d:)*"));
|
||||
if (!map.contains(trimmedKey)) {
|
||||
return Result(false, "Missing required key: " + key, key);
|
||||
}
|
||||
|
||||
@ -138,11 +138,6 @@ Device::Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *pa
|
||||
|
||||
}
|
||||
|
||||
void Device::setupCompleted()
|
||||
{
|
||||
m_setupComplete = true;
|
||||
}
|
||||
|
||||
/*! Returns the id of this Device. */
|
||||
DeviceId Device::id() const
|
||||
{
|
||||
@ -366,10 +361,16 @@ void Device::setParentId(const DeviceId &parentId)
|
||||
m_parentId = parentId;
|
||||
}
|
||||
|
||||
/*! Returns true, if setup of this Device is already completed. */
|
||||
/*! Returns true, if setup of this Device is already completed. This method is deprecated, use setupStatus() instead. */
|
||||
bool Device::setupComplete() const
|
||||
{
|
||||
return m_setupComplete;
|
||||
return m_setupStatus == DeviceSetupStatusComplete;
|
||||
}
|
||||
|
||||
/*! Returns the setup error display message, if any. */
|
||||
QString Device::setupDisplayMessage() const
|
||||
{
|
||||
return m_setupDisplayMessage;
|
||||
}
|
||||
|
||||
/*! Returns true if this device has been auto-created (not created by the user) */
|
||||
@ -378,9 +379,23 @@ bool Device::autoCreated() const
|
||||
return m_autoCreated;
|
||||
}
|
||||
|
||||
void Device::setSetupComplete(bool complete)
|
||||
/* Returns the current device setup status. */
|
||||
Device::DeviceSetupStatus Device::setupStatus() const
|
||||
{
|
||||
m_setupComplete = complete;
|
||||
return m_setupStatus;
|
||||
}
|
||||
|
||||
Device::DeviceError Device::setupError() const
|
||||
{
|
||||
return m_setupError;
|
||||
}
|
||||
|
||||
void Device::setSetupStatus(Device::DeviceSetupStatus status, Device::DeviceError setupError, const QString &displayMessage)
|
||||
{
|
||||
m_setupStatus = status;
|
||||
m_setupError = setupError;
|
||||
m_setupDisplayMessage = displayMessage;
|
||||
emit setupStatusChanged();
|
||||
}
|
||||
|
||||
Devices::Devices(const QList<Device*> &other)
|
||||
|
||||
@ -50,12 +50,15 @@ class LIBNYMEA_EXPORT Device: public QObject
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QUuid id READ id)
|
||||
Q_PROPERTY(QUuid deviceClassId READ deviceClassId)
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
|
||||
Q_PROPERTY(ParamList params READ params WRITE setParams)
|
||||
Q_PROPERTY(ParamList settings READ settings WRITE setSettings)
|
||||
Q_PROPERTY(States states READ states WRITE setStates)
|
||||
Q_PROPERTY(bool setupComplete READ setupComplete WRITE setSetupComplete)
|
||||
Q_PROPERTY(QUuid parentId READ parentId WRITE setParentId USER true)
|
||||
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged USER true)
|
||||
Q_PROPERTY(ParamList params READ params)
|
||||
Q_PROPERTY(ParamList settings READ settings WRITE setSettings USER true)
|
||||
Q_PROPERTY(States states READ states)
|
||||
Q_PROPERTY(bool setupComplete READ setupComplete NOTIFY setupStatusChanged REVISION 1)
|
||||
Q_PROPERTY(DeviceSetupStatus setupStatus READ setupStatus NOTIFY setupStatusChanged)
|
||||
Q_PROPERTY(QString setupDisplayMessage READ setupDisplayMessage NOTIFY setupStatusChanged USER true)
|
||||
Q_PROPERTY(DeviceError setupError READ setupError NOTIFY setupStatusChanged)
|
||||
Q_PROPERTY(QUuid parentId READ parentId USER true)
|
||||
|
||||
public:
|
||||
enum DeviceError {
|
||||
@ -89,6 +92,14 @@ public:
|
||||
};
|
||||
Q_ENUM(DeviceError)
|
||||
|
||||
enum DeviceSetupStatus {
|
||||
DeviceSetupStatusNone,
|
||||
DeviceSetupStatusInProgress,
|
||||
DeviceSetupStatusComplete,
|
||||
DeviceSetupStatusFailed,
|
||||
};
|
||||
Q_ENUM(DeviceSetupStatus)
|
||||
|
||||
DeviceId id() const;
|
||||
DeviceClassId deviceClassId() const;
|
||||
PluginId pluginId() const;
|
||||
@ -125,13 +136,19 @@ public:
|
||||
DeviceId parentId() const;
|
||||
void setParentId(const DeviceId &parentId);
|
||||
|
||||
// Deprecated
|
||||
bool setupComplete() const;
|
||||
bool autoCreated() const;
|
||||
|
||||
DeviceSetupStatus setupStatus() const;
|
||||
DeviceError setupError() const;
|
||||
QString setupDisplayMessage() const;
|
||||
|
||||
signals:
|
||||
void stateValueChanged(const StateTypeId &stateTypeId, const QVariant &value);
|
||||
void settingChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
void nameChanged();
|
||||
void setupStatusChanged();
|
||||
|
||||
private:
|
||||
friend class DeviceManager;
|
||||
@ -139,8 +156,7 @@ private:
|
||||
Device(DevicePlugin *plugin, const DeviceClass &deviceClass, const DeviceId &id, QObject *parent = nullptr);
|
||||
Device(DevicePlugin *plugin, const DeviceClass &deviceClass, QObject *parent = nullptr);
|
||||
|
||||
void setupCompleted();
|
||||
void setSetupComplete(bool complete);
|
||||
void setSetupStatus(Device::DeviceSetupStatus status, Device::DeviceError setupError, const QString &displayMessage = QString());
|
||||
|
||||
private:
|
||||
DeviceClass m_deviceClass;
|
||||
@ -152,8 +168,11 @@ private:
|
||||
ParamList m_params;
|
||||
ParamList m_settings;
|
||||
States m_states;
|
||||
bool m_setupComplete = false;
|
||||
bool m_autoCreated = false;
|
||||
|
||||
DeviceSetupStatus m_setupStatus = DeviceSetupStatusNone;
|
||||
DeviceError m_setupError = DeviceErrorNoError;
|
||||
QString m_setupDisplayMessage;
|
||||
};
|
||||
|
||||
QDebug operator<<(QDebug dbg, Device *device);
|
||||
|
||||
@ -41,6 +41,13 @@ JsonHandler::JsonHandler(QObject *parent) : QObject(parent)
|
||||
registerEnum<BasicType>();
|
||||
}
|
||||
|
||||
QVariantMap JsonHandler::translateNotification(const QString ¬ification, const QVariantMap ¶ms, const QLocale &locale)
|
||||
{
|
||||
Q_UNUSED(notification)
|
||||
Q_UNUSED(locale)
|
||||
return params;
|
||||
}
|
||||
|
||||
QVariantMap JsonHandler::jsonEnums() const
|
||||
{
|
||||
return m_enums;
|
||||
@ -186,6 +193,9 @@ void JsonHandler::registerObject(const QMetaObject &metaObject)
|
||||
if (!metaProperty.isWritable()) {
|
||||
name.prepend("r:");
|
||||
}
|
||||
if (metaProperty.revision() == 1) {
|
||||
name.prepend("d:");
|
||||
}
|
||||
QVariant typeName;
|
||||
if (metaProperty.type() == QVariant::UserType) {
|
||||
if (metaProperty.typeName() == QStringLiteral("QVariant::Type")) {
|
||||
|
||||
@ -65,6 +65,8 @@ public:
|
||||
|
||||
virtual QString name() const = 0;
|
||||
|
||||
virtual QVariantMap translateNotification(const QString ¬ification, const QVariantMap ¶ms, const QLocale &locale);
|
||||
|
||||
QVariantMap jsonEnums() const;
|
||||
QVariantMap jsonFlags() const;
|
||||
QVariantMap jsonObjects() const;
|
||||
|
||||
@ -76,6 +76,12 @@
|
||||
"DeviceErrorUnsupportedFeature",
|
||||
"DeviceErrorTimeout"
|
||||
],
|
||||
"DeviceSetupStatus": [
|
||||
"DeviceSetupStatusNone",
|
||||
"DeviceSetupStatusInProgress",
|
||||
"DeviceSetupStatusComplete",
|
||||
"DeviceSetupStatusFailed"
|
||||
],
|
||||
"InputType": [
|
||||
"InputTypeNone",
|
||||
"InputTypeTextLine",
|
||||
@ -1609,7 +1615,7 @@
|
||||
}
|
||||
},
|
||||
"Devices.DeviceChanged": {
|
||||
"description": "Emitted whenever the params or name of a Device are changed (by EditDevice or ReconfigureDevice).",
|
||||
"description": "Emitted whenever the params, name or setupStatus of a Device changes.",
|
||||
"params": {
|
||||
"device": "$ref:Device"
|
||||
}
|
||||
@ -1904,14 +1910,17 @@
|
||||
"$ref:CalendarItem"
|
||||
],
|
||||
"Device": {
|
||||
"name": "String",
|
||||
"o:parentId": "Uuid",
|
||||
"params": "$ref:ParamList",
|
||||
"d:r:setupComplete": "Bool",
|
||||
"o:name": "String",
|
||||
"o:settings": "$ref:ParamList",
|
||||
"r:deviceClassId": "Uuid",
|
||||
"r:id": "Uuid",
|
||||
"settings": "$ref:ParamList",
|
||||
"setupComplete": "Bool",
|
||||
"states": "$ref:States"
|
||||
"r:o:parentId": "Uuid",
|
||||
"r:o:setupDisplayMessage": "String",
|
||||
"r:params": "$ref:ParamList",
|
||||
"r:setupError": "$ref:DeviceError",
|
||||
"r:setupStatus": "$ref:DeviceSetupStatus",
|
||||
"r:states": "$ref:States"
|
||||
},
|
||||
"DeviceClass": {
|
||||
"r:actionTypes": "$ref:ActionTypes",
|
||||
|
||||
@ -136,6 +136,8 @@ private slots:
|
||||
|
||||
void params();
|
||||
|
||||
void asyncSetupEmitsSetupStatusUpdate();
|
||||
|
||||
// Keep those at last as they will remove devices
|
||||
void removeDevice_data();
|
||||
void removeDevice();
|
||||
@ -1971,6 +1973,55 @@ void TestDevices::params()
|
||||
QVERIFY(!event.param(ParamTypeId::createParamTypeId()).value().isValid());
|
||||
}
|
||||
|
||||
void TestDevices::asyncSetupEmitsSetupStatusUpdate()
|
||||
{
|
||||
QVariantMap configuredDevices = injectAndWait("Devices.GetConfiguredDevices").toMap();
|
||||
foreach (const QVariant &deviceVariant, configuredDevices.value("params").toMap().value("devices").toList()) {
|
||||
QVariantMap device = deviceVariant.toMap();
|
||||
qCDebug(dcTests()) << "confdiguredd device" << device.value("setupStatus");
|
||||
}
|
||||
|
||||
// Restart the core instance to check if settings are loaded at startup
|
||||
restartServer();
|
||||
enableNotifications({"Devices"});
|
||||
|
||||
QSignalSpy notificationSpy(m_mockTcpServer, SIGNAL(outgoingData(QUuid,QByteArray)));
|
||||
|
||||
configuredDevices = injectAndWait("Devices.GetConfiguredDevices").toMap();
|
||||
QList<QUuid> devicesWithSetupInProgress;
|
||||
foreach (const QVariant &deviceVariant, configuredDevices.value("params").toMap().value("devices").toList()) {
|
||||
QVariantMap device = deviceVariant.toMap();
|
||||
qCDebug(dcTests()) << "Configured device" << device.value("name").toString() << "with setup status" << device.value("setupStatus").toString();
|
||||
if (device.value("setupStatus").toString() == "DeviceSetupStatusInProgress") {
|
||||
devicesWithSetupInProgress << device.value("id").toUuid();
|
||||
}
|
||||
}
|
||||
QVERIFY2(devicesWithSetupInProgress.count() > 0, "This test requires at least one device that is still being set up at this point.");
|
||||
|
||||
QDateTime maxTime = QDateTime::currentDateTime().addSecs(10);
|
||||
while (QDateTime::currentDateTime() < maxTime && devicesWithSetupInProgress.count() > 0) {
|
||||
QList<QList<QVariant>> notifications = notificationSpy;
|
||||
while (notifications.count() > 0) {
|
||||
QByteArray notificationData = notifications.takeFirst().at(1).toByteArray();
|
||||
QVariantMap notification = QJsonDocument::fromJson(notificationData).toVariant().toMap();
|
||||
if (notification.value("notification").toString() == "Devices.DeviceChanged") {
|
||||
QString setupStatus = notification.value("params").toMap().value("device").toMap().value("setupStatus").toString();
|
||||
if (setupStatus == "DeviceSetupStatusComplete") {
|
||||
qCDebug(dcTests()) << "Device setup completed for" << notification.value("params").toMap().value("device").toMap().value("name").toString();
|
||||
DeviceId deviceId = notification.value("params").toMap().value("device").toMap().value("id").toUuid();
|
||||
devicesWithSetupInProgress.removeAll(deviceId);
|
||||
}
|
||||
}
|
||||
}
|
||||
notificationSpy.clear();
|
||||
if (devicesWithSetupInProgress.count() > 0) {
|
||||
notificationSpy.wait();
|
||||
}
|
||||
}
|
||||
|
||||
QVERIFY2(devicesWithSetupInProgress.isEmpty(), "Some devices did not finish the setup!");
|
||||
}
|
||||
|
||||
#include "testdevices.moc"
|
||||
QTEST_MAIN(TestDevices)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user