Merge PR #396: Don't call thingRemoved() when a thing didn't complete the setup
This commit is contained in:
commit
a81b484635
@ -454,6 +454,10 @@ ThingSetupInfo *ThingManagerImplementation::reconfigureThingInternal(Thing *thin
|
|||||||
// try to setup the thing with the new params
|
// try to setup the thing with the new params
|
||||||
ThingSetupInfo *info = new ThingSetupInfo(thing, this, 30000);
|
ThingSetupInfo *info = new ThingSetupInfo(thing, this, 30000);
|
||||||
plugin->setupThing(info);
|
plugin->setupThing(info);
|
||||||
|
connect(info, &ThingSetupInfo::destroyed, thing, [=](){
|
||||||
|
m_pendingSetups.remove(thing->id());
|
||||||
|
});
|
||||||
|
|
||||||
connect(info, &ThingSetupInfo::finished, this, [this, info](){
|
connect(info, &ThingSetupInfo::finished, this, [this, info](){
|
||||||
|
|
||||||
if (info->status() != Thing::ThingErrorNoError) {
|
if (info->status() != Thing::ThingErrorNoError) {
|
||||||
@ -824,6 +828,11 @@ ThingSetupInfo* ThingManagerImplementation::addConfiguredThingInternal(const Thi
|
|||||||
|
|
||||||
Thing::ThingError ThingManagerImplementation::removeConfiguredThing(const ThingId &thingId)
|
Thing::ThingError ThingManagerImplementation::removeConfiguredThing(const ThingId &thingId)
|
||||||
{
|
{
|
||||||
|
// We're checking thingSetupStatus and abort any pending setup here. As setup finished()
|
||||||
|
// comes in as a QueuedConnection, make sure to process all events before going on so we
|
||||||
|
// don't end up aborting an already finished setup instead of calling thingRemoved() on it.
|
||||||
|
qApp->processEvents();
|
||||||
|
|
||||||
Thing *thing = m_configuredThings.take(thingId);
|
Thing *thing = m_configuredThings.take(thingId);
|
||||||
if (!thing) {
|
if (!thing) {
|
||||||
return Thing::ThingErrorThingNotFound;
|
return Thing::ThingErrorThingNotFound;
|
||||||
@ -831,7 +840,11 @@ Thing::ThingError ThingManagerImplementation::removeConfiguredThing(const ThingI
|
|||||||
IntegrationPlugin *plugin = m_integrationPlugins.value(thing->pluginId());
|
IntegrationPlugin *plugin = m_integrationPlugins.value(thing->pluginId());
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
qCWarning(dcThingManager()).nospace() << "Plugin not loaded for thing " << thing->name() << ". Not calling thingRemoved on plugin.";
|
qCWarning(dcThingManager()).nospace() << "Plugin not loaded for thing " << thing->name() << ". Not calling thingRemoved on plugin.";
|
||||||
} else {
|
} else if (thing->setupStatus() == Thing::ThingSetupStatusInProgress) {
|
||||||
|
qCWarning(dcThingManager()).nospace() << "Thing " << thing->name() << " is still being set up. Aborting setup.";
|
||||||
|
ThingSetupInfo *setupInfo = m_pendingSetups.value(thingId);
|
||||||
|
emit setupInfo->aborted();
|
||||||
|
} else if (thing->setupStatus() == Thing::ThingSetupStatusComplete) {
|
||||||
plugin->thingRemoved(thing);
|
plugin->thingRemoved(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2070,6 +2083,11 @@ ThingSetupInfo* ThingManagerImplementation::setupThing(Thing *thing)
|
|||||||
|
|
||||||
plugin->setupThing(info);
|
plugin->setupThing(info);
|
||||||
|
|
||||||
|
m_pendingSetups.insert(thing->id(), info);
|
||||||
|
connect(info, &ThingSetupInfo::destroyed, thing, [=](){
|
||||||
|
m_pendingSetups.remove(thing->id());
|
||||||
|
});
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -194,6 +194,7 @@ private:
|
|||||||
QString thingName;
|
QString thingName;
|
||||||
};
|
};
|
||||||
QHash<PairingTransactionId, PairingContext> m_pendingPairings;
|
QHash<PairingTransactionId, PairingContext> m_pendingPairings;
|
||||||
|
QHash<ThingId, ThingSetupInfo*> m_pendingSetups;
|
||||||
|
|
||||||
QHash<IOConnectionId, IOConnection> m_ioConnections;
|
QHash<IOConnectionId, IOConnection> m_ioConnections;
|
||||||
|
|
||||||
|
|||||||
@ -134,7 +134,7 @@ void IntegrationPluginMock::setupThing(ThingSetupInfo *info)
|
|||||||
{
|
{
|
||||||
if (info->thing()->thingClassId() == mockThingClassId || info->thing()->thingClassId() == autoMockThingClassId) {
|
if (info->thing()->thingClassId() == mockThingClassId || info->thing()->thingClassId() == autoMockThingClassId) {
|
||||||
if (m_daemons.contains(info->thing())) {
|
if (m_daemons.contains(info->thing())) {
|
||||||
// We already have a daemon, seem's we're reconfiguring
|
// We already have a daemon, seems we're reconfiguring
|
||||||
delete m_daemons.take(info->thing());
|
delete m_daemons.take(info->thing());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,8 +174,7 @@ void IntegrationPluginMock::setupThing(ThingSetupInfo *info)
|
|||||||
|
|
||||||
|
|
||||||
if (async) {
|
if (async) {
|
||||||
Thing *device = info->thing();
|
QTimer::singleShot(1000, info, [info](){
|
||||||
QTimer::singleShot(1000, device, [info](){
|
|
||||||
qCDebug(dcMock()) << "Finishing thing setup for mocked thing" << info->thing()->name();
|
qCDebug(dcMock()) << "Finishing thing setup for mocked thing" << info->thing()->name();
|
||||||
if (info->thing()->paramValue(mockThingBrokenParamTypeId).toBool()) {
|
if (info->thing()->paramValue(mockThingBrokenParamTypeId).toBool()) {
|
||||||
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("This mocked thing is intentionally broken."));
|
info->finish(Thing::ThingErrorSetupFailed, QT_TR_NOOP("This mocked thing is intentionally broken."));
|
||||||
@ -183,6 +182,12 @@ void IntegrationPluginMock::setupThing(ThingSetupInfo *info)
|
|||||||
info->finish(Thing::ThingErrorNoError);
|
info->finish(Thing::ThingErrorNoError);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(info, &ThingSetupInfo::aborted, this, [=](){
|
||||||
|
qCDebug(dcMock()) << "Setup aborted. Destroying webserver" << info->thing()->name();
|
||||||
|
delete m_daemons.take(info->thing());
|
||||||
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qCDebug(dcMock()) << "Setup complete" << info->thing()->name();
|
qCDebug(dcMock()) << "Setup complete" << info->thing()->name();
|
||||||
@ -260,24 +265,25 @@ void IntegrationPluginMock::setupThing(ThingSetupInfo *info)
|
|||||||
info->finish(Thing::ThingErrorThingClassNotFound);
|
info->finish(Thing::ThingErrorThingClassNotFound);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginMock::postSetupThing(Thing *device)
|
void IntegrationPluginMock::postSetupThing(Thing *thing)
|
||||||
{
|
{
|
||||||
qCDebug(dcMock()) << "Postsetup mock" << device->name();
|
qCDebug(dcMock()) << "Postsetup mock" << thing->name();
|
||||||
if (device->thingClassId() == parentMockThingClassId) {
|
if (thing->thingClassId() == parentMockThingClassId) {
|
||||||
foreach (Thing *d, myThings()) {
|
foreach (Thing *d, myThings()) {
|
||||||
if (d->thingClassId() == childMockThingClassId && d->parentId() == device->id()) {
|
if (d->thingClassId() == childMockThingClassId && d->parentId() == thing->id()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ThingDescriptor mockDescriptor(childMockThingClassId, "Mocked Thing Child (Auto created)", "Mocked Thing Child (Auto created)", device->id());
|
ThingDescriptor mockDescriptor(childMockThingClassId, "Mocked Thing Child (Auto created)", "Mocked Thing Child (Auto created)", thing->id());
|
||||||
emit autoThingsAppeared(ThingDescriptors() << mockDescriptor);
|
emit autoThingsAppeared(ThingDescriptors() << mockDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginMock::thingRemoved(Thing *device)
|
void IntegrationPluginMock::thingRemoved(Thing *thing)
|
||||||
{
|
{
|
||||||
delete m_daemons.take(device);
|
qCDebug(dcMock()) << "Thing removed" << thing->name();
|
||||||
|
delete m_daemons.take(thing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IntegrationPluginMock::startMonitoringAutoThings()
|
void IntegrationPluginMock::startMonitoringAutoThings()
|
||||||
|
|||||||
@ -51,8 +51,8 @@ public:
|
|||||||
void discoverThings(ThingDiscoveryInfo *info) override;
|
void discoverThings(ThingDiscoveryInfo *info) override;
|
||||||
|
|
||||||
void setupThing(ThingSetupInfo *info) override;
|
void setupThing(ThingSetupInfo *info) override;
|
||||||
void postSetupThing(Thing *device) override;
|
void postSetupThing(Thing *thing) override;
|
||||||
void thingRemoved(Thing *device) override;
|
void thingRemoved(Thing *thing) override;
|
||||||
|
|
||||||
void startMonitoringAutoThings() override;
|
void startMonitoringAutoThings() override;
|
||||||
|
|
||||||
|
|||||||
@ -160,7 +160,7 @@ void TestDevices::initTestCase()
|
|||||||
NymeaTestBase::initTestCase();
|
NymeaTestBase::initTestCase();
|
||||||
QLoggingCategory::setFilterRules("*.debug=false\n"
|
QLoggingCategory::setFilterRules("*.debug=false\n"
|
||||||
"Tests.debug=true\n"
|
"Tests.debug=true\n"
|
||||||
"MockDevice.debug=true\n"
|
"Mock.debug=true\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
// Adding an async mock device to be used in tests below
|
// Adding an async mock device to be used in tests below
|
||||||
@ -619,6 +619,7 @@ void TestDevices::storedDevices()
|
|||||||
|
|
||||||
params.clear();
|
params.clear();
|
||||||
params.insert("deviceId", addedDeviceId);
|
params.insert("deviceId", addedDeviceId);
|
||||||
|
qCDebug(dcTests()) << "Cleaning up mock device again";
|
||||||
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
response = injectAndWait("Devices.RemoveConfiguredDevice", params);
|
||||||
verifyDeviceError(response);
|
verifyDeviceError(response);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user