prevent auto devices from being manually removed, allow plugins to remove them again
This commit is contained in:
parent
6a9759eb62
commit
3b42d16777
@ -146,10 +146,15 @@ QPair<DeviceManager::DeviceError, QList<RuleId> > GuhCore::removeConfiguredDevic
|
||||
return QPair<DeviceManager::DeviceError, QList<RuleId> > (DeviceManager::DeviceErrorDeviceIsChild, QList<RuleId>());
|
||||
}
|
||||
|
||||
if (device->autoCreated()) {
|
||||
qCWarning(dcDeviceManager) << "This device has been auto-created and cannot be deleted manually.";
|
||||
return QPair<DeviceManager::DeviceError, QList<RuleId> >(DeviceManager::DeviceErrorCreationMethodNotSupported, {});
|
||||
}
|
||||
|
||||
// Check if this device has child devices
|
||||
QList<Device *> devicesToRemove;
|
||||
devicesToRemove.append(device);
|
||||
QList<Device *> childDevices = m_deviceManager->findChildDevices(device);
|
||||
QList<Device *> childDevices = m_deviceManager->findChildDevices(deviceId);
|
||||
if (!childDevices.isEmpty()) {
|
||||
foreach (Device *child, childDevices) {
|
||||
devicesToRemove.append(child);
|
||||
@ -236,10 +241,15 @@ DeviceManager::DeviceError GuhCore::removeConfiguredDevice(const DeviceId &devic
|
||||
return DeviceManager::DeviceErrorDeviceIsChild;
|
||||
}
|
||||
|
||||
if (device->autoCreated()) {
|
||||
qCWarning(dcDeviceManager) << "This device has been auto-created and cannot be deleted manually.";
|
||||
return DeviceManager::DeviceErrorCreationMethodNotSupported;
|
||||
}
|
||||
|
||||
// Check if this device has child devices
|
||||
QList<Device *> devicesToRemove;
|
||||
devicesToRemove.append(device);
|
||||
QList<Device *> childDevices = m_deviceManager->findChildDevices(device);
|
||||
QList<Device *> childDevices = m_deviceManager->findChildDevices(deviceId);
|
||||
if (!childDevices.isEmpty()) {
|
||||
foreach (Device *child, childDevices) {
|
||||
devicesToRemove.append(child);
|
||||
@ -437,6 +447,7 @@ void GuhCore::init() {
|
||||
connect(m_deviceManager, &DeviceManager::deviceAdded, this, &GuhCore::deviceAdded);
|
||||
connect(m_deviceManager, &DeviceManager::deviceChanged, this, &GuhCore::deviceChanged);
|
||||
connect(m_deviceManager, &DeviceManager::deviceRemoved, this, &GuhCore::deviceRemoved);
|
||||
connect(m_deviceManager, &DeviceManager::deviceDisappeared, this, &GuhCore::onDeviceDisappeared);
|
||||
connect(m_deviceManager, &DeviceManager::actionExecutionFinished, this, &GuhCore::actionExecutionFinished);
|
||||
connect(m_deviceManager, &DeviceManager::devicesDiscovered, this, &GuhCore::devicesDiscovered);
|
||||
connect(m_deviceManager, &DeviceManager::deviceSetupFinished, this, &GuhCore::deviceSetupFinished);
|
||||
@ -566,4 +577,58 @@ void GuhCore::actionExecutionFinished(const ActionId &id, DeviceManager::DeviceE
|
||||
m_logger->logAction(action, status == DeviceManager::DeviceErrorNoError ? Logging::LoggingLevelInfo : Logging::LoggingLevelAlert, status);
|
||||
}
|
||||
|
||||
void GuhCore::onDeviceDisappeared(const DeviceId &deviceId)
|
||||
{
|
||||
Device *device = m_deviceManager->findConfiguredDevice(deviceId);
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if this device has child devices
|
||||
QList<Device *> devicesToRemove;
|
||||
devicesToRemove.append(device);
|
||||
QList<Device *> childDevices = m_deviceManager->findChildDevices(deviceId);
|
||||
if (!childDevices.isEmpty()) {
|
||||
foreach (Device *child, childDevices) {
|
||||
devicesToRemove.append(child);
|
||||
}
|
||||
}
|
||||
|
||||
// check devices
|
||||
QList<RuleId> offendingRules;
|
||||
qCDebug(dcDeviceManager) << "Devices to remove:";
|
||||
foreach (Device *d, devicesToRemove) {
|
||||
qCDebug(dcDeviceManager) << " -> " << d->name() << d->id().toString();
|
||||
|
||||
// Check if device is in a rule
|
||||
foreach (const RuleId &ruleId, m_ruleEngine->findRules(d->id())) {
|
||||
qCDebug(dcDeviceManager) << " -> in rule:" << ruleId.toString();
|
||||
if (!offendingRules.contains(ruleId)) {
|
||||
offendingRules.append(ruleId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update involved rules
|
||||
foreach (const RuleId &ruleId, offendingRules) {
|
||||
foreach (Device *d, devicesToRemove) {
|
||||
m_ruleEngine->removeDeviceFromRule(ruleId, d->id());
|
||||
}
|
||||
}
|
||||
|
||||
// remove the child devices
|
||||
foreach (Device *d, childDevices) {
|
||||
DeviceManager::DeviceError removeError = m_deviceManager->removeConfiguredDevice(d->id());
|
||||
if (removeError == DeviceManager::DeviceErrorNoError) {
|
||||
m_logger->removeDeviceLogs(d->id());
|
||||
}
|
||||
}
|
||||
|
||||
// delete the device
|
||||
DeviceManager::DeviceError removeError = m_deviceManager->removeConfiguredDevice(deviceId);
|
||||
if (removeError == DeviceManager::DeviceErrorNoError) {
|
||||
m_logger->removeDeviceLogs(deviceId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -122,6 +122,7 @@ private slots:
|
||||
void onDateTimeChanged(const QDateTime &dateTime);
|
||||
void onLocaleChanged();
|
||||
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status);
|
||||
void onDeviceDisappeared(const DeviceId &deviceId);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -741,7 +741,7 @@ DeviceManager::DeviceError DeviceManager::addConfiguredDeviceInternal(const Devi
|
||||
break;
|
||||
}
|
||||
|
||||
m_configuredDevices.append(device);
|
||||
m_configuredDevices.insert(device->id(), device);
|
||||
storeConfiguredDevices();
|
||||
postSetupDevice(device);
|
||||
|
||||
@ -755,12 +755,10 @@ DeviceManager::DeviceError DeviceManager::addConfiguredDeviceInternal(const Devi
|
||||
* Returns \l{DeviceError} to inform about the result. */
|
||||
DeviceManager::DeviceError DeviceManager::removeConfiguredDevice(const DeviceId &deviceId)
|
||||
{
|
||||
Device *device = findConfiguredDevice(deviceId);
|
||||
Device *device = m_configuredDevices.take(deviceId);
|
||||
if (!device) {
|
||||
return DeviceErrorDeviceNotFound;
|
||||
}
|
||||
|
||||
m_configuredDevices.removeAll(device);
|
||||
m_devicePlugins.value(device->pluginId())->deviceRemoved(device);
|
||||
|
||||
// check if this plugin still needs the guhTimer call
|
||||
@ -806,7 +804,7 @@ Device *DeviceManager::findConfiguredDevice(const DeviceId &id) const
|
||||
/*! Returns all configured \{Device}{Devices} in the system. */
|
||||
QList<Device *> DeviceManager::configuredDevices() const
|
||||
{
|
||||
return m_configuredDevices;
|
||||
return m_configuredDevices.values();
|
||||
}
|
||||
|
||||
/*! Returns all \l{Device}{Devices} matching the \l{DeviceClass} referred by \a deviceClassId. */
|
||||
@ -822,11 +820,11 @@ QList<Device *> DeviceManager::findConfiguredDevices(const DeviceClassId &device
|
||||
}
|
||||
|
||||
/*! Returns all child \l{Device}{Devices} of the given \a device. */
|
||||
QList<Device *> DeviceManager::findChildDevices(Device *device) const
|
||||
QList<Device *> DeviceManager::findChildDevices(const DeviceId &id) const
|
||||
{
|
||||
QList<Device *> ret;
|
||||
foreach (Device *d, m_configuredDevices) {
|
||||
if (d->parentId() == device->id()) {
|
||||
if (d->parentId() == id) {
|
||||
ret.append(d);
|
||||
}
|
||||
}
|
||||
@ -1101,7 +1099,8 @@ void DeviceManager::loadPlugins()
|
||||
connect(pluginIface, &DevicePlugin::deviceSetupFinished, this, &DeviceManager::slotDeviceSetupFinished);
|
||||
connect(pluginIface, &DevicePlugin::actionExecutionFinished, this, &DeviceManager::actionExecutionFinished);
|
||||
connect(pluginIface, &DevicePlugin::pairingFinished, this, &DeviceManager::slotPairingFinished);
|
||||
connect(pluginIface, &DevicePlugin::autoDevicesAppeared, this, &DeviceManager::autoDevicesAppeared);
|
||||
connect(pluginIface, &DevicePlugin::autoDevicesAppeared, this, &DeviceManager::onAutoDevicesAppeared);
|
||||
connect(pluginIface, &DevicePlugin::autoDeviceDisappeared, this, &DeviceManager::onAutoDeviceDisappeared);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1114,6 +1113,7 @@ void DeviceManager::loadConfiguredDevices()
|
||||
foreach (const QString &idString, settings.childGroups()) {
|
||||
settings.beginGroup(idString);
|
||||
Device *device = new Device(PluginId(settings.value("pluginid").toString()), DeviceId(idString), DeviceClassId(settings.value("deviceClassId").toString()), this);
|
||||
device->m_autoCreated = settings.value("autoCreated").toBool();
|
||||
device->setName(settings.value("devicename").toString());
|
||||
device->setParentId(DeviceId(settings.value("parentid", QUuid()).toString()));
|
||||
|
||||
@ -1130,7 +1130,7 @@ void DeviceManager::loadConfiguredDevices()
|
||||
// it means that it was working at some point so lets still add it as there might
|
||||
// be rules associated with this device. Device::setupCompleted() will be false.
|
||||
DeviceSetupStatus status = setupDevice(device);
|
||||
m_configuredDevices.append(device);
|
||||
m_configuredDevices.insert(device->id(), device);
|
||||
|
||||
if (status == DeviceSetupStatus::DeviceSetupStatusSuccess)
|
||||
postSetupDevice(device);
|
||||
@ -1144,6 +1144,7 @@ void DeviceManager::storeConfiguredDevices()
|
||||
settings.beginGroup("DeviceConfig");
|
||||
foreach (Device *device, m_configuredDevices) {
|
||||
settings.beginGroup(device->id().toString());
|
||||
settings.setValue("autoCreated", device->autoCreated());
|
||||
settings.setValue("devicename", device->name());
|
||||
settings.setValue("deviceClassId", device->deviceClassId().toString());
|
||||
settings.setValue("pluginid", device->pluginId().toString());
|
||||
@ -1202,7 +1203,7 @@ void DeviceManager::slotDeviceSetupFinished(Device *device, DeviceManager::Devic
|
||||
}
|
||||
|
||||
if (status == DeviceSetupStatusFailure) {
|
||||
if (m_configuredDevices.contains(device)) {
|
||||
if (m_configuredDevices.contains(device->id())) {
|
||||
if (m_asyncDeviceReconfiguration.contains(device)) {
|
||||
m_asyncDeviceReconfiguration.removeAll(device);
|
||||
qCWarning(dcDeviceManager) << QString("Error in device setup after reconfiguration. Device %1 (%2) will not be functional.").arg(device->name()).arg(device->id().toString());
|
||||
@ -1226,8 +1227,8 @@ void DeviceManager::slotDeviceSetupFinished(Device *device, DeviceManager::Devic
|
||||
|
||||
// A device might be in here already if loaded from storedDevices. If it's not in the configuredDevices,
|
||||
// lets add it now.
|
||||
if (!m_configuredDevices.contains(device)) {
|
||||
m_configuredDevices.append(device);
|
||||
if (!m_configuredDevices.contains(device->id())) {
|
||||
m_configuredDevices.insert(device->id(), device);
|
||||
emit deviceAdded(device);
|
||||
storeConfiguredDevices();
|
||||
}
|
||||
@ -1335,14 +1336,14 @@ void DeviceManager::slotPairingFinished(const PairingTransactionId &pairingTrans
|
||||
break;
|
||||
}
|
||||
|
||||
m_configuredDevices.append(device);
|
||||
m_configuredDevices.insert(device->id(), device);
|
||||
emit deviceAdded(device);
|
||||
storeConfiguredDevices();
|
||||
emit deviceSetupFinished(device, DeviceError::DeviceErrorNoError);
|
||||
postSetupDevice(device);
|
||||
}
|
||||
|
||||
void DeviceManager::autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors)
|
||||
void DeviceManager::onAutoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors)
|
||||
{
|
||||
DeviceClass deviceClass = findDeviceClass(deviceClassId);
|
||||
if (!deviceClass.isValid()) {
|
||||
@ -1356,6 +1357,7 @@ void DeviceManager::autoDevicesAppeared(const DeviceClassId &deviceClassId, cons
|
||||
|
||||
foreach (const DeviceDescriptor &deviceDescriptor, deviceDescriptors) {
|
||||
Device *device = new Device(plugin->pluginId(), deviceClassId, this);
|
||||
device->m_autoCreated = true;
|
||||
device->setName(deviceClass.name());
|
||||
device->setParams(deviceDescriptor.params());
|
||||
|
||||
@ -1370,7 +1372,7 @@ void DeviceManager::autoDevicesAppeared(const DeviceClassId &deviceClassId, cons
|
||||
break;
|
||||
case DeviceSetupStatusSuccess:
|
||||
qCDebug(dcDeviceManager) << "Device setup complete.";
|
||||
m_configuredDevices.append(device);
|
||||
m_configuredDevices.insert(device->id(), device);
|
||||
storeConfiguredDevices();
|
||||
emit deviceSetupFinished(device, DeviceError::DeviceErrorNoError);
|
||||
emit deviceAdded(device);
|
||||
@ -1380,6 +1382,31 @@ void DeviceManager::autoDevicesAppeared(const DeviceClassId &deviceClassId, cons
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::onAutoDeviceDisappeared(const DeviceId &deviceId)
|
||||
{
|
||||
DevicePlugin *plugin = static_cast<DevicePlugin*>(sender());
|
||||
Device *device = m_configuredDevices.value(deviceId);
|
||||
|
||||
if (!device) {
|
||||
qWarning(dcDeviceManager) << "Received an autoDeviceDisappeared signal but don't know this device:" << deviceId;
|
||||
return;
|
||||
}
|
||||
|
||||
DeviceClass deviceClass = m_supportedDevices.value(device->deviceClassId());
|
||||
|
||||
if (deviceClass.pluginId() != plugin->pluginId()) {
|
||||
qWarning(dcDeviceManager) << "Received a autoDeviceDisappeared signal but emitting plugin does not own the device";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!device->autoCreated()) {
|
||||
qWarning(dcDeviceManager) << "Received an autoDeviceDisappeared signal but device creationMethod is not CreateMothodAuto";
|
||||
return;
|
||||
}
|
||||
|
||||
emit deviceDisappeared(deviceId);
|
||||
}
|
||||
|
||||
void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value)
|
||||
{
|
||||
Device *device = qobject_cast<Device*>(sender());
|
||||
|
||||
@ -138,7 +138,7 @@ public:
|
||||
|
||||
Device* findConfiguredDevice(const DeviceId &id) const;
|
||||
QList<Device *> findConfiguredDevices(const DeviceClassId &deviceClassId) const;
|
||||
QList<Device *> findChildDevices(Device *device) const;
|
||||
QList<Device *> findChildDevices(const DeviceId &id) const;
|
||||
DeviceClass findDeviceClass(const DeviceClassId &deviceClassId) const;
|
||||
|
||||
DeviceError verifyParams(const QList<ParamType> paramTypes, ParamList ¶ms, bool requireAll = true);
|
||||
@ -152,6 +152,7 @@ signals:
|
||||
void eventTriggered(const Event &event);
|
||||
void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value);
|
||||
void deviceRemoved(const DeviceId &deviceId);
|
||||
void deviceDisappeared(const DeviceId &deviceId);
|
||||
void deviceAdded(Device *device);
|
||||
void deviceChanged(Device *device);
|
||||
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &devices);
|
||||
@ -172,7 +173,8 @@ private slots:
|
||||
void slotDevicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
|
||||
void slotDeviceSetupFinished(Device *device, DeviceManager::DeviceSetupStatus status);
|
||||
void slotPairingFinished(const PairingTransactionId &pairingTransactionId, DeviceManager::DeviceSetupStatus status);
|
||||
void autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
|
||||
void onAutoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
|
||||
void onAutoDeviceDisappeared(const DeviceId &deviceId);
|
||||
|
||||
// Only connect this to Devices. It will query the sender()
|
||||
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
|
||||
@ -200,7 +202,7 @@ private:
|
||||
QHash<VendorId, Vendor> m_supportedVendors;
|
||||
QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap;
|
||||
QHash<DeviceClassId, DeviceClass> m_supportedDevices;
|
||||
QList<Device *> m_configuredDevices;
|
||||
QHash<DeviceId, Device*> m_configuredDevices;
|
||||
QHash<DeviceDescriptorId, DeviceDescriptor> m_discoveredDevices;
|
||||
|
||||
QHash<PluginId, DevicePlugin*> m_devicePlugins;
|
||||
|
||||
@ -50,8 +50,7 @@ Device::Device(const PluginId &pluginId, const DeviceId &id, const DeviceClassId
|
||||
QObject(parent),
|
||||
m_id(id),
|
||||
m_deviceClassId(deviceClassId),
|
||||
m_pluginId(pluginId),
|
||||
m_setupComplete(false)
|
||||
m_pluginId(pluginId)
|
||||
{
|
||||
|
||||
}
|
||||
@ -61,8 +60,7 @@ Device::Device(const PluginId &pluginId, const DeviceClassId &deviceClassId, QOb
|
||||
QObject(parent),
|
||||
m_id(DeviceId::createDeviceId()),
|
||||
m_deviceClassId(deviceClassId),
|
||||
m_pluginId(pluginId),
|
||||
m_setupComplete(false)
|
||||
m_pluginId(pluginId)
|
||||
{
|
||||
|
||||
}
|
||||
@ -233,6 +231,12 @@ bool Device::setupComplete() const
|
||||
return m_setupComplete;
|
||||
}
|
||||
|
||||
/*! Returns true if this device has been auto-created (not created by the user) */
|
||||
bool Device::autoCreated() const
|
||||
{
|
||||
return m_autoCreated;
|
||||
}
|
||||
|
||||
void Device::setSetupComplete(const bool &complete)
|
||||
{
|
||||
m_setupComplete = complete;
|
||||
|
||||
@ -69,6 +69,7 @@ public:
|
||||
void setParentId(const DeviceId &parentId);
|
||||
|
||||
bool setupComplete() const;
|
||||
bool autoCreated() const;
|
||||
|
||||
signals:
|
||||
void stateValueChanged(const QUuid &stateTypeId, const QVariant &value);
|
||||
@ -88,7 +89,8 @@ private:
|
||||
QString m_name;
|
||||
ParamList m_params;
|
||||
QList<State> m_states;
|
||||
bool m_setupComplete;
|
||||
bool m_setupComplete = false;
|
||||
bool m_autoCreated = false;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -120,6 +120,14 @@
|
||||
will be in \a deviceDescriptors. This signal can only emitted from devices with the \l{DeviceClass}{CreateMethodAuto}.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void DevicePlugin::autoDeviceDisappeared(const DeviceId &id)
|
||||
Emit this signal when a device which was created by \l{DevicePlugin::autoDevicesAppeared} has been removed from the system.
|
||||
Be careful with this, as this will completely remove the device from the system and with it all the associated rules. Only
|
||||
emit this if you are sure that a device will never come back. This signal should not be emitted for child auto devices
|
||||
when the parent who created them is removed. The system will automatically remove all child devices in such a case.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn void DevicePlugin::emitEvent(const Event &event)
|
||||
To produce a new event in the system, create a new \l{Event} and emit it with \a event.
|
||||
|
||||
@ -108,6 +108,7 @@ signals:
|
||||
void actionExecutionFinished(const ActionId &id, DeviceManager::DeviceError status);
|
||||
void configValueChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
void autoDevicesAppeared(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &deviceDescriptors);
|
||||
void autoDeviceDisappeared(const DeviceId &deviceId);
|
||||
|
||||
protected:
|
||||
DeviceManager *deviceManager() const;
|
||||
|
||||
@ -1175,6 +1175,7 @@ void TestDevices::removeDevice_data()
|
||||
|
||||
QTest::newRow("Existing Device") << m_mockDeviceId << DeviceManager::DeviceErrorNoError;
|
||||
QTest::newRow("Not existing Device") << DeviceId::createDeviceId() << DeviceManager::DeviceErrorDeviceNotFound;
|
||||
QTest::newRow("Auto device") << m_mockDeviceAutoId << DeviceManager::DeviceErrorCreationMethodNotSupported;
|
||||
}
|
||||
|
||||
void TestDevices::removeDevice()
|
||||
|
||||
@ -203,6 +203,13 @@ void GuhTestBase::initTestCase()
|
||||
|
||||
m_mockDeviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
QVERIFY2(!m_mockDeviceId.isNull(), "Newly created mock device must not be null.");
|
||||
|
||||
response = injectAndWait("Devices.GetConfiguredDevices", {});
|
||||
foreach (const QVariant &device, response.toMap().value("params").toMap().value("devices").toList()) {
|
||||
if (device.toMap().value("deviceClassId").toUuid() == mockDeviceAutoClassId) {
|
||||
m_mockDeviceAutoId = DeviceId(device.toMap().value("id").toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GuhTestBase::cleanupTestCase()
|
||||
|
||||
@ -188,6 +188,7 @@ protected:
|
||||
int m_mockDevice2Port;
|
||||
|
||||
DeviceId m_mockDeviceId;
|
||||
DeviceId m_mockDeviceAutoId;
|
||||
QByteArray m_apiToken;
|
||||
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user