Merge PR #146: Add a method to filter Devices
This commit is contained in:
commit
ad9261290d
@ -469,17 +469,20 @@ DeviceManager::DeviceError DeviceManager::reconfigureDevice(const DeviceId &devi
|
|||||||
{
|
{
|
||||||
Device *device = findConfiguredDevice(deviceId);
|
Device *device = findConfiguredDevice(deviceId);
|
||||||
if (!device) {
|
if (!device) {
|
||||||
|
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Device with id" << deviceId.toString() << "not found.";
|
||||||
return DeviceErrorDeviceNotFound;
|
return DeviceErrorDeviceNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamList effectiveParams = params;
|
ParamList effectiveParams = params;
|
||||||
DeviceClass deviceClass = findDeviceClass(device->deviceClassId());
|
DeviceClass deviceClass = findDeviceClass(device->deviceClassId());
|
||||||
if (deviceClass.id().isNull()) {
|
if (deviceClass.id().isNull()) {
|
||||||
|
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. DeviceClass for device" << device->name() << deviceId.toString() << "not found.";
|
||||||
return DeviceErrorDeviceClassNotFound;
|
return DeviceErrorDeviceClassNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
|
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
|
||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
|
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Plugin for DeviceClass" << deviceClass.displayName() << deviceClass.id().toString() << "not found.";
|
||||||
return DeviceErrorPluginNotFound;
|
return DeviceErrorPluginNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,8 +492,10 @@ DeviceManager::DeviceError DeviceManager::reconfigureDevice(const DeviceId &devi
|
|||||||
foreach (const ParamType ¶mType, deviceClass.paramTypes()) {
|
foreach (const ParamType ¶mType, deviceClass.paramTypes()) {
|
||||||
foreach (const Param ¶m, params) {
|
foreach (const Param ¶m, params) {
|
||||||
if (paramType.id() == param.paramTypeId()) {
|
if (paramType.id() == param.paramTypeId()) {
|
||||||
if (paramType.readOnly())
|
if (paramType.readOnly()) {
|
||||||
|
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Read-only parameters set by user.";
|
||||||
return DeviceErrorParameterNotWritable;
|
return DeviceErrorParameterNotWritable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -498,6 +503,7 @@ DeviceManager::DeviceError DeviceManager::reconfigureDevice(const DeviceId &devi
|
|||||||
|
|
||||||
DeviceError result = verifyParams(deviceClass.paramTypes(), effectiveParams, false);
|
DeviceError result = verifyParams(deviceClass.paramTypes(), effectiveParams, false);
|
||||||
if (result != DeviceErrorNoError) {
|
if (result != DeviceErrorNoError) {
|
||||||
|
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Params failed validation.";
|
||||||
return result;
|
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.";
|
qCWarning(dcDeviceManager()) << "Invalid parent device id. Not adding device to the system.";
|
||||||
continue;
|
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->m_autoCreated = true;
|
||||||
device->setName(deviceDescriptor.title());
|
device->setName(deviceDescriptor.title());
|
||||||
device->setParams(deviceDescriptor.params());
|
device->setParams(deviceDescriptor.params());
|
||||||
@ -1452,7 +1473,7 @@ void DeviceManager::onAutoDeviceDisappeared(const DeviceId &deviceId)
|
|||||||
|
|
||||||
void DeviceManager::onLoaded()
|
void DeviceManager::onLoaded()
|
||||||
{
|
{
|
||||||
qCWarning(dcDeviceManager()) << "Done loading plugins and devices.";
|
qCDebug(dcDeviceManager()) << "Done loading plugins and devices.";
|
||||||
emit loaded();
|
emit loaded();
|
||||||
|
|
||||||
// schedule some housekeeping...
|
// schedule some housekeeping...
|
||||||
|
|||||||
@ -260,3 +260,30 @@ Device *Devices::findById(const DeviceId &id)
|
|||||||
}
|
}
|
||||||
return nullptr;
|
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 ¶mTypeId, 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;
|
||||||
|
}
|
||||||
|
|||||||
@ -94,12 +94,15 @@ private:
|
|||||||
bool m_autoCreated = false;
|
bool m_autoCreated = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Devices: public QList<Device*>
|
QDebug operator<<(QDebug dbg, Device *device);
|
||||||
|
|
||||||
|
class LIBNYMEA_EXPORT Devices: public QList<Device*>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Devices() = default;
|
Devices() = default;
|
||||||
Devices(const QList<Device *> &other);
|
Devices(const QList<Device *> &other);
|
||||||
Device* findById(const DeviceId &id);
|
Device* findById(const DeviceId &id);
|
||||||
|
Devices filterByParam(const ParamTypeId ¶mTypeId, const QVariant &value = QVariant());
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -110,6 +110,7 @@ DeviceManager::DeviceSetupStatus DevicePluginMock::setupDevice(Device *device)
|
|||||||
connect(daemon, &HttpDaemon::setState, this, &DevicePluginMock::setState);
|
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
|
// 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::disappear, this, &DevicePluginMock::onDisappear, Qt::QueuedConnection);
|
||||||
|
connect(daemon, &HttpDaemon::reconfigureAutodevice, this, &DevicePluginMock::onReconfigureAutoDevice, Qt::QueuedConnection);
|
||||||
|
|
||||||
if (async) {
|
if (async) {
|
||||||
m_asyncSetupDevices.append(device);
|
m_asyncSetupDevices.append(device);
|
||||||
@ -383,6 +384,30 @@ void DevicePluginMock::onDisappear()
|
|||||||
emit autoDeviceDisappeared(device->id());
|
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()
|
void DevicePluginMock::emitDevicesDiscovered()
|
||||||
{
|
{
|
||||||
QList<DeviceDescriptor> deviceDescriptors;
|
QList<DeviceDescriptor> deviceDescriptors;
|
||||||
|
|||||||
@ -59,6 +59,7 @@ 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 emitDevicesDiscovered();
|
void emitDevicesDiscovered();
|
||||||
void emitPushButtonDevicesDiscovered();
|
void emitPushButtonDevicesDiscovered();
|
||||||
void emitDisplayPinDevicesDiscovered();
|
void emitDisplayPinDevicesDiscovered();
|
||||||
|
|||||||
@ -114,6 +114,9 @@ void HttpDaemon::readClient()
|
|||||||
} else if (url.path() == "/disappear") {
|
} else if (url.path() == "/disappear") {
|
||||||
qCDebug(dcMockDevice) << "Should disappear";
|
qCDebug(dcMockDevice) << "Should disappear";
|
||||||
emit disappear();
|
emit disappear();
|
||||||
|
} else if (url.path() == "/reconfigureautodevice") {
|
||||||
|
qCDebug(dcMockDevice) << "Reconfigure auto device";
|
||||||
|
emit reconfigureAutodevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokens[0] == "GET") {
|
if (tokens[0] == "GET") {
|
||||||
|
|||||||
@ -47,6 +47,7 @@ signals:
|
|||||||
void setState(const StateTypeId &stateTypeId, const QVariant &value);
|
void setState(const StateTypeId &stateTypeId, const QVariant &value);
|
||||||
void triggerEvent(const EventTypeId &eventTypeId);
|
void triggerEvent(const EventTypeId &eventTypeId);
|
||||||
void disappear();
|
void disappear();
|
||||||
|
void reconfigureAutodevice();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void readClient();
|
void readClient();
|
||||||
|
|||||||
@ -91,6 +91,7 @@ private slots:
|
|||||||
void reconfigureByDiscovery();
|
void reconfigureByDiscovery();
|
||||||
|
|
||||||
void reconfigureByDiscoveryAndPair();
|
void reconfigureByDiscoveryAndPair();
|
||||||
|
void reconfigureAutodevice();
|
||||||
|
|
||||||
void removeDevice_data();
|
void removeDevice_data();
|
||||||
void removeDevice();
|
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()
|
void TestDevices::removeDevice_data()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user