Merge PR #146: Add a method to filter Devices

pull/152/head
Jenkins 2019-04-12 13:42:30 +02:00
commit ad9261290d
8 changed files with 114 additions and 4 deletions

View File

@ -469,17 +469,20 @@ DeviceManager::DeviceError DeviceManager::reconfigureDevice(const DeviceId &devi
{
Device *device = findConfiguredDevice(deviceId);
if (!device) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Device with id" << deviceId.toString() << "not found.";
return DeviceErrorDeviceNotFound;
}
ParamList effectiveParams = params;
DeviceClass deviceClass = findDeviceClass(device->deviceClassId());
if (deviceClass.id().isNull()) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. DeviceClass for device" << device->name() << deviceId.toString() << "not found.";
return DeviceErrorDeviceClassNotFound;
}
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
if (!plugin) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Plugin for DeviceClass" << deviceClass.displayName() << deviceClass.id().toString() << "not found.";
return DeviceErrorPluginNotFound;
}
@ -489,8 +492,10 @@ DeviceManager::DeviceError DeviceManager::reconfigureDevice(const DeviceId &devi
foreach (const ParamType &paramType, deviceClass.paramTypes()) {
foreach (const Param &param, params) {
if (paramType.id() == param.paramTypeId()) {
if (paramType.readOnly())
if (paramType.readOnly()) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Read-only parameters set by user.";
return DeviceErrorParameterNotWritable;
}
}
}
}
@ -498,6 +503,7 @@ DeviceManager::DeviceError DeviceManager::reconfigureDevice(const DeviceId &devi
DeviceError result = verifyParams(deviceClass.paramTypes(), effectiveParams, false);
if (result != DeviceErrorNoError) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Params failed validation.";
return result;
}
@ -1398,7 +1404,22 @@ void DeviceManager::onAutoDevicesAppeared(const DeviceClassId &deviceClassId, co
qCWarning(dcDeviceManager()) << "Invalid parent device id. Not adding device to the system.";
continue;
}
Device *device = new Device(plugin->pluginId(), deviceClassId, this);
Device *device = nullptr;
// If the appreaed auto device holds a valid device id, do a reconfiguration for this device
if (!deviceDescriptor.deviceId().isNull()) {
device = findConfiguredDevice(deviceDescriptor.deviceId());
if (!device) {
qCWarning(dcDeviceManager()) << "Could not find device for auto device descriptor" << deviceDescriptor.deviceId();
continue;
}
qCDebug(dcDeviceManager()) << "Start reconfiguring auto device" << device;
reconfigureDevice(deviceDescriptor.deviceId(), deviceDescriptor.params());
continue;
}
device = new Device(plugin->pluginId(), deviceClassId, this);
device->m_autoCreated = true;
device->setName(deviceDescriptor.title());
device->setParams(deviceDescriptor.params());
@ -1452,7 +1473,7 @@ void DeviceManager::onAutoDeviceDisappeared(const DeviceId &deviceId)
void DeviceManager::onLoaded()
{
qCWarning(dcDeviceManager()) << "Done loading plugins and devices.";
qCDebug(dcDeviceManager()) << "Done loading plugins and devices.";
emit loaded();
// schedule some housekeeping...

View File

@ -260,3 +260,30 @@ Device *Devices::findById(const DeviceId &id)
}
return nullptr;
}
QDebug operator<<(QDebug dbg, Device *device)
{
dbg.nospace() << "Device(" << device->name();
dbg.nospace() << ", id" << device->id();
dbg.nospace() << ", deviceClassId" << device->deviceClassId() << ")";
return dbg.space();
}
/*! Filter a Devices list by a parameter. Only Devices having a parameter of the given
\a paramTypeId will be returned. If \a value is given and it is not null, only Devices
with the given \a paramTypeId and the same \a value will be returned.
*/
Devices Devices::filterByParam(const ParamTypeId &paramTypeId, const QVariant &value)
{
Devices ret;
foreach (Device* device, *this) {
if (paramTypeId != paramTypeId) {
continue;
}
if (!value.isNull() && device->paramValue(paramTypeId) != value) {
continue;
}
ret << device;
}
return ret;
}

View File

@ -94,12 +94,15 @@ private:
bool m_autoCreated = false;
};
class Devices: public QList<Device*>
QDebug operator<<(QDebug dbg, Device *device);
class LIBNYMEA_EXPORT Devices: public QList<Device*>
{
public:
Devices() = default;
Devices(const QList<Device *> &other);
Device* findById(const DeviceId &id);
Devices filterByParam(const ParamTypeId &paramTypeId, const QVariant &value = QVariant());
};
#endif

View File

@ -110,6 +110,7 @@ DeviceManager::DeviceSetupStatus DevicePluginMock::setupDevice(Device *device)
connect(daemon, &HttpDaemon::setState, this, &DevicePluginMock::setState);
// Keep this queued or it might happen that the HttpDaemon is deleted before it is able to reply to the caller
connect(daemon, &HttpDaemon::disappear, this, &DevicePluginMock::onDisappear, Qt::QueuedConnection);
connect(daemon, &HttpDaemon::reconfigureAutodevice, this, &DevicePluginMock::onReconfigureAutoDevice, Qt::QueuedConnection);
if (async) {
m_asyncSetupDevices.append(device);
@ -383,6 +384,30 @@ void DevicePluginMock::onDisappear()
emit autoDeviceDisappeared(device->id());
}
void DevicePluginMock::onReconfigureAutoDevice()
{
HttpDaemon *daemon = qobject_cast<HttpDaemon *>(sender());
if (!daemon)
return;
Device *device = m_daemons.key(daemon);
qCDebug(dcMockDevice()) << "Reconfigure auto device for" << device << device->params();
int currentPort = device->params().paramValue(mockDeviceAutoDeviceHttpportParamTypeId).toInt();
// Note: the reconfigure makes the http server listen on port + 1
ParamList params;
params.append(Param(mockDeviceAutoDeviceHttpportParamTypeId, currentPort + 1));
DeviceDescriptor deviceDescriptor;
deviceDescriptor.setTitle(device->name() + " (reconfigured)");
deviceDescriptor.setDescription("This auto device was reconfigured");
deviceDescriptor.setDeviceId(device->id());
deviceDescriptor.setParams(params);
emit autoDevicesAppeared(mockDeviceAutoDeviceClassId, { deviceDescriptor });
}
void DevicePluginMock::emitDevicesDiscovered()
{
QList<DeviceDescriptor> deviceDescriptors;

View File

@ -59,6 +59,7 @@ private slots:
void setState(const StateTypeId &stateTypeId, const QVariant &value);
void triggerEvent(const EventTypeId &id);
void onDisappear();
void onReconfigureAutoDevice();
void emitDevicesDiscovered();
void emitPushButtonDevicesDiscovered();
void emitDisplayPinDevicesDiscovered();

View File

@ -114,6 +114,9 @@ void HttpDaemon::readClient()
} else if (url.path() == "/disappear") {
qCDebug(dcMockDevice) << "Should disappear";
emit disappear();
} else if (url.path() == "/reconfigureautodevice") {
qCDebug(dcMockDevice) << "Reconfigure auto device";
emit reconfigureAutodevice();
}
if (tokens[0] == "GET") {

View File

@ -47,6 +47,7 @@ signals:
void setState(const StateTypeId &stateTypeId, const QVariant &value);
void triggerEvent(const EventTypeId &eventTypeId);
void disappear();
void reconfigureAutodevice();
private slots:
void readClient();

View File

@ -91,6 +91,7 @@ private slots:
void reconfigureByDiscovery();
void reconfigureByDiscoveryAndPair();
void reconfigureAutodevice();
void removeDevice_data();
void removeDevice();
@ -1275,6 +1276,34 @@ void TestDevices::reconfigureByDiscoveryAndPair()
}
void TestDevices::reconfigureAutodevice()
{
qCDebug(dcTests()) << "Reconfigure auto device";
// Get the autodevice
QList<Device *> devices = NymeaCore::instance()->deviceManager()->findConfiguredDevices(mockDeviceAutoClassId);
QVERIFY2(devices.count() > 0, "There needs to be at least one auto-created Mock Device for this test");
// Get current auto device infos
Device *currentDevice = devices.first();
DeviceId deviceId = currentDevice->id();
int currentPort = currentDevice->paramValue(httpportParamTypeId).toInt();
// Trigger reconfigure signal in mock device
QNetworkAccessManager *nam = new QNetworkAccessManager(this);
QSignalSpy spy(nam, SIGNAL(finished(QNetworkReply*)));
QNetworkReply *reply = nam->get(QNetworkRequest(QUrl(QString("http://localhost:%1/reconfigureautodevice").arg(currentPort))));
spy.wait();
QCOMPARE(spy.count(), 1);
reply->deleteLater();
Device *device = NymeaCore::instance()->deviceManager()->findConfiguredDevice(deviceId);
QVERIFY(device);
int newPort = device->paramValue(httpportParamTypeId).toInt();
// Note: reconfigure autodevice increases the http port by 1
QVERIFY(newPort == currentPort + 1);
}
void TestDevices::removeDevice_data()
{