Merge PR #223: More complete setup

This commit is contained in:
Jenkins nymea 2019-12-01 00:04:59 +01:00
commit 9710aa5927
11 changed files with 325 additions and 246 deletions

View File

@ -169,7 +169,7 @@ Device::DeviceError DeviceManagerImplementation::setPluginConfig(const PluginId
return Device::DeviceErrorPluginNotFound; return Device::DeviceErrorPluginNotFound;
} }
ParamList params = pluginConfig; ParamList params = buildParams(plugin->configurationDescription(), pluginConfig);
Device::DeviceError verify = DeviceUtils::verifyParams(plugin->configurationDescription(), params); Device::DeviceError verify = DeviceUtils::verifyParams(plugin->configurationDescription(), params);
if (verify != Device::DeviceErrorNoError) if (verify != Device::DeviceErrorNoError)
return verify; return verify;
@ -248,8 +248,7 @@ DeviceDiscoveryInfo* DeviceManagerImplementation::discoverDevices(const DeviceCl
return discoveryInfo; return discoveryInfo;
} }
// Create a copy of the parameter list because we might modify it (fillig in default values etc) ParamList effectiveParams = buildParams(deviceClass.discoveryParamTypes(), params);
ParamList effectiveParams = params;
Device::DeviceError result = DeviceUtils::verifyParams(deviceClass.discoveryParamTypes(), effectiveParams); Device::DeviceError result = DeviceUtils::verifyParams(deviceClass.discoveryParamTypes(), effectiveParams);
if (result != Device::DeviceErrorNoError) { if (result != Device::DeviceErrorNoError) {
qCWarning(dcDeviceManager) << "Device discovery failed. Parameter verification failed."; qCWarning(dcDeviceManager) << "Device discovery failed. Parameter verification failed.";
@ -266,7 +265,7 @@ DeviceDiscoveryInfo* DeviceManagerImplementation::discoverDevices(const DeviceCl
} }
qCDebug(dcDeviceManager()) << "Discovery finished. Found devices:" << discoveryInfo->deviceDescriptors().count(); qCDebug(dcDeviceManager()) << "Discovery finished. Found devices:" << discoveryInfo->deviceDescriptors().count();
foreach (const DeviceDescriptor &descriptor, discoveryInfo->deviceDescriptors()) { foreach (const DeviceDescriptor &descriptor, discoveryInfo->deviceDescriptors()) {
m_discoveredDevices[descriptor.deviceClassId()].insert(descriptor.id(), descriptor); m_discoveredDevices.insert(descriptor.id(), descriptor);
} }
}); });
@ -280,9 +279,9 @@ DeviceDiscoveryInfo* DeviceManagerImplementation::discoverDevices(const DeviceCl
* Optionally you can supply an id yourself if you must keep track of the added device. If you don't supply it, a new one will * Optionally you can supply an id yourself if you must keep track of the added device. If you don't supply it, a new one will
* be generated. Only devices with \l{DeviceClass}{CreateMethodUser} can be created using this method. * be generated. Only devices with \l{DeviceClass}{CreateMethodUser} can be created using this method.
* Returns \l{DeviceError} to inform about the result. */ * Returns \l{DeviceError} to inform about the result. */
DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id) DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDevice(const DeviceClassId &deviceClassId, const ParamList &params, const QString &name)
{ {
return addConfiguredDeviceInternal(deviceClassId, name, params, id); return addConfiguredDeviceInternal(deviceClassId, name, params);
} }
/*! Add a new configured device for the given \l{DeviceClass} the given DeviceDescriptorId and \a deviceId. Only devices with \l{DeviceClass}{CreateMethodDiscovery} /*! Add a new configured device for the given \l{DeviceClass} the given DeviceDescriptorId and \a deviceId. Only devices with \l{DeviceClass}{CreateMethodDiscovery}
@ -291,9 +290,16 @@ DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDevice(const DeviceCl
* are used but can be overridden here. * are used but can be overridden here.
* *
* Returns \l{DeviceError} to inform about the result. */ * Returns \l{DeviceError} to inform about the result. */
DeviceSetupInfo *DeviceManagerImplementation::addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId, const ParamList &params, const DeviceId &deviceId) DeviceSetupInfo *DeviceManagerImplementation::addConfiguredDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params, const QString &name)
{ {
DeviceClass deviceClass = findDeviceClass(deviceClassId); DeviceDescriptor descriptor = m_discoveredDevices.value(deviceDescriptorId);
if (!descriptor.isValid()) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceDescriptorNotFound);
return info;
}
DeviceClass deviceClass = findDeviceClass(descriptor.deviceClassId());
if (!deviceClass.isValid()) { if (!deviceClass.isValid()) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this); DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceClassNotFound); info->finish(Device::DeviceErrorDeviceClassNotFound);
@ -305,24 +311,10 @@ DeviceSetupInfo *DeviceManagerImplementation::addConfiguredDevice(const DeviceCl
return info; return info;
} }
DeviceDescriptor descriptor = m_discoveredDevices.value(deviceClassId).value(deviceDescriptorId); // Merging params from descriptor and user provided ones
if (!descriptor.isValid()) { ParamList finalParams = buildParams(deviceClass.paramTypes(), params, descriptor.params());
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceDescriptorNotFound);
return info;
}
// Merge params from discovered descriptor and additional overrides provided on API call. User provided params have higher priority than discovery params. return addConfiguredDeviceInternal(descriptor.deviceClassId(), name, finalParams, descriptor.parentDeviceId());
ParamList finalParams;
foreach (const ParamType &paramType, deviceClass.paramTypes()) {
if (params.hasParam(paramType.id())) {
finalParams.append(Param(paramType.id(), params.paramValue(paramType.id())));
} else if (descriptor.params().hasParam(paramType.id())) {
finalParams.append(Param(paramType.id(), descriptor.params().paramValue(paramType.id())));
}
}
return addConfiguredDeviceInternal(deviceClassId, name, finalParams, deviceId, descriptor.parentDeviceId());
} }
@ -331,7 +323,7 @@ DeviceSetupInfo *DeviceManagerImplementation::addConfiguredDevice(const DeviceCl
* from a discovery or if the user set them. If it came from discovery not writable parameters (readOnly) will be changed too. * from a discovery or if the user set them. If it came from discovery not writable parameters (readOnly) will be changed too.
* *
* Returns \l{DeviceError} to inform about the result. */ * Returns \l{DeviceError} to inform about the result. */
DeviceSetupInfo* DeviceManagerImplementation::reconfigureDevice(const DeviceId &deviceId, const ParamList &params, bool fromDiscoveryOrAuto) DeviceSetupInfo* DeviceManagerImplementation::reconfigureDevice(const DeviceId &deviceId, const ParamList &params, const QString &name)
{ {
Device *device = findConfiguredDevice(deviceId); Device *device = findConfiguredDevice(deviceId);
if (!device) { if (!device) {
@ -341,7 +333,6 @@ DeviceSetupInfo* DeviceManagerImplementation::reconfigureDevice(const DeviceId &
return info; return info;
} }
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."; qCWarning(dcDeviceManager()) << "Cannot reconfigure device. DeviceClass for device" << device->name() << deviceId.toString() << "not found.";
@ -350,32 +341,69 @@ DeviceSetupInfo* DeviceManagerImplementation::reconfigureDevice(const DeviceId &
return info; return info;
} }
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId()); foreach (const ParamType &paramType, deviceClass.paramTypes()) {
if (paramType.readOnly() && params.hasParam(paramType.id())) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
qCWarning(dcDeviceManager()) << "Parameter" << paramType.name() << paramType.id() << "is not writable";
info->finish(Device::DeviceErrorParameterNotWritable);
return info;
}
}
ParamList finalParams = buildParams(deviceClass.paramTypes(), params);
return reconfigureDeviceInternal(device, finalParams, name);
}
/*! Edit the \l{Param}{Params} of a configured device to the \l{Param}{Params} of the DeviceDescriptor with the
* given \a deviceId to the given DeviceDescriptorId.
* Only devices with \l{DeviceClass}{CreateMethodDiscovery} can be changed using this method.
* The \a deviceDescriptorId must refer to an existing DeviceDescriptorId from the discovery.
* This method allows to rediscover a device and update it's \l{Param}{Params}.
*
* Returns \l{DeviceError} to inform about the result. */
DeviceSetupInfo *DeviceManagerImplementation::reconfigureDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params, const QString &name)
{
DeviceDescriptor descriptor = m_discoveredDevices.value(deviceDescriptorId);
if (!descriptor.isValid()) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. No deviceDescriptor with ID" << deviceDescriptorId << "found.";
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceDescriptorNotFound);
return info;
}
Device *device = findConfiguredDevice(descriptor.deviceId());
if (!device) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. No device with ID" << descriptor.deviceId() << "found.";
info->finish(Device::DeviceErrorDeviceNotFound);
return info;
}
DeviceClass deviceClass = findDeviceClass(device->deviceClassId());
if (!deviceClass.isValid()) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. No deviceClass with ID" << device->deviceClassId() << "found.";
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceClassNotFound);
return info;
}
ParamList finalParams = buildParams(device->deviceClass().paramTypes(), params, descriptor.params());
return reconfigureDeviceInternal(device, finalParams, name);
}
DeviceSetupInfo *DeviceManagerImplementation::reconfigureDeviceInternal(Device *device, const ParamList &params, const QString &name)
{
DevicePlugin *plugin = m_devicePlugins.value(device->deviceClass().pluginId());
if (!plugin) { if (!plugin) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Plugin for DeviceClass" << deviceClass.displayName() << deviceClass.id().toString() << "not found."; qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Plugin for DeviceClass" << device->deviceClassId().toString() << "not found.";
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this); DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorPluginNotFound); info->finish(Device::DeviceErrorPluginNotFound);
return info; return info;
} }
// if the params are discovered and not set by the user ParamList finalParams = buildParams(device->deviceClass().paramTypes(), params);
if (!fromDiscoveryOrAuto) { Device::DeviceError result = DeviceUtils::verifyParams(device->deviceClass().paramTypes(), finalParams);
// check if one of the given params is not editable
foreach (const ParamType &paramType, deviceClass.paramTypes()) {
foreach (const Param &param, params) {
if (paramType.id() == param.paramTypeId()) {
if (paramType.readOnly()) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Read-only parameters set by user.";
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorParameterNotWritable);
return info;
}
}
}
}
}
Device::DeviceError result = DeviceUtils::verifyParams(deviceClass.paramTypes(), effectiveParams, false);
if (result != Device::DeviceErrorNoError) { if (result != Device::DeviceErrorNoError) {
qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Params failed validation."; qCWarning(dcDeviceManager()) << "Cannot reconfigure device. Params failed validation.";
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this); DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
@ -390,10 +418,14 @@ DeviceSetupInfo* DeviceManagerImplementation::reconfigureDevice(const DeviceId &
device->setSetupComplete(false); device->setSetupComplete(false);
// set new params // set new params
foreach (const Param &param, effectiveParams) { foreach (const Param &param, params) {
device->setParamValue(param.paramTypeId(), param.value()); device->setParamValue(param.paramTypeId(), param.value());
} }
if (!name.isEmpty()) {
device->setName(name);
}
// try to setup the device with the new params // try to setup the device with the new params
DeviceSetupInfo *info = new DeviceSetupInfo(device, this, 30000); DeviceSetupInfo *info = new DeviceSetupInfo(device, this, 30000);
plugin->setupDevice(info); plugin->setupDevice(info);
@ -415,44 +447,7 @@ DeviceSetupInfo* DeviceManagerImplementation::reconfigureDevice(const DeviceId &
}); });
return info; return info;
}
/*! Edit the \l{Param}{Params} of a configured device to the \l{Param}{Params} of the DeviceDescriptor with the
* given \a deviceId to the given DeviceDescriptorId.
* Only devices with \l{DeviceClass}{CreateMethodDiscovery} can be changed using this method.
* The \a deviceDescriptorId must refer to an existing DeviceDescriptorId from the discovery.
* This method allows to rediscover a device and update it's \l{Param}{Params}.
*
* Returns \l{DeviceError} to inform about the result. */
DeviceSetupInfo *DeviceManagerImplementation::reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId)
{
Device *device = findConfiguredDevice(deviceId);
if (!device) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceNotFound);
return info;
}
DeviceClass deviceClass = findDeviceClass(device->deviceClassId());
if (!deviceClass.isValid()) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceClassNotFound);
return info;
}
if (!deviceClass.createMethods().testFlag(DeviceClass::CreateMethodDiscovery)) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorCreationMethodNotSupported);
return info;
}
DeviceDescriptor descriptor = m_discoveredDevices.value(deviceClass.id()).value(deviceDescriptorId);
if (!descriptor.isValid()) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
info->finish(Device::DeviceErrorDeviceDescriptorNotFound);
return info;
}
return reconfigureDevice(deviceId, descriptor.params(), true);
} }
/*! Edit the \a name of the \l{Device} with the given \a deviceId. /*! Edit the \a name of the \l{Device} with the given \a deviceId.
@ -478,57 +473,89 @@ Device::DeviceError DeviceManagerImplementation::setDeviceSettings(const DeviceI
qCWarning(dcDeviceManager()) << "Cannot set device settings. Device" << deviceId.toString() << "not found"; qCWarning(dcDeviceManager()) << "Cannot set device settings. Device" << deviceId.toString() << "not found";
return Device::DeviceErrorDeviceNotFound; return Device::DeviceErrorDeviceNotFound;
} }
ParamList effectiveSettings = settings; // build a list of settings using: a) provided new settings b) previous settings and c) default values
Device::DeviceError status = DeviceUtils::verifyParams(findDeviceClass(device->deviceClassId()).settingsTypes(), effectiveSettings); ParamList effectiveSettings = buildParams(device->deviceClass().settingsTypes(), settings, device->settings());
Device::DeviceError status = DeviceUtils::verifyParams(device->deviceClass().settingsTypes(), effectiveSettings);
if (status != Device::DeviceErrorNoError) { if (status != Device::DeviceErrorNoError) {
qCWarning(dcDeviceManager()) << "Error setting device settings for device" << device->name() << device->id().toString(); qCWarning(dcDeviceManager()) << "Error setting device settings for device" << device->name() << device->id().toString();
return status; return status;
} }
foreach (const Param &setting, settings) { device->setSettings(effectiveSettings);
device->setSettingValue(setting.paramTypeId(), setting.value());
}
return Device::DeviceErrorNoError; return Device::DeviceErrorNoError;
} }
/*! Initiates a pairing with a \l{DeviceClass}{Device} with the given \a pairingTransactionId, \a deviceClassId, \a name and \a params. DevicePairingInfo* DeviceManagerImplementation::pairDevice(const DeviceClassId &deviceClassId, const ParamList &params, const QString &name)
* Returns \l{Device::DeviceError}{DeviceError} to inform about the result. */
DevicePairingInfo* DeviceManagerImplementation::pairDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params)
{ {
PairingTransactionId transactionId = PairingTransactionId::createPairingTransactionId(); PairingTransactionId transactionId = PairingTransactionId::createPairingTransactionId();
// Create new device id
DeviceId newDeviceId = DeviceId::createDeviceId();
DevicePairingInfo *info = new DevicePairingInfo(transactionId, deviceClassId, newDeviceId, name, params, DeviceId(), this, 30000);
pairDeviceInternal(info);
return info;
}
/*! Initiates a pairing with a \l{DeviceClass}{Device} with the given \a pairingTransactionId, \a deviceClassId, \a name and \a deviceDescriptorId. DeviceClass deviceClass = m_supportedDevices.value(deviceClassId);
* Returns \l{Device::DeviceError}{DeviceError} to inform about the result. */ if (!deviceClass.isValid()) {
DevicePairingInfo* DeviceManagerImplementation::pairDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId) qCWarning(dcDeviceManager) << "Cannot find a DeviceClass with ID" << deviceClassId.toString();
{ DevicePairingInfo *info = new DevicePairingInfo(transactionId, deviceClassId, DeviceId(), name, ParamList(), DeviceId(), this);
PairingTransactionId pairingTransactionId = PairingTransactionId::createPairingTransactionId();
DeviceClass deviceClass = findDeviceClass(deviceClassId);
if (deviceClass.id().isNull()) {
qCWarning(dcDeviceManager) << "Cannot find a device class with id" << deviceClassId;
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, deviceClassId, DeviceId(), name, ParamList(), DeviceId(), this);
info->finish(Device::DeviceErrorDeviceClassNotFound); info->finish(Device::DeviceErrorDeviceClassNotFound);
return info; return info;
} }
DeviceDescriptor deviceDescriptor = m_discoveredDevices.value(deviceClassId).value(deviceDescriptorId); // Create new device id
if (!deviceDescriptor.isValid()) { DeviceId newDeviceId = DeviceId::createDeviceId();
qCWarning(dcDeviceManager) << "Cannot find a DeviceDescriptor with ID" << deviceClassId.toString();
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, deviceClassId, DeviceId(), name, ParamList(), DeviceId(), this); // Use given params, if there are missing some, use the defaults ones.
ParamList finalParams = buildParams(deviceClass.paramTypes(), params);
DevicePairingInfo *info = new DevicePairingInfo(transactionId, deviceClassId, newDeviceId, name, finalParams, DeviceId(), this, 30000);
pairDeviceInternal(info);
return info;
}
DevicePairingInfo* DeviceManagerImplementation::pairDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params, const QString &name)
{
PairingTransactionId pairingTransactionId = PairingTransactionId::createPairingTransactionId();
DeviceDescriptor descriptor = m_discoveredDevices.value(deviceDescriptorId);
if (!descriptor.isValid()) {
qCWarning(dcDeviceManager) << "Cannot find a DeviceDescriptor with ID" << deviceDescriptorId.toString();
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, DeviceClassId(), DeviceId(), name, ParamList(), DeviceId(), this);
info->finish(Device::DeviceErrorDeviceDescriptorNotFound); info->finish(Device::DeviceErrorDeviceDescriptorNotFound);
return info; return info;
} }
DeviceId deviceId = deviceDescriptor.deviceId(); DeviceClass deviceClass = m_supportedDevices.value(descriptor.deviceClassId());
if (!deviceClass.isValid()) {
qCWarning(dcDeviceManager) << "Cannot find a DeviceClass with ID" << descriptor.deviceClassId().toString();
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, descriptor.deviceClassId(), DeviceId(), name, ParamList(), DeviceId(), this);
info->finish(Device::DeviceErrorDeviceClassNotFound);
return info;
}
DeviceId deviceId = descriptor.deviceId();
// If it's a new device (not a reconfiguration), create a new DeviceId now. // If it's a new device (not a reconfiguration), create a new DeviceId now.
if (deviceId.isNull()) { if (deviceId.isNull()) {
deviceId = DeviceId::createDeviceId(); deviceId = DeviceId::createDeviceId();
} }
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, deviceClassId, deviceId, name, deviceDescriptor.params(), deviceDescriptor.parentDeviceId(), this, 30000);
// Use given params, if there are missing some, use the discovered ones.
ParamList finalParams = buildParams(deviceClass.paramTypes(), params, descriptor.params());
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, descriptor.deviceClassId(), deviceId, name, finalParams, descriptor.parentDeviceId(), this, 30000);
pairDeviceInternal(info);
return info;
}
DevicePairingInfo *DeviceManagerImplementation::pairDevice(const DeviceId &deviceId, const ParamList &params, const QString &name)
{
PairingTransactionId pairingTransactionId = PairingTransactionId::createPairingTransactionId();
Device *device = findConfiguredDevice(deviceId);
if (!device) {
qCWarning(dcDeviceManager) << "Cannot find a Device with ID" << deviceId.toString();
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, DeviceClassId(), deviceId, name, ParamList(), DeviceId(), this);
info->finish(Device::DeviceErrorDeviceDescriptorNotFound);
return info;
}
// Use new params, if there are missing some, use the existing ones.
ParamList finalParams = buildParams(device->deviceClass().paramTypes(), params, device->params());
DevicePairingInfo *info = new DevicePairingInfo(pairingTransactionId, device->deviceClassId(), deviceId, name, finalParams, DeviceId(), this, 30000);
pairDeviceInternal(info); pairDeviceInternal(info);
return info; return info;
} }
@ -599,9 +626,7 @@ DevicePairingInfo *DeviceManagerImplementation::confirmPairing(const PairingTran
} }
device->setParams(internalInfo->params()); device->setParams(internalInfo->params());
ParamList settings; ParamList settings = buildParams(deviceClass.settingsTypes(), ParamList());
// Use verifyParams to populate it with defaults
DeviceUtils::verifyParams(deviceClass.settingsTypes(), settings);
device->setSettings(settings); device->setSettings(settings);
DeviceSetupInfo *info = setupDevice(device); DeviceSetupInfo *info = setupDevice(device);
@ -642,7 +667,7 @@ DevicePairingInfo *DeviceManagerImplementation::confirmPairing(const PairingTran
/*! This method will only be used from the DeviceManagerImplementation in order to add a \l{Device} with the given \a deviceClassId, \a name, \a params and \ id. /*! This method will only be used from the DeviceManagerImplementation in order to add a \l{Device} with the given \a deviceClassId, \a name, \a params and \ id.
* Returns \l{DeviceError} to inform about the result. */ * Returns \l{DeviceError} to inform about the result. */
DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId &deviceId, const DeviceId &parentDeviceId) DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId &parentDeviceId)
{ {
DeviceClass deviceClass = findDeviceClass(deviceClassId); DeviceClass deviceClass = findDeviceClass(deviceClassId);
if (deviceClass.id().isNull()) { if (deviceClass.id().isNull()) {
@ -657,10 +682,10 @@ DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDeviceInternal(const
return info; return info;
} }
if (m_configuredDevices.contains(deviceId)) { DeviceId deviceId = DeviceId::createDeviceId();
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this); // Chances are like 0, but...
info->finish(Device::DeviceErrorDuplicateUuid); while (m_configuredDevices.contains(deviceId)) {
return info; deviceId = DeviceId::createDeviceId();
} }
DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId()); DevicePlugin *plugin = m_devicePlugins.value(deviceClass.pluginId());
@ -670,7 +695,8 @@ DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDeviceInternal(const
return info; return info;
} }
ParamList effectiveParams = params; // set params
ParamList effectiveParams = buildParams(deviceClass.paramTypes(), params);
Device::DeviceError paramsResult = DeviceUtils::verifyParams(deviceClass.paramTypes(), effectiveParams); Device::DeviceError paramsResult = DeviceUtils::verifyParams(deviceClass.paramTypes(), effectiveParams);
if (paramsResult != Device::DeviceErrorNoError) { if (paramsResult != Device::DeviceErrorNoError) {
DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this); DeviceSetupInfo *info = new DeviceSetupInfo(nullptr, this);
@ -687,8 +713,8 @@ DeviceSetupInfo* DeviceManagerImplementation::addConfiguredDeviceInternal(const
} }
device->setParams(effectiveParams); device->setParams(effectiveParams);
ParamList settings; // set settings (init with defaults)
DeviceUtils::verifyParams(deviceClass.settingsTypes(), settings); ParamList settings = buildParams(deviceClass.settingsTypes(), ParamList());
qCDebug(dcDeviceManager()) << "Adding device settings" << settings << deviceId; qCDebug(dcDeviceManager()) << "Adding device settings" << settings << deviceId;
device->setSettings(settings); device->setSettings(settings);
@ -936,7 +962,7 @@ DeviceActionInfo *DeviceManagerImplementation::executeAction(const Action &actio
return info; return info;
} }
ParamList finalParams = action.params(); ParamList finalParams = buildParams(actionType.paramTypes(), action.params());
Device::DeviceError paramCheck = DeviceUtils::verifyParams(actionType.paramTypes(), finalParams); Device::DeviceError paramCheck = DeviceUtils::verifyParams(actionType.paramTypes(), finalParams);
if (paramCheck != Device::DeviceErrorNoError) { if (paramCheck != Device::DeviceErrorNoError) {
qCWarning(dcDeviceManager()) << "Cannot execute action. Parameter verification failed."; qCWarning(dcDeviceManager()) << "Cannot execute action. Parameter verification failed.";
@ -1206,13 +1232,9 @@ void DeviceManagerImplementation::loadConfiguredDevices()
params.append(Param(ParamTypeId(paramTypeIdString), settings.value(paramTypeIdString))); params.append(Param(ParamTypeId(paramTypeIdString), settings.value(paramTypeIdString)));
} }
} }
DeviceUtils::verifyParams(deviceClass.settingsTypes(), deviceSettings);
// Make sure all settings are around. if they aren't initialize with default values // Fill in any missing params with defaults
foreach (const ParamType &settingsType, deviceClass.settingsTypes()) { deviceSettings = buildParams(deviceClass.settingsTypes(), deviceSettings);
if (!deviceSettings.hasParam(settingsType.id())) {
deviceSettings.append(Param(settingsType.id(), settingsType.defaultValue().isValid() ? settingsType.defaultValue() : ""));
}
}
device->setSettings(deviceSettings); device->setSettings(deviceSettings);
@ -1332,7 +1354,8 @@ void DeviceManagerImplementation::onAutoDevicesAppeared(const DeviceDescriptors
continue; continue;
} }
qCDebug(dcDeviceManager()) << "Start reconfiguring auto device" << device; qCDebug(dcDeviceManager()) << "Start reconfiguring auto device" << device;
reconfigureDevice(deviceDescriptor.deviceId(), deviceDescriptor.params(), true); ParamList finalParams = buildParams(deviceClass.paramTypes(), deviceDescriptor.params());
reconfigureDeviceInternal(device, finalParams);
continue; continue;
} }
@ -1340,8 +1363,7 @@ void DeviceManagerImplementation::onAutoDevicesAppeared(const DeviceDescriptors
device->m_autoCreated = true; device->m_autoCreated = true;
device->setName(deviceDescriptor.title()); device->setName(deviceDescriptor.title());
device->setParams(deviceDescriptor.params()); device->setParams(deviceDescriptor.params());
ParamList settings; ParamList settings = buildParams(deviceClass.settingsTypes(), ParamList());
DeviceUtils::verifyParams(deviceClass.settingsTypes(), settings);
device->setSettings(settings); device->setSettings(settings);
device->setParentId(deviceDescriptor.parentDeviceId()); device->setParentId(deviceDescriptor.parentDeviceId());
@ -1453,6 +1475,22 @@ void DeviceManagerImplementation::slotDeviceSettingChanged(const ParamTypeId &pa
emit deviceSettingChanged(device->id(), paramTypeId, value); emit deviceSettingChanged(device->id(), paramTypeId, value);
} }
ParamList DeviceManagerImplementation::buildParams(const ParamTypes &types, const ParamList &first, const ParamList &second)
{
// Merge params from discovered descriptor and additional overrides provided on API call. User provided params have higher priority than discovery params.
ParamList finalParams;
foreach (const ParamType &paramType, types) {
if (first.hasParam(paramType.id())) {
finalParams.append(Param(paramType.id(), first.paramValue(paramType.id())));
} else if (second.hasParam(paramType.id())) {
finalParams.append(Param(paramType.id(), second.paramValue(paramType.id())));
} else if (paramType.defaultValue().isValid()){
finalParams.append(Param(paramType.id(), paramType.defaultValue()));
}
}
return finalParams;
}
void DeviceManagerImplementation::pairDeviceInternal(DevicePairingInfo *info) void DeviceManagerImplementation::pairDeviceInternal(DevicePairingInfo *info)
{ {
DeviceClass deviceClass = m_supportedDevices.value(info->deviceClassId()); DeviceClass deviceClass = m_supportedDevices.value(info->deviceClassId());

View File

@ -83,19 +83,20 @@ public:
DeviceDiscoveryInfo* discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override; DeviceDiscoveryInfo* discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) override;
DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id = DeviceId::createDeviceId()) override; DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const ParamList &params, const QString &name = QString()) override;
DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const DeviceId &deviceId = DeviceId::createDeviceId()) override; DeviceSetupInfo* addConfiguredDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const QString &name = QString()) override;
DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const ParamList &params, bool fromDiscoveryOrAuto = false) override; DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const ParamList &params, const QString &name = QString()) override;
DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId) override; DeviceSetupInfo* reconfigureDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const QString &name = QString()) override;
DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const ParamList &params, const QString &name = QString()) override;
DevicePairingInfo* pairDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const QString &name = QString()) override;
DevicePairingInfo* pairDevice(const DeviceId &deviceId, const ParamList &params, const QString &name = QString()) override;
DevicePairingInfo* confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &username, const QString &secret) override;
Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) override; Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) override;
Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) override; Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) override;
DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params) override;
DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId) override;
DevicePairingInfo* confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &username, const QString &secret) override;
Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) override; Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) override;
DeviceActionInfo* executeAction(const Action &action) override; DeviceActionInfo* executeAction(const Action &action) override;
@ -130,8 +131,12 @@ private slots:
void slotDeviceSettingChanged(const ParamTypeId &paramTypeId, const QVariant &value); void slotDeviceSettingChanged(const ParamTypeId &paramTypeId, const QVariant &value);
private: private:
// Builds a list of params ready to create a device.
// Template is deviceClass.paramtypes, "first" has highest priority. If a param is not found neither in first nor in second, defaults apply.
ParamList buildParams(const ParamTypes &types, const ParamList &first, const ParamList &second = ParamList());
void pairDeviceInternal(DevicePairingInfo *info); void pairDeviceInternal(DevicePairingInfo *info);
DeviceSetupInfo *addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId &deviceId = DeviceId::createDeviceId(), const DeviceId &parentDeviceId = DeviceId()); DeviceSetupInfo *addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId &parentDeviceId = DeviceId());
DeviceSetupInfo *reconfigureDeviceInternal(Device *device, const ParamList &params, const QString &name = QString());
DeviceSetupInfo *setupDevice(Device *device); DeviceSetupInfo *setupDevice(Device *device);
void postSetupDevice(Device *device); void postSetupDevice(Device *device);
void storeDeviceStates(Device *device); void storeDeviceStates(Device *device);
@ -147,7 +152,7 @@ private:
QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap; QHash<VendorId, QList<DeviceClassId> > m_vendorDeviceMap;
QHash<DeviceClassId, DeviceClass> m_supportedDevices; QHash<DeviceClassId, DeviceClass> m_supportedDevices;
QHash<DeviceId, Device*> m_configuredDevices; QHash<DeviceId, Device*> m_configuredDevices;
QHash<DeviceClassId, QHash<DeviceDescriptorId, DeviceDescriptor> > m_discoveredDevices; QHash<DeviceDescriptorId, DeviceDescriptor> m_discoveredDevices;
QHash<PluginId, DevicePlugin*> m_devicePlugins; QHash<PluginId, DevicePlugin*> m_devicePlugins;

View File

@ -127,7 +127,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
"Devices with CreateMethodJustAdd require all parameters to be supplied here. " "Devices with CreateMethodJustAdd require all parameters to be supplied here. "
"Devices with CreateMethodDiscovery require the use of a deviceDescriptorId. For discovered " "Devices with CreateMethodDiscovery require the use of a deviceDescriptorId. For discovered "
"devices params are not required and will be taken from the DeviceDescriptor, however, they " "devices params are not required and will be taken from the DeviceDescriptor, however, they "
"may be overridden by supplying parameters here." "may be overridden by supplying deviceParams."
); );
params.insert("deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("name", JsonTypes::basicTypeToString(JsonTypes::String));
@ -141,28 +141,44 @@ DeviceHandler::DeviceHandler(QObject *parent) :
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("AddConfiguredDevice", returns); setReturns("AddConfiguredDevice", returns);
returns.clear(); // Reused params from above! params.clear(); returns.clear();
setDescription("PairDevice", "Pair a device. " setDescription("PairDevice", "Pair a device. "
"Use this for DeviceClasses with a setupMethod different than SetupMethodJustAdd. " "Use this to set up or reconfigure devices for DeviceClasses with a setupMethod different than SetupMethodJustAdd. "
"Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. " "Depending on the CreateMethod and whether a new devices is set up or an existing one is reconfigured, different parameters "
"CreateMethodJustAdd takes the parameters you want to have with that device. " "are required:\n"
"CreateMethodDiscovery requires the use of a deviceDescriptorId, optionally, parameters can be overridden here. " "CreateMethodJustAdd takes the deviceClassId and the parameters you want to have with that device.\n"
"CreateMethodDiscovery requires the use of a deviceDescriptorId, previously obtained with DiscoverDevices. Optionally, "
"parameters can be overridden with the give deviceParams.\n"
"If an existing device should be reconfigured, the deviceId of said device should be given additionally.\n"
"If success is true, the return values will contain a pairingTransactionId, a displayMessage and " "If success is true, the return values will contain a pairingTransactionId, a displayMessage and "
"the setupMethod. Depending on the setupMethod you should either proceed with AddConfiguredDevice " "the setupMethod. Depending on the setupMethod, the application should present the use an appropriate login mask, "
"or PairDevice." "that is, For SetupMethodDisplayPin the user should enter a pin that is displayed on the device, for SetupMethodEnterPin the "
"application should present the given PIN so the user can enter it on the device. For SetupMethodPushButton, the displayMessage "
"shall be presented to the user as informational hints to press a button on the device. For SetupMethodUserAndPassword a login "
"mask for a user and password login should be presented to the user. In case of SetupMethodOAuth, an OAuth URL will be returned "
"which shall be opened in a web view to allow the user logging in.\n"
"Once the login procedure has completed, the application shall proceed with ConfirmPairing, providing the results of the pairing "
"procedure."
); );
params.insert("o:deviceClassId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:name", JsonTypes::basicTypeToString(JsonTypes::String));
params.insert("o:deviceDescriptorId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:deviceParams", deviceParams);
params.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
setParams("PairDevice", params); setParams("PairDevice", params);
returns.insert("deviceError", JsonTypes::deviceErrorRef()); returns.insert("deviceError", JsonTypes::deviceErrorRef());
returns.insert("o:setupMethod", JsonTypes::setupMethodRef()); returns.insert("o:setupMethod", JsonTypes::setupMethodRef());
returns.insert("o:pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); returns.insert("o:pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("o:displayMessage", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("o:oAuthUrl", JsonTypes::basicTypeToString(JsonTypes::String)); returns.insert("o:oAuthUrl", JsonTypes::basicTypeToString(JsonTypes::String));
returns.insert("o:pin", JsonTypes::basicTypeToString(JsonTypes::String));
setReturns("PairDevice", returns); setReturns("PairDevice", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ConfirmPairing", "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field " setDescription("ConfirmPairing", "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field "
"and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" " "and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" "
"field. For SetupMethodOAuth, return the entire unmodified callback URL containing the code parameter back in the secret field."); "field. In case of SetupMethodOAuth, the previously opened web view will eventually be redirected to http://128.0.0.1:8888 "
"and the OAuth code as query parameters to this url. Provide the entire unmodified URL in the secret field.");
params.insert("pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("pairingTransactionId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:username", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("o:username", JsonTypes::basicTypeToString(JsonTypes::String));
params.insert("o:secret", JsonTypes::basicTypeToString(JsonTypes::String)); params.insert("o:secret", JsonTypes::basicTypeToString(JsonTypes::String));
@ -200,12 +216,14 @@ DeviceHandler::DeviceHandler(QObject *parent) :
setReturns("GetDiscoveredDevices", returns); setReturns("GetDiscoveredDevices", returns);
params.clear(); returns.clear(); params.clear(); returns.clear();
setDescription("ReconfigureDevice", "Edit the parameter configuration of the device. The device params will be set to the " setDescription("ReconfigureDevice", "Reconfigure a device. This comes down to removing and recreating a device with new parameters "
"passed parameters and the setup device will be called. If the device is discoverable, " "but keeping its device id the same (and with that keeping rules, tags etc). For devices with "
"you can perform a GetDiscoveredDevices before calling this method and pass " "create method CreateMethodDiscovery, a discovery (GetDiscoveredDevices) shall be performed first "
"the new DeviceDescriptor (rediscover). Only writable parameters can be changed. By default, " "and this method is to be called with a deviceDescriptorId of the re-discovered device instead of "
"every Param is writable."); "the deviceId directly. Device parameters will be taken from the discovery, but can be overridden "
params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); "individually here by providing them in the deviceParams parameter. Only writable parameters can "
"be changed.");
params.insert("o:deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
params.insert("o:deviceDescriptorId", JsonTypes::basicTypeToString(JsonTypes::Uuid)); params.insert("o:deviceDescriptorId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
QVariantList newDeviceParams; QVariantList newDeviceParams;
newDeviceParams.append(JsonTypes::paramRef()); newDeviceParams.append(JsonTypes::paramRef());
@ -451,20 +469,19 @@ JsonReply* DeviceHandler::SetPluginConfiguration(const QVariantMap &params)
JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap &params) JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap &params)
{ {
DeviceClassId deviceClass(params.value("deviceClassId").toString()); DeviceClassId deviceClassId(params.value("deviceClassId").toString());
QString deviceName = params.value("name").toString(); QString deviceName = params.value("name").toString();
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
DeviceId newDeviceId = DeviceId::createDeviceId();
QLocale locale = params.value("locale").toLocale(); QLocale locale = params.value("locale").toLocale();
JsonReply *jsonReply = createAsyncReply("AddConfiguredDevice"); JsonReply *jsonReply = createAsyncReply("AddConfiguredDevice");
DeviceSetupInfo *info; DeviceSetupInfo *info;
if (deviceDescriptorId.isNull()) { if (deviceDescriptorId.isNull()) {
info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceName, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceParams, deviceName);
} else { } else {
info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClass, deviceName, deviceDescriptorId, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceDescriptorId, deviceParams, deviceName);
} }
connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){ connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){
QVariantMap returns; QVariantMap returns;
@ -486,28 +503,31 @@ JsonReply* DeviceHandler::AddConfiguredDevice(const QVariantMap &params)
JsonReply *DeviceHandler::PairDevice(const QVariantMap &params) JsonReply *DeviceHandler::PairDevice(const QVariantMap &params)
{ {
DeviceClassId deviceClassId(params.value("deviceClassId").toString());
QString deviceName = params.value("name").toString(); QString deviceName = params.value("name").toString();
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(deviceClassId); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
QLocale locale = params.value("locale").toLocale(); QLocale locale = params.value("locale").toLocale();
DevicePairingInfo *info; DevicePairingInfo *info;
if (params.contains("deviceDescriptorId")) { if (params.contains("deviceDescriptorId")) {
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId = DeviceDescriptorId(params.value("deviceDescriptorId").toString());
info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceDescriptorId); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceDescriptorId, deviceParams, deviceName);
} else if (params.contains("deviceId")) {
DeviceId deviceId = DeviceId(params.value("deviceId").toString());
info = NymeaCore::instance()->deviceManager()->pairDevice(deviceId, deviceParams, deviceName);
} else { } else {
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); DeviceClassId deviceClassId(params.value("deviceClassId").toString());
info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceParams); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceParams, deviceName);
} }
JsonReply *jsonReply = createAsyncReply("PairDevice"); JsonReply *jsonReply = createAsyncReply("PairDevice");
connect(info, &DevicePairingInfo::finished, jsonReply, [jsonReply, info, locale, deviceClass](){ connect(info, &DevicePairingInfo::finished, jsonReply, [jsonReply, info, locale](){
QVariantMap returns; QVariantMap returns;
returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status())); returns.insert("deviceError", JsonTypes::deviceErrorToString(info->status()));
returns.insert("pairingTransactionId", info->transactionId().toString()); returns.insert("pairingTransactionId", info->transactionId().toString());
if (info->status() == Device::DeviceErrorNoError) { if (info->status() == Device::DeviceErrorNoError) {
DeviceClass deviceClass = NymeaCore::instance()->deviceManager()->findDeviceClass(info->deviceClassId());
returns.insert("setupMethod", JsonTypes::setupMethodToString(deviceClass.setupMethod())); returns.insert("setupMethod", JsonTypes::setupMethodToString(deviceClass.setupMethod()));
} }
@ -584,10 +604,15 @@ JsonReply *DeviceHandler::ReconfigureDevice(const QVariantMap &params)
JsonReply *jsonReply = createAsyncReply("ReconfigureDevice"); JsonReply *jsonReply = createAsyncReply("ReconfigureDevice");
DeviceSetupInfo *info; DeviceSetupInfo *info;
if (deviceDescriptorId.isNull()) { if (!deviceDescriptorId.isNull()) {
info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceDescriptorId, deviceParams);
} else if (!deviceId.isNull()){
info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceId, deviceParams); info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceId, deviceParams);
} else { } else {
info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceId, deviceDescriptorId); qCWarning(dcJsonRpc()) << "Either deviceId or deviceDescriptorId are required";
QVariantMap ret;
ret.insert("deviceError", JsonTypes::deviceErrorToString(Device::DeviceErrorMissingParameter));
return createReply(ret);
} }
connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){ connect(info, &DeviceSetupInfo::finished, jsonReply, [info, jsonReply, locale](){
@ -597,6 +622,7 @@ JsonReply *DeviceHandler::ReconfigureDevice(const QVariantMap &params)
returns.insert("displayMessage", info->translatedDisplayMessage(locale)); returns.insert("displayMessage", info->translatedDisplayMessage(locale));
jsonReply->setData(returns); jsonReply->setData(returns);
jsonReply->finished(); jsonReply->finished();
}); });
return jsonReply; return jsonReply;

View File

@ -375,7 +375,6 @@ HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const
return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorDeviceClassNotFound); return createDeviceErrorReply(HttpReply::BadRequest, Device::DeviceErrorDeviceClassNotFound);
QString deviceName = params.value("name").toString(); QString deviceName = params.value("name").toString();
DeviceId newDeviceId = DeviceId::createDeviceId();
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
@ -384,10 +383,10 @@ HttpReply *DevicesResource::addConfiguredDevice(const QByteArray &payload) const
DeviceSetupInfo *info; DeviceSetupInfo *info;
if (deviceDescriptorId.isNull()) { if (deviceDescriptorId.isNull()) {
qCDebug(dcRest) << "Adding device" << deviceName << "with" << deviceParams; qCDebug(dcRest) << "Adding device" << deviceName << "with" << deviceParams;
info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceName, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceParams, deviceName);
} else { } else {
qCDebug(dcRest) << "Adding discovered device" << deviceName << "with DeviceDescriptorId" << deviceDescriptorId.toString(); qCDebug(dcRest) << "Adding discovered device" << deviceName << "with DeviceDescriptorId" << deviceDescriptorId.toString();
info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceClassId, deviceName, deviceDescriptorId, deviceParams, newDeviceId); info = NymeaCore::instance()->deviceManager()->addConfiguredDevice(deviceDescriptorId, deviceParams, deviceName);
} }
connect(info, &DeviceSetupInfo::finished, httpReply, [info, httpReply](){ connect(info, &DeviceSetupInfo::finished, httpReply, [info, httpReply](){
@ -443,6 +442,7 @@ HttpReply *DevicesResource::pairDevice(const QByteArray &payload) const
} }
QString deviceName = params.value("name").toString(); QString deviceName = params.value("name").toString();
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList());
qCDebug(dcRest) << "Pair device" << deviceName << "with deviceClassId" << deviceClassId.toString(); qCDebug(dcRest) << "Pair device" << deviceName << "with deviceClassId" << deviceClassId.toString();
@ -451,10 +451,9 @@ HttpReply *DevicesResource::pairDevice(const QByteArray &payload) const
DevicePairingInfo *info; DevicePairingInfo *info;
if (params.contains("deviceDescriptorId")) { if (params.contains("deviceDescriptorId")) {
DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString()); DeviceDescriptorId deviceDescriptorId(params.value("deviceDescriptorId").toString());
info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceDescriptorId); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceDescriptorId, deviceParams, deviceName);
} else { } else {
ParamList deviceParams = JsonTypes::unpackParams(params.value("deviceParams").toList()); info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceParams, deviceName);
info = NymeaCore::instance()->deviceManager()->pairDevice(deviceClassId, deviceName, deviceParams);
} }
connect(info, &DevicePairingInfo::finished, httpReply, [info, httpReply](){ connect(info, &DevicePairingInfo::finished, httpReply, [info, httpReply](){
@ -533,7 +532,7 @@ HttpReply *DevicesResource::reconfigureDevice(Device *device, const QByteArray &
info = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceParams); info = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceParams);
} else { } else {
qCDebug(dcRest) << "Reconfigure device using the new discovered device with descriptorId:" << deviceDescriptorId.toString(); qCDebug(dcRest) << "Reconfigure device using the new discovered device with descriptorId:" << deviceDescriptorId.toString();
info = NymeaCore::instance()->deviceManager()->reconfigureDevice(device->id(), deviceDescriptorId); info = NymeaCore::instance()->deviceManager()->reconfigureDevice(deviceDescriptorId);
} }
connect(info, &DeviceSetupInfo::finished, httpReply, [httpReply, info](){ connect(info, &DeviceSetupInfo::finished, httpReply, [httpReply, info](){

View File

@ -101,19 +101,20 @@ public:
virtual DeviceDiscoveryInfo* discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) = 0; virtual DeviceDiscoveryInfo* discoverDevices(const DeviceClassId &deviceClassId, const ParamList &params) = 0;
virtual DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params, const DeviceId id = DeviceId::createDeviceId()) = 0; virtual DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const ParamList &params, const QString &name = QString()) = 0;
virtual DeviceSetupInfo* addConfiguredDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const DeviceId &deviceId = DeviceId::createDeviceId()) = 0; virtual DeviceSetupInfo* addConfiguredDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const QString &name = QString()) = 0;
virtual DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const ParamList &params, bool fromDiscoveryOrAuto = false) = 0; virtual DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const ParamList &params, const QString &name = QString()) = 0;
virtual DeviceSetupInfo* reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId) = 0; virtual DeviceSetupInfo* reconfigureDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const QString &name = QString()) = 0;
virtual DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const ParamList &params, const QString &name = QString()) = 0;
virtual DevicePairingInfo* pairDevice(const DeviceDescriptorId &deviceDescriptorId, const ParamList &params = ParamList(), const QString &name = QString()) = 0;
virtual DevicePairingInfo* pairDevice(const DeviceId &deviceId, const ParamList &params, const QString &name = QString()) = 0;
virtual DevicePairingInfo* confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &username = QString(), const QString &secret = QString()) = 0;
virtual Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) = 0; virtual Device::DeviceError editDevice(const DeviceId &deviceId, const QString &name) = 0;
virtual Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) = 0; virtual Device::DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings) = 0;
virtual DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const ParamList &params) = 0;
virtual DevicePairingInfo* pairDevice(const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId) = 0;
virtual DevicePairingInfo* confirmPairing(const PairingTransactionId &pairingTransactionId, const QString &username = QString(), const QString &secret = QString()) = 0;
virtual Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) = 0; virtual Device::DeviceError removeConfiguredDevice(const DeviceId &deviceId) = 0;
virtual DeviceActionInfo* executeAction(const Action &action) = 0; virtual DeviceActionInfo* executeAction(const Action &action) = 0;

View File

@ -34,7 +34,7 @@ DeviceUtils::DeviceUtils()
/*! Verify if the given \a params matches the given \a paramTypes. Ith \a requireAll /*! Verify if the given \a params matches the given \a paramTypes. Ith \a requireAll
* is true, all \l{ParamList}{Params} has to be valid. Returns \l{Device::DeviceError} to inform about the result.*/ * is true, all \l{ParamList}{Params} has to be valid. Returns \l{Device::DeviceError} to inform about the result.*/
Device::DeviceError DeviceUtils::verifyParams(const QList<ParamType> paramTypes, ParamList &params, bool requireAll) Device::DeviceError DeviceUtils::verifyParams(const QList<ParamType> paramTypes, const ParamList &params)
{ {
foreach (const Param &param, params) { foreach (const Param &param, params) {
Device::DeviceError result = verifyParam(paramTypes, param); Device::DeviceError result = verifyParam(paramTypes, param);
@ -42,25 +42,17 @@ Device::DeviceError DeviceUtils::verifyParams(const QList<ParamType> paramTypes,
return result; return result;
} }
} }
if (!requireAll) {
return Device::DeviceErrorNoError;
}
foreach (const ParamType &paramType, paramTypes) { foreach (const ParamType &paramType, paramTypes) {
bool found = false; bool found = false;
foreach (const Param &param, params) { foreach (const Param &param, params) {
if (paramType.id() == param.paramTypeId()) { if (paramType.id() == param.paramTypeId()) {
found = true; found = true;
break;
} }
} }
// This paramType has a default value... lets fill in that one.
if (!paramType.defaultValue().isNull() && !found) {
found = true;
params.append(Param(paramType.id(), paramType.defaultValue()));
}
if (!found) { if (!found) {
qCWarning(dcDevice) << "Missing parameter:" << paramType.name(); qCWarning(dcDevice) << "Missing parameter:" << paramType.name() << params;
return Device::DeviceErrorMissingParameter; return Device::DeviceErrorMissingParameter;
} }
} }

View File

@ -34,7 +34,7 @@ class DeviceUtils
public: public:
DeviceUtils(); DeviceUtils();
static Device::DeviceError verifyParams(const QList<ParamType> paramTypes, ParamList &params, bool requireAll = true); static Device::DeviceError verifyParams(const QList<ParamType> paramTypes, const ParamList &params);
static Device::DeviceError verifyParam(const QList<ParamType> paramTypes, const Param &param); static Device::DeviceError verifyParam(const QList<ParamType> paramTypes, const Param &param);
static Device::DeviceError verifyParam(const ParamType &paramType, const Param &param); static Device::DeviceError verifyParam(const ParamType &paramType, const Param &param);

View File

@ -3,7 +3,7 @@ NYMEA_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"
# define protocol versions # define protocol versions
JSON_PROTOCOL_VERSION_MAJOR=3 JSON_PROTOCOL_VERSION_MAJOR=3
JSON_PROTOCOL_VERSION_MINOR=1 JSON_PROTOCOL_VERSION_MINOR=2
REST_API_VERSION=1 REST_API_VERSION=1
LIBNYMEA_API_VERSION_MAJOR=3 LIBNYMEA_API_VERSION_MAJOR=3
LIBNYMEA_API_VERSION_MINOR=0 LIBNYMEA_API_VERSION_MINOR=0

View File

@ -1,4 +1,4 @@
3.1 3.2
{ {
"methods": { "methods": {
"Actions.ExecuteAction": { "Actions.ExecuteAction": {
@ -260,7 +260,7 @@
} }
}, },
"Devices.AddConfiguredDevice": { "Devices.AddConfiguredDevice": {
"description": "Add a configured device with a setupMethod of SetupMethodJustAdd. For devices with a setupMethod different than SetupMethodJustAdd, use PairDevice. Devices with CreateMethodJustAdd require all parameters to be supplied here. Devices with CreateMethodDiscovery require the use of a deviceDescriptorId. For discovered devices params are not required and will be taken from the DeviceDescriptor, however, they may be overridden by supplying parameters here.", "description": "Add a configured device with a setupMethod of SetupMethodJustAdd. For devices with a setupMethod different than SetupMethodJustAdd, use PairDevice. Devices with CreateMethodJustAdd require all parameters to be supplied here. Devices with CreateMethodDiscovery require the use of a deviceDescriptorId. For discovered devices params are not required and will be taken from the DeviceDescriptor, however, they may be overridden by supplying deviceParams.",
"params": { "params": {
"deviceClassId": "Uuid", "deviceClassId": "Uuid",
"name": "String", "name": "String",
@ -289,7 +289,7 @@
} }
}, },
"Devices.ConfirmPairing": { "Devices.ConfirmPairing": {
"description": "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" field. For SetupMethodOAuth, return the entire unmodified callback URL containing the code parameter back in the secret field.", "description": "Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the \"username\" field and the password in the \"secret\" field. For SetupMethodEnterPin and provide the PIN in the \"secret\" field. In case of SetupMethodOAuth, the previously opened web view will eventually be redirected to http://128.0.0.1:8888 and the OAuth code as query parameters to this url. Provide the entire unmodified URL in the secret field.",
"params": { "params": {
"o:secret": "String", "o:secret": "String",
"o:username": "String", "o:username": "String",
@ -452,28 +452,30 @@
} }
}, },
"Devices.PairDevice": { "Devices.PairDevice": {
"description": "Pair a device. Use this for DeviceClasses with a setupMethod different than SetupMethodJustAdd. Use deviceDescriptorId or deviceParams, depending on the createMethod of the device class. CreateMethodJustAdd takes the parameters you want to have with that device. CreateMethodDiscovery requires the use of a deviceDescriptorId, optionally, parameters can be overridden here. If success is true, the return values will contain a pairingTransactionId, a displayMessage and the setupMethod. Depending on the setupMethod you should either proceed with AddConfiguredDevice or PairDevice.", "description": "Pair a device. Use this to set up or reconfigure devices for DeviceClasses with a setupMethod different than SetupMethodJustAdd. Depending on the CreateMethod and whether a new devices is set up or an existing one is reconfigured, different parameters are required:\nCreateMethodJustAdd takes the deviceClassId and the parameters you want to have with that device.\nCreateMethodDiscovery requires the use of a deviceDescriptorId, previously obtained with DiscoverDevices. Optionally, parameters can be overridden with the give deviceParams.\nIf an existing device should be reconfigured, the deviceId of said device should be given additionally.\nIf success is true, the return values will contain a pairingTransactionId, a displayMessage and the setupMethod. Depending on the setupMethod, the application should present the use an appropriate login mask, that is, For SetupMethodDisplayPin the user should enter a pin that is displayed on the device, for SetupMethodEnterPin the application should present the given PIN so the user can enter it on the device. For SetupMethodPushButton, the displayMessage shall be presented to the user as informational hints to press a button on the device. For SetupMethodUserAndPassword a login mask for a user and password login should be presented to the user. In case of SetupMethodOAuth, an OAuth URL will be returned which shall be opened in a web view to allow the user logging in.\nOnce the login procedure has completed, the application shall proceed with ConfirmPairing, providing the results of the pairing procedure.",
"params": { "params": {
"deviceClassId": "Uuid", "o:deviceClassId": "Uuid",
"name": "String",
"o:deviceDescriptorId": "Uuid", "o:deviceDescriptorId": "Uuid",
"o:deviceId": "Uuid",
"o:deviceParams": [ "o:deviceParams": [
"$ref:Param" "$ref:Param"
] ],
"o:name": "String"
}, },
"returns": { "returns": {
"deviceError": "$ref:DeviceError", "deviceError": "$ref:DeviceError",
"o:displayMessage": "String", "o:displayMessage": "String",
"o:oAuthUrl": "String", "o:oAuthUrl": "String",
"o:pairingTransactionId": "Uuid", "o:pairingTransactionId": "Uuid",
"o:pin": "String",
"o:setupMethod": "$ref:SetupMethod" "o:setupMethod": "$ref:SetupMethod"
} }
}, },
"Devices.ReconfigureDevice": { "Devices.ReconfigureDevice": {
"description": "Edit the parameter configuration of the device. The device params will be set to the passed parameters and the setup device will be called. If the device is discoverable, you can perform a GetDiscoveredDevices before calling this method and pass the new DeviceDescriptor (rediscover). Only writable parameters can be changed. By default, every Param is writable.", "description": "Reconfigure a device. This comes down to removing and recreating a device with new parameters but keeping its device id the same (and with that keeping rules, tags etc). For devices with create method CreateMethodDiscovery, a discovery (GetDiscoveredDevices) shall be performed first and this method is to be called with a deviceDescriptorId of the re-discovered device instead of the deviceId directly. Device parameters will be taken from the discovery, but can be overridden individually here by providing them in the deviceParams parameter. Only writable parameters can be changed.",
"params": { "params": {
"deviceId": "Uuid",
"o:deviceDescriptorId": "Uuid", "o:deviceDescriptorId": "Uuid",
"o:deviceId": "Uuid",
"o:deviceParams": [ "o:deviceParams": [
"$ref:Param" "$ref:Param"
] ]

View File

@ -338,13 +338,18 @@ void TestDevices::addConfiguredDevice_data()
QVariantMap fakeparam; QVariantMap fakeparam;
fakeparam.insert("paramTypeId", ParamTypeId::createParamTypeId()); fakeparam.insert("paramTypeId", ParamTypeId::createParamTypeId());
invalidDeviceParams.append(fakeparam); invalidDeviceParams.append(fakeparam);
QTest::newRow("User, JustAdd, invalid param") << mockDeviceClassId << invalidDeviceParams << Device::DeviceErrorInvalidParameter; QTest::newRow("User, JustAdd, invalid param") << mockDeviceClassId << invalidDeviceParams << Device::DeviceErrorMissingParameter;
fakeparam.insert("value", "buhuu"); QVariantMap fakeparam2;
fakeparam2.insert("paramTypeId", mockDeviceHttpportParamTypeId.toString());
fakeparam2.insert("value", "blabla");
invalidDeviceParams.clear(); invalidDeviceParams.clear();
invalidDeviceParams.append(fakeparam); invalidDeviceParams.append(fakeparam2);
QTest::newRow("User, JustAdd, wrong param") << mockDeviceClassId << invalidDeviceParams << Device::DeviceErrorInvalidParameter; QTest::newRow("User, JustAdd, wrong param") << mockDeviceClassId << invalidDeviceParams << Device::DeviceErrorInvalidParameter;
deviceParams.clear(); deviceParams << httpportParam << fakeparam;
QTest::newRow("USer, JustAdd, additional invalid param") << mockDeviceClassId << deviceParams << Device::DeviceErrorNoError;
} }
void TestDevices::addConfiguredDevice() void TestDevices::addConfiguredDevice()
@ -1198,6 +1203,7 @@ void TestDevices::reconfigureByDiscovery()
QFETCH(Device::DeviceError, error); QFETCH(Device::DeviceError, error);
QFETCH(QVariantList, discoveryParams); QFETCH(QVariantList, discoveryParams);
qCDebug(dcTests()) << "Discovering...";
QVariantMap params; QVariantMap params;
params.insert("deviceClassId", deviceClassId); params.insert("deviceClassId", deviceClassId);
params.insert("discoveryParams", discoveryParams); params.insert("discoveryParams", discoveryParams);
@ -1211,31 +1217,33 @@ void TestDevices::reconfigureByDiscovery()
// add Discovered Device 1 port 55555 // add Discovered Device 1 port 55555
QVariantList deviceDescriptors = response.toMap().value("params").toMap().value("deviceDescriptors").toList(); QVariantList deviceDescriptors = response.toMap().value("params").toMap().value("deviceDescriptors").toList();
DeviceDescriptorId descriptorId1; DeviceDescriptorId descriptorId;
foreach (const QVariant &descriptor, deviceDescriptors) { foreach (const QVariant &descriptor, deviceDescriptors) {
// find the device with port 55555 // find the device with port 55555
if (descriptor.toMap().value("description").toString() == "55555") { if (descriptor.toMap().value("description").toString() == "55555") {
descriptorId1 = DeviceDescriptorId(descriptor.toMap().value("id").toString()); descriptorId = DeviceDescriptorId(descriptor.toMap().value("id").toString());
qDebug() << descriptorId1.toString(); qDebug() << descriptorId.toString();
break; break;
} }
} }
qDebug() << "adding descriptorId 1" << descriptorId1; QVERIFY(!descriptorId.isNull());
QVERIFY(!descriptorId1.isNull()); qCDebug(dcTests()) << "Adding...";
params.clear(); params.clear();
response.clear(); response.clear();
params.insert("deviceClassId", deviceClassId); params.insert("deviceClassId", deviceClassId);
params.insert("name", "Discoverd mock device"); params.insert("name", "Discoverd mock device");
params.insert("deviceDescriptorId", descriptorId1); params.insert("deviceDescriptorId", descriptorId);
response = injectAndWait("Devices.AddConfiguredDevice", params); response = injectAndWait("Devices.AddConfiguredDevice", params);
DeviceId deviceId(response.toMap().value("params").toMap().value("deviceId").toString()); DeviceId deviceId(response.toMap().value("params").toMap().value("deviceId").toString());
QVERIFY(!deviceId.isNull()); QVERIFY(!deviceId.isNull());
// and now rediscover, and edit the first device with the second // and now rediscover and find the existing device in the discovery results
qCDebug(dcTests()) << "Re-Discovering...";
params.clear(); params.clear();
response.clear(); response.clear();
params.insert("deviceClassId", deviceClassId); params.insert("deviceClassId", deviceClassId);
@ -1247,24 +1255,28 @@ void TestDevices::reconfigureByDiscovery()
QCOMPARE(response.toMap().value("params").toMap().value("deviceDescriptors").toList().count(), resultCount); QCOMPARE(response.toMap().value("params").toMap().value("deviceDescriptors").toList().count(), resultCount);
} }
// get the second device deviceDescriptors = response.toMap().value("params").toMap().value("deviceDescriptors").toList();
DeviceDescriptorId descriptorId2;
// find the already added device
descriptorId = DeviceDescriptorId(); // reset it first
foreach (const QVariant &descriptor, deviceDescriptors) { foreach (const QVariant &descriptor, deviceDescriptors) {
// find the device with port 55556 if (descriptor.toMap().value("deviceId").toUuid().toString() == deviceId.toString()) {
if (descriptor.toMap().value("description").toString() == "55556") { descriptorId = DeviceDescriptorId(descriptor.toMap().value("id").toString());
descriptorId2 = DeviceDescriptorId(descriptor.toMap().value("id").toString());
break; break;
} }
} }
QVERIFY(!descriptorId2.isNull()); QVERIFY2(!descriptorId.isNull(), QString("Device %1 not found in discovery results: %2").arg(deviceId.toString()).arg(qUtf8Printable(QJsonDocument::fromVariant(response).toJson())).toUtf8());
qDebug() << "edit device 1 (55555) with descriptor 2 (55556) " << descriptorId2; qCDebug(dcTests()) << "Reconfiguring...";
// EDIT
response.clear(); response.clear();
params.clear(); params.clear();
params.insert("deviceId", deviceId.toString()); params.insert("deviceDescriptorId", descriptorId);
params.insert("deviceDescriptorId", descriptorId2); // override port param
QVariantMap portParam;
portParam.insert("paramTypeId", mockDeviceHttpportParamTypeId);
portParam.insert("value", "55556");
params.insert("deviceParams", QVariantList() << portParam);
response = injectAndWait("Devices.ReconfigureDevice", params); response = injectAndWait("Devices.ReconfigureDevice", params);
verifyDeviceError(response, error); verifyDeviceError(response, error);
@ -1601,7 +1613,7 @@ void TestDevices::discoverDeviceParenting()
DeviceDescriptorId descriptorId = discoveryInfo->deviceDescriptors().first().id(); DeviceDescriptorId descriptorId = discoveryInfo->deviceDescriptors().first().id();
QSignalSpy addSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded); QSignalSpy addSpy(NymeaCore::instance()->deviceManager(), &DeviceManager::deviceAdded);
DeviceSetupInfo *setupInfo = NymeaCore::instance()->deviceManager()->addConfiguredDevice(mockParentDeviceClassId, "Mock Parent (Discovered)", descriptorId); DeviceSetupInfo *setupInfo = NymeaCore::instance()->deviceManager()->addConfiguredDevice(descriptorId, ParamList(), "Mock Parent (Discovered)");
{ {
QSignalSpy spy(setupInfo, &DeviceSetupInfo::finished); QSignalSpy spy(setupInfo, &DeviceSetupInfo::finished);
spy.wait(); spy.wait();
@ -1627,7 +1639,7 @@ void TestDevices::discoverDeviceParenting()
// Found one! Adding it... // Found one! Adding it...
addSpy.clear(); addSpy.clear();
setupInfo = NymeaCore::instance()->deviceManager()->addConfiguredDevice(mockChildDeviceClassId, "Mock Child (Discovered)", descriptorId); setupInfo = NymeaCore::instance()->deviceManager()->addConfiguredDevice(descriptorId, ParamList(), "Mock Child (Discovered)");
{ {
QSignalSpy spy(setupInfo, &DeviceSetupInfo::finished); QSignalSpy spy(setupInfo, &DeviceSetupInfo::finished);
spy.wait(); spy.wait();

View File

@ -732,19 +732,19 @@ void TestRestDevices::reconfigureByDiscovery()
// add Discovered Device 1 port 55555 // add Discovered Device 1 port 55555
request.setUrl(QUrl("https://localhost:3333/api/v1/devices")); request.setUrl(QUrl("https://localhost:3333/api/v1/devices"));
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");
DeviceDescriptorId descriptorId1; DeviceDescriptorId descriptorId;
foreach (const QVariant &descriptor, foundDevices) { foreach (const QVariant &descriptor, foundDevices) {
// find the device with port 55555 // find the device with port 55555
if (descriptor.toMap().value("description").toString() == "55555") { if (descriptor.toMap().value("description").toString() == "55555") {
descriptorId1 = DeviceDescriptorId(descriptor.toMap().value("id").toString()); descriptorId = DeviceDescriptorId(descriptor.toMap().value("id").toString());
qDebug() << descriptorId1.toString(); qDebug() << descriptorId.toString();
break; break;
} }
} }
params.clear(); params.clear();
params.insert("deviceClassId", deviceClassId); params.insert("deviceClassId", deviceClassId);
params.insert("name", "Discovered mock device"); params.insert("name", "Discovered mock device");
params.insert("deviceDescriptorId", descriptorId1.toString()); params.insert("deviceDescriptorId", descriptorId.toString());
QVariant response = postAndWait(request, params, expectedStatusCode); QVariant response = postAndWait(request, params, expectedStatusCode);
QVERIFY2(!response.isNull(), "Could not delete device"); QVERIFY2(!response.isNull(), "Could not delete device");
@ -767,23 +767,27 @@ void TestRestDevices::reconfigureByDiscovery()
foundDevices = response.toList(); foundDevices = response.toList();
QCOMPARE(foundDevices.count(), resultCount); QCOMPARE(foundDevices.count(), resultCount);
// get the second device // find the already added device
DeviceDescriptorId descriptorId2; descriptorId = DeviceDescriptorId(); // reset it first
foreach (const QVariant &descriptor, foundDevices) { foreach (const QVariant &descriptor, foundDevices) {
// find the device with port 55556 if (descriptor.toMap().value("deviceId").toUuid().toString() == deviceId.toString()) {
if (descriptor.toMap().value("description").toString() == "55556") { descriptorId = DeviceDescriptorId(descriptor.toMap().value("id").toString());
descriptorId2 = DeviceDescriptorId(descriptor.toMap().value("id").toString());
break; break;
} }
} }
QVERIFY(!descriptorId2.isNull());
qDebug() << "edit device 1 (55555) with descriptor 2 (55556) " << descriptorId2; QVERIFY(!descriptorId.isNull());
qDebug() << "edit device 1 (55555) with descriptor 2 (55556) " << descriptorId;
// RECONFIGURE // RECONFIGURE
response.clear(); response.clear();
params.clear(); params.clear();
params.insert("deviceId", deviceId.toString()); params.insert("deviceDescriptorId", descriptorId);
params.insert("deviceDescriptorId", descriptorId2); // override port param
QVariantMap portParam;
portParam.insert("paramTypeId", mockDeviceHttpportParamTypeId);
portParam.insert("value", "55556");
params.insert("deviceParams", QVariantList() << portParam);
request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString()))); request = QNetworkRequest(QUrl(QString("https://localhost:3333/api/v1/devices/%1").arg(deviceId.toString())));
request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json"); request.setHeader(QNetworkRequest::ContentTypeHeader, "text/json");