Add support for device settings
This commit is contained in:
parent
7b4f317567
commit
77a3e851bd
@ -211,6 +211,14 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
||||
returns.insert("deviceError", JsonTypes::deviceErrorRef());
|
||||
setReturns("EditDevice", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("SetDeviceSettings", "Change the settings of a device.");
|
||||
params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||
params.insert("settings", QVariantList() << JsonTypes::paramRef());
|
||||
setParams("SetDeviceSettings", params);
|
||||
returns.insert("deviceError", JsonTypes::deviceErrorRef());
|
||||
setReturns("SetDeviceSettings", returns);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("RemoveConfiguredDevice", "Remove a device from the system.");
|
||||
params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||
@ -294,10 +302,17 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
||||
setParams("DeviceAdded", params);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("DeviceChanged", "Emitted whenever the params or name of a Device changed (by EditDevice or ReconfigureDevice).");
|
||||
setDescription("DeviceChanged", "Emitted whenever the params or name of a Device are changed (by EditDevice or ReconfigureDevice).");
|
||||
params.insert("device", JsonTypes::deviceRef());
|
||||
setParams("DeviceChanged", params);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("DeviceSettingChanged", "Emitted whenever the setting of a Device is changed.");
|
||||
params.insert("deviceId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||
params.insert("paramTypeId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||
params.insert("value", JsonTypes::basicTypeToString(JsonTypes::Variant));
|
||||
setParams("DeviceSettingChanged", params);
|
||||
|
||||
params.clear(); returns.clear();
|
||||
setDescription("PluginConfigurationChanged", "Emitted whenever a plugin's configuration is changed.");
|
||||
params.insert("pluginId", JsonTypes::basicTypeToString(JsonTypes::Uuid));
|
||||
@ -309,6 +324,7 @@ DeviceHandler::DeviceHandler(QObject *parent) :
|
||||
connect(NymeaCore::instance(), &NymeaCore::deviceRemoved, this, &DeviceHandler::deviceRemovedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::deviceAdded, this, &DeviceHandler::deviceAddedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::deviceChanged, this, &DeviceHandler::deviceChangedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::deviceSettingChanged, this, &DeviceHandler::deviceSettingChangedNotification);
|
||||
connect(NymeaCore::instance(), &NymeaCore::devicesDiscovered, this, &DeviceHandler::devicesDiscovered, Qt::QueuedConnection);
|
||||
connect(NymeaCore::instance(), &NymeaCore::deviceSetupFinished, this, &DeviceHandler::deviceSetupFinished);
|
||||
connect(NymeaCore::instance(), &NymeaCore::deviceReconfigurationFinished, this, &DeviceHandler::deviceReconfigurationFinished);
|
||||
@ -565,6 +581,16 @@ JsonReply* DeviceHandler::RemoveConfiguredDevice(const QVariantMap ¶ms)
|
||||
return createReply(returns);
|
||||
}
|
||||
|
||||
JsonReply *DeviceHandler::SetDeviceSettings(const QVariantMap ¶ms)
|
||||
{
|
||||
QVariantMap returns;
|
||||
DeviceId deviceId = DeviceId(params.value("deviceId").toString());
|
||||
ParamList settings = JsonTypes::unpackParams(params.value("settings").toList());
|
||||
DeviceManager::DeviceError status = NymeaCore::instance()->deviceManager()->setDeviceSettings(deviceId, settings);
|
||||
returns.insert("deviceError", JsonTypes::deviceErrorToString(status));
|
||||
return createReply(returns);
|
||||
}
|
||||
|
||||
JsonReply* DeviceHandler::GetEventTypes(const QVariantMap ¶ms) const
|
||||
{
|
||||
QVariantMap returns;
|
||||
@ -685,6 +711,15 @@ void DeviceHandler::deviceChangedNotification(Device *device)
|
||||
emit DeviceChanged(params);
|
||||
}
|
||||
|
||||
void DeviceHandler::deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId ¶mTypeId, const QVariant &value)
|
||||
{
|
||||
QVariantMap params;
|
||||
params.insert("deviceId", deviceId);
|
||||
params.insert("paramTypeId", paramTypeId.toString());
|
||||
params.insert("value", value);
|
||||
emit DeviceSettingChanged(params);
|
||||
}
|
||||
|
||||
void DeviceHandler::devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors)
|
||||
{
|
||||
if (!m_discoverRequests.contains(deviceClassId)) {
|
||||
|
||||
@ -31,7 +31,7 @@ class DeviceHandler : public JsonHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DeviceHandler(QObject *parent = 0);
|
||||
explicit DeviceHandler(QObject *parent = nullptr);
|
||||
|
||||
QString name() const override;
|
||||
|
||||
@ -49,6 +49,7 @@ public:
|
||||
Q_INVOKABLE JsonReply *ReconfigureDevice(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *EditDevice(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *RemoveConfiguredDevice(const QVariantMap ¶ms);
|
||||
Q_INVOKABLE JsonReply *SetDeviceSettings(const QVariantMap ¶ms);
|
||||
|
||||
Q_INVOKABLE JsonReply *GetEventTypes(const QVariantMap ¶ms) const;
|
||||
Q_INVOKABLE JsonReply *GetActionTypes(const QVariantMap ¶ms) const;
|
||||
@ -62,6 +63,7 @@ signals:
|
||||
void DeviceRemoved(const QVariantMap ¶ms);
|
||||
void DeviceAdded(const QVariantMap ¶ms);
|
||||
void DeviceChanged(const QVariantMap ¶ms);
|
||||
void DeviceSettingChanged(const QVariantMap ¶ms);
|
||||
|
||||
private slots:
|
||||
void pluginConfigChanged(const PluginId &id, const ParamList &config);
|
||||
@ -74,6 +76,8 @@ private slots:
|
||||
|
||||
void deviceChangedNotification(Device *device);
|
||||
|
||||
void deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
|
||||
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
|
||||
|
||||
void deviceSetupFinished(Device *device, DeviceManager::DeviceError status);
|
||||
|
||||
@ -280,6 +280,7 @@ void JsonTypes::init()
|
||||
s_deviceClass.insert("eventTypes", QVariantList() << eventTypeRef());
|
||||
s_deviceClass.insert("actionTypes", QVariantList() << actionTypeRef());
|
||||
s_deviceClass.insert("paramTypes", QVariantList() << paramTypeRef());
|
||||
s_deviceClass.insert("settingsTypes", QVariantList() << paramTypeRef());
|
||||
s_deviceClass.insert("discoveryParamTypes", QVariantList() << paramTypeRef());
|
||||
|
||||
// Device
|
||||
@ -287,6 +288,7 @@ void JsonTypes::init()
|
||||
s_device.insert("deviceClassId", basicTypeToString(Uuid));
|
||||
s_device.insert("name", basicTypeToString(String));
|
||||
s_device.insert("params", QVariantList() << paramRef());
|
||||
s_device.insert("settings", QVariantList() << paramRef());
|
||||
QVariantMap stateValues;
|
||||
stateValues.insert("stateTypeId", basicTypeToString(Uuid));
|
||||
stateValues.insert("value", basicTypeToString(Variant));
|
||||
@ -705,6 +707,15 @@ QVariantMap JsonTypes::packParam(const Param ¶m)
|
||||
return variantMap;
|
||||
}
|
||||
|
||||
QVariantList JsonTypes::packParams(const ParamList ¶mList)
|
||||
{
|
||||
QVariantList ret;
|
||||
foreach (const Param ¶m, paramList) {
|
||||
ret << packParam(param);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*! Returns a variant map of the given \a paramDescriptor. */
|
||||
QVariantMap JsonTypes::packParamDescriptor(const ParamDescriptor ¶mDescriptor)
|
||||
{
|
||||
@ -797,11 +808,16 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass, const QLo
|
||||
foreach (const ParamType ¶mType, deviceClass.paramTypes())
|
||||
paramTypes.append(packParamType(paramType, deviceClass.pluginId(), locale));
|
||||
|
||||
QVariantList settingsTypes;
|
||||
foreach (const ParamType &settingsType, deviceClass.settingsTypes())
|
||||
settingsTypes.append(packParamType(settingsType, deviceClass.pluginId(), locale));
|
||||
|
||||
QVariantList discoveryParamTypes;
|
||||
foreach (const ParamType ¶mType, deviceClass.discoveryParamTypes())
|
||||
discoveryParamTypes.append(packParamType(paramType, deviceClass.pluginId(), locale));
|
||||
|
||||
variant.insert("paramTypes", paramTypes);
|
||||
variant.insert("settingsTypes", settingsTypes);
|
||||
variant.insert("discoveryParamTypes", discoveryParamTypes);
|
||||
variant.insert("stateTypes", stateTypes);
|
||||
variant.insert("eventTypes", eventTypes);
|
||||
@ -834,14 +850,12 @@ QVariantMap JsonTypes::packDevice(Device *device)
|
||||
variant.insert("id", device->id().toString());
|
||||
variant.insert("deviceClassId", device->deviceClassId().toString());
|
||||
variant.insert("name", device->name());
|
||||
QVariantList params;
|
||||
foreach (const Param ¶m, device->params())
|
||||
params.append(packParam(param));
|
||||
variant.insert("params", packParams(device->params()));
|
||||
variant.insert("settings", packParams(device->settings()));
|
||||
|
||||
if (!device->parentId().isNull())
|
||||
variant.insert("parentId", device->parentId().toString());
|
||||
|
||||
variant.insert("params", params);
|
||||
variant.insert("states", packDeviceStates(device));
|
||||
variant.insert("setupComplete", device->setupComplete());
|
||||
return variant;
|
||||
|
||||
@ -194,6 +194,7 @@ public:
|
||||
static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor);
|
||||
static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator);
|
||||
static QVariantMap packParam(const Param ¶m);
|
||||
static QVariantList packParams(const ParamList ¶mList);
|
||||
static QVariantMap packParamType(const ParamType ¶mType, const PluginId &pluginId, const QLocale &locale);
|
||||
static QVariantMap packParamDescriptor(const ParamDescriptor ¶mDescriptor);
|
||||
static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale);
|
||||
|
||||
@ -197,6 +197,7 @@ void NymeaCore::init() {
|
||||
connect(m_deviceManager, &DeviceManager::deviceStateChanged, this, &NymeaCore::deviceStateChanged);
|
||||
connect(m_deviceManager, &DeviceManager::deviceAdded, this, &NymeaCore::deviceAdded);
|
||||
connect(m_deviceManager, &DeviceManager::deviceChanged, this, &NymeaCore::deviceChanged);
|
||||
connect(m_deviceManager, &DeviceManager::deviceSettingChanged, this, &NymeaCore::deviceSettingChanged);
|
||||
connect(m_deviceManager, &DeviceManager::deviceRemoved, this, &NymeaCore::deviceRemoved);
|
||||
connect(m_deviceManager, &DeviceManager::deviceDisappeared, this, &NymeaCore::onDeviceDisappeared);
|
||||
connect(m_deviceManager, &DeviceManager::actionExecutionFinished, this, &NymeaCore::actionExecutionFinished);
|
||||
|
||||
@ -103,6 +103,7 @@ signals:
|
||||
void deviceRemoved(const DeviceId &deviceId);
|
||||
void deviceAdded(Device *device);
|
||||
void deviceChanged(Device *device);
|
||||
void deviceSettingChanged(const DeviceId deviceId, const ParamTypeId &settingParamTypeId, const QVariant &value);
|
||||
void actionExecuted(const ActionId &id, DeviceManager::DeviceError status);
|
||||
|
||||
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
|
||||
|
||||
@ -590,6 +590,25 @@ DeviceManager::DeviceError DeviceManager::editDevice(const DeviceId &deviceId, c
|
||||
return DeviceErrorNoError;
|
||||
}
|
||||
|
||||
DeviceManager::DeviceError DeviceManager::setDeviceSettings(const DeviceId &deviceId, const ParamList &settings)
|
||||
{
|
||||
Device *device = findConfiguredDevice(deviceId);
|
||||
if (!device) {
|
||||
qCWarning(dcDeviceManager()) << "Cannot set device settings. Device" << deviceId.toString() << "not found";
|
||||
return DeviceErrorDeviceNotFound;
|
||||
}
|
||||
ParamList effectiveSettings = settings;
|
||||
DeviceManager::DeviceError status = verifyParams(findDeviceClass(device->deviceClassId()).settingsTypes(), effectiveSettings);
|
||||
if (status != DeviceManager::DeviceErrorNoError) {
|
||||
qCWarning(dcDeviceManager()) << "Error setting device settings for device" << device->name() << device->id().toString();
|
||||
return status;
|
||||
}
|
||||
foreach (const Param &setting, settings) {
|
||||
device->setSettingValue(setting.paramTypeId(), setting.value());
|
||||
}
|
||||
return DeviceErrorNoError;
|
||||
}
|
||||
|
||||
/*! Initiates a pairing with a \l{DeviceClass}{Device} with the given \a pairingTransactionId, \a deviceClassId, \a name and \a params.
|
||||
* Returns \l{DeviceManager::DeviceError}{DeviceError} to inform about the result. */
|
||||
DeviceManager::DeviceError DeviceManager::pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const QString &name, const ParamList ¶ms)
|
||||
@ -701,7 +720,6 @@ DeviceManager::DeviceError DeviceManager::confirmPairing(const PairingTransactio
|
||||
* Returns \l{DeviceError} to inform about the result. */
|
||||
DeviceManager::DeviceError DeviceManager::addConfiguredDeviceInternal(const DeviceClassId &deviceClassId, const QString &name, const ParamList ¶ms, const DeviceId id)
|
||||
{
|
||||
ParamList effectiveParams = params;
|
||||
DeviceClass deviceClass = findDeviceClass(deviceClassId);
|
||||
if (deviceClass.id().isNull()) {
|
||||
return DeviceErrorDeviceClassNotFound;
|
||||
@ -711,11 +729,6 @@ DeviceManager::DeviceError DeviceManager::addConfiguredDeviceInternal(const Devi
|
||||
return DeviceErrorCreationMethodNotSupported;
|
||||
}
|
||||
|
||||
DeviceError result = verifyParams(deviceClass.paramTypes(), effectiveParams);
|
||||
if (result != DeviceErrorNoError) {
|
||||
return result;
|
||||
}
|
||||
|
||||
foreach(Device *device, m_configuredDevices) {
|
||||
if (device->id() == id) {
|
||||
return DeviceErrorDuplicateUuid;
|
||||
@ -727,6 +740,12 @@ DeviceManager::DeviceError DeviceManager::addConfiguredDeviceInternal(const Devi
|
||||
return DeviceErrorPluginNotFound;
|
||||
}
|
||||
|
||||
ParamList effectiveParams = params;
|
||||
DeviceError paramsResult = verifyParams(deviceClass.paramTypes(), effectiveParams);
|
||||
if (paramsResult != DeviceErrorNoError) {
|
||||
return paramsResult;
|
||||
}
|
||||
|
||||
Device *device = new Device(plugin->pluginId(), id, deviceClassId, this);
|
||||
if (name.isEmpty()) {
|
||||
device->setName(deviceClass.name());
|
||||
@ -735,6 +754,11 @@ DeviceManager::DeviceError DeviceManager::addConfiguredDeviceInternal(const Devi
|
||||
}
|
||||
device->setParams(effectiveParams);
|
||||
|
||||
ParamList settings;
|
||||
verifyParams(deviceClass.settingsTypes(), settings);
|
||||
qCDebug(dcDeviceManager()) << "Adding device settings" << settings;
|
||||
device->setSettings(settings);
|
||||
|
||||
DeviceSetupStatus status = setupDevice(device);
|
||||
switch (status) {
|
||||
case DeviceSetupStatusFailure:
|
||||
@ -1191,9 +1215,37 @@ void DeviceManager::loadConfiguredDevices()
|
||||
params.append(Param(ParamTypeId(paramTypeIdString), settings.value(paramTypeIdString)));
|
||||
}
|
||||
}
|
||||
|
||||
device->setParams(params);
|
||||
settings.endGroup(); // Params
|
||||
|
||||
ParamList deviceSettings;
|
||||
settings.beginGroup("Settings");
|
||||
if (!settings.childGroups().isEmpty()) {
|
||||
foreach (const QString ¶mTypeIdString, settings.childGroups()) {
|
||||
ParamTypeId paramTypeId(paramTypeIdString);
|
||||
ParamType paramType = deviceClass.settingsTypes().findById(paramTypeId);
|
||||
if (!paramType.isValid()) {
|
||||
qCWarning(dcDeviceManager()) << "Not loading Setting for device" << device << "because the ParamType for the saved Setting" << ParamTypeId(paramTypeIdString).toString() << "could not be found.";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Note: since nymea 0.12.2
|
||||
QVariant paramValue;
|
||||
settings.beginGroup(paramTypeIdString);
|
||||
paramValue = settings.value("value", paramType.defaultValue());
|
||||
paramValue.convert(settings.value("type").toInt());
|
||||
deviceSettings.append(Param(paramTypeId, paramValue));
|
||||
settings.endGroup(); // ParamId
|
||||
}
|
||||
} else {
|
||||
foreach (const QString ¶mTypeIdString, settings.allKeys()) {
|
||||
params.append(Param(ParamTypeId(paramTypeIdString), settings.value(paramTypeIdString)));
|
||||
}
|
||||
}
|
||||
verifyParams(deviceClass.settingsTypes(), deviceSettings);
|
||||
device->setSettings(deviceSettings);
|
||||
|
||||
settings.endGroup(); // Settings
|
||||
settings.endGroup(); // DeviceId
|
||||
|
||||
// We always add the device to the list in this case. If its in the storedDevices
|
||||
@ -1246,6 +1298,16 @@ void DeviceManager::storeConfiguredDevices()
|
||||
}
|
||||
settings.endGroup(); // Params
|
||||
|
||||
settings.beginGroup("Settings");
|
||||
foreach (const Param ¶m, device->settings()) {
|
||||
settings.beginGroup(param.paramTypeId().toString());
|
||||
settings.setValue("type", static_cast<int>(param.value().type()));
|
||||
settings.setValue("value", param.value());
|
||||
settings.endGroup(); // ParamTypeId
|
||||
}
|
||||
settings.endGroup(); // Settings
|
||||
|
||||
|
||||
settings.endGroup(); // DeviceId
|
||||
}
|
||||
settings.endGroup(); // DeviceConfig
|
||||
@ -1333,7 +1395,8 @@ void DeviceManager::slotDeviceSetupFinished(Device *device, DeviceManager::Devic
|
||||
return;
|
||||
}
|
||||
|
||||
connect(device, SIGNAL(stateValueChanged(QUuid,QVariant)), this, SLOT(slotDeviceStateValueChanged(QUuid,QVariant)));
|
||||
connect(device, &Device::stateValueChanged, this, &DeviceManager::slotDeviceStateValueChanged);
|
||||
connect(device, &Device::settingChanged, this, &DeviceManager::slotDeviceSettingChanged);
|
||||
|
||||
device->setupCompleted();
|
||||
emit deviceSetupFinished(device, DeviceManager::DeviceErrorNoError);
|
||||
@ -1417,6 +1480,10 @@ void DeviceManager::slotPairingFinished(const PairingTransactionId &pairingTrans
|
||||
emit pairingFinished(pairingTransactionId, DeviceErrorNoError, deviceId);
|
||||
|
||||
device->setParams(params);
|
||||
ParamList settings;
|
||||
// Use verifyParams to populate it with defaults
|
||||
verifyParams(deviceClass.settingsTypes(), settings);
|
||||
device->setSettings(settings);
|
||||
|
||||
DeviceSetupStatus setupStatus = setupDevice(device);
|
||||
switch (setupStatus) {
|
||||
@ -1482,6 +1549,9 @@ void DeviceManager::onAutoDevicesAppeared(const DeviceClassId &deviceClassId, co
|
||||
device->m_autoCreated = true;
|
||||
device->setName(deviceDescriptor.title());
|
||||
device->setParams(deviceDescriptor.params());
|
||||
ParamList settings;
|
||||
verifyParams(deviceClass.settingsTypes(), settings);
|
||||
device->setSettings(settings);
|
||||
device->setParentId(deviceDescriptor.parentDeviceId());
|
||||
|
||||
DeviceSetupStatus setupStatus = setupDevice(device);
|
||||
@ -1551,7 +1621,7 @@ void DeviceManager::cleanupDeviceStateCache()
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value)
|
||||
void DeviceManager::slotDeviceStateValueChanged(const StateTypeId &stateTypeId, const QVariant &value)
|
||||
{
|
||||
Device *device = qobject_cast<Device*>(sender());
|
||||
if (!device) {
|
||||
@ -1564,6 +1634,16 @@ void DeviceManager::slotDeviceStateValueChanged(const QUuid &stateTypeId, const
|
||||
emit eventTriggered(event);
|
||||
}
|
||||
|
||||
void DeviceManager::slotDeviceSettingChanged(const ParamTypeId ¶mTypeId, const QVariant &value)
|
||||
{
|
||||
Device *device = qobject_cast<Device*>(sender());
|
||||
if (!device) {
|
||||
return;
|
||||
}
|
||||
storeConfiguredDevices();
|
||||
emit deviceSettingChanged(device->id(), paramTypeId, value);
|
||||
}
|
||||
|
||||
bool DeviceManager::verifyPluginMetadata(const QJsonObject &data)
|
||||
{
|
||||
QStringList requiredFields;
|
||||
@ -1602,7 +1682,8 @@ DeviceManager::DeviceSetupStatus DeviceManager::setupDevice(Device *device)
|
||||
return status;
|
||||
}
|
||||
|
||||
connect(device, SIGNAL(stateValueChanged(QUuid,QVariant)), this, SLOT(slotDeviceStateValueChanged(QUuid,QVariant)));
|
||||
connect(device, &Device::stateValueChanged, this, &DeviceManager::slotDeviceStateValueChanged);
|
||||
connect(device, &Device::settingChanged, this, &DeviceManager::slotDeviceSettingChanged);
|
||||
|
||||
device->setupCompleted();
|
||||
return status;
|
||||
|
||||
@ -119,6 +119,7 @@ public:
|
||||
DeviceError reconfigureDevice(const DeviceId &deviceId, const DeviceDescriptorId &deviceDescriptorId);
|
||||
|
||||
DeviceError editDevice(const DeviceId &deviceId, const QString &name);
|
||||
DeviceError setDeviceSettings(const DeviceId &deviceId, const ParamList &settings);
|
||||
|
||||
DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const QString &name, const ParamList ¶ms);
|
||||
DeviceError pairDevice(const PairingTransactionId &pairingTransactionId, const DeviceClassId &deviceClassId, const QString &name, const DeviceDescriptorId &deviceDescriptorId);
|
||||
@ -141,11 +142,12 @@ signals:
|
||||
void loaded();
|
||||
void pluginConfigChanged(const PluginId &id, const ParamList &config);
|
||||
void eventTriggered(const Event &event);
|
||||
void deviceStateChanged(Device *device, const QUuid &stateTypeId, const QVariant &value);
|
||||
void deviceStateChanged(Device *device, const StateTypeId &stateTypeId, const QVariant &value);
|
||||
void deviceRemoved(const DeviceId &deviceId);
|
||||
void deviceDisappeared(const DeviceId &deviceId);
|
||||
void deviceAdded(Device *device);
|
||||
void deviceChanged(Device *device);
|
||||
void deviceSettingChanged(const DeviceId deviceId, const ParamTypeId &settingParamTypeId, const QVariant &value);
|
||||
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> &devices);
|
||||
void deviceSetupFinished(Device *device, DeviceError status);
|
||||
void deviceReconfigurationFinished(Device *device, DeviceError status);
|
||||
@ -171,7 +173,8 @@ private slots:
|
||||
void cleanupDeviceStateCache();
|
||||
|
||||
// Only connect this to Devices. It will query the sender()
|
||||
void slotDeviceStateValueChanged(const QUuid &stateTypeId, const QVariant &value);
|
||||
void slotDeviceStateValueChanged(const StateTypeId &stateTypeId, const QVariant &value);
|
||||
void slotDeviceSettingChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
|
||||
private:
|
||||
bool verifyPluginMetadata(const QJsonObject &data);
|
||||
|
||||
@ -34,7 +34,7 @@
|
||||
\sa DeviceClass, DeviceDescriptor
|
||||
*/
|
||||
|
||||
/*! \fn void Device::stateValueChanged(const QUuid &stateTypeId, const QVariant &value)
|
||||
/*! \fn void Device::stateValueChanged(const StateTypeId &stateTypeId, const QVariant &value)
|
||||
This signal is emitted when the \l{State} with the given \a stateTypeId changed.
|
||||
The \a value parameter describes the new value of the State.
|
||||
*/
|
||||
@ -138,6 +138,59 @@ void Device::setParamValue(const ParamTypeId ¶mTypeId, const QVariant &value
|
||||
m_params = params;
|
||||
}
|
||||
|
||||
ParamList Device::settings() const
|
||||
{
|
||||
return m_settings;
|
||||
}
|
||||
|
||||
bool Device::hasSetting(const ParamTypeId ¶mTypeId) const
|
||||
{
|
||||
return m_settings.hasParam(paramTypeId);
|
||||
}
|
||||
|
||||
void Device::setSettings(const ParamList &settings)
|
||||
{
|
||||
m_settings = settings;
|
||||
foreach (const Param ¶m, m_settings) {
|
||||
emit settingChanged(param.paramTypeId(), param.value());
|
||||
}
|
||||
}
|
||||
|
||||
QVariant Device::setting(const ParamTypeId ¶mTypeId) const
|
||||
{
|
||||
foreach (Param setting, m_settings) {
|
||||
if (setting.paramTypeId() == paramTypeId) {
|
||||
return setting.value();
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void Device::setSettingValue(const ParamTypeId ¶mTypeId, const QVariant &value)
|
||||
{
|
||||
ParamList settings;
|
||||
bool found = false;
|
||||
bool changed = false;
|
||||
foreach (Param param, m_settings) {
|
||||
if (param.paramTypeId() == paramTypeId) {
|
||||
found = true;
|
||||
if (param.value() != value) {
|
||||
param.setValue(value);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
settings << param;
|
||||
}
|
||||
if (!found) {
|
||||
qCWarning(dcDeviceManager()) << "Device" << m_name << "(" << m_id.toString() << ") does not have a setting with id" << paramTypeId;
|
||||
return;
|
||||
}
|
||||
if (changed) {
|
||||
m_settings = settings;
|
||||
emit settingChanged(paramTypeId, value);
|
||||
}
|
||||
}
|
||||
|
||||
/*! Returns the states of this Device. It must match the \l{StateType} description in the associated \l{DeviceClass}. */
|
||||
QList<State> Device::states() const
|
||||
{
|
||||
|
||||
@ -56,6 +56,13 @@ public:
|
||||
QVariant paramValue(const ParamTypeId ¶mTypeId) const;
|
||||
void setParamValue(const ParamTypeId ¶mName, const QVariant &value);
|
||||
|
||||
ParamList settings() const;
|
||||
bool hasSetting(const ParamTypeId ¶mTypeId) const;
|
||||
void setSettings(const ParamList &settings);
|
||||
|
||||
QVariant setting(const ParamTypeId ¶mTypeId) const;
|
||||
void setSettingValue(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
|
||||
QList<State> states() const;
|
||||
bool hasState(const StateTypeId &stateTypeId) const;
|
||||
void setStates(const QList<State> &states);
|
||||
@ -72,7 +79,8 @@ public:
|
||||
bool autoCreated() const;
|
||||
|
||||
signals:
|
||||
void stateValueChanged(const QUuid &stateTypeId, const QVariant &value);
|
||||
void stateValueChanged(const StateTypeId &stateTypeId, const QVariant &value);
|
||||
void settingChanged(const ParamTypeId ¶mTypeId, const QVariant &value);
|
||||
void nameChanged();
|
||||
|
||||
private:
|
||||
@ -89,6 +97,7 @@ private:
|
||||
PluginId m_pluginId;
|
||||
QString m_name;
|
||||
ParamList m_params;
|
||||
ParamList m_settings;
|
||||
QList<State> m_states;
|
||||
bool m_setupComplete = false;
|
||||
bool m_autoCreated = false;
|
||||
|
||||
@ -603,6 +603,15 @@ void DevicePlugin::loadMetaData()
|
||||
deviceClass.setParamTypes(paramTypesVerification.second);
|
||||
}
|
||||
|
||||
// Read settings
|
||||
QPair<bool, QList<ParamType> > settingsTypesVerification = parseParamTypes(deviceClassObject.value("settingsTypes").toArray());
|
||||
if (!settingsTypesVerification.first) {
|
||||
broken = true;
|
||||
break;
|
||||
} else {
|
||||
deviceClass.setSettingsTypes(settingsTypesVerification.second);
|
||||
}
|
||||
|
||||
// Read discover params
|
||||
QPair<bool, QList<ParamType> > discoveryParamVerification = parseParamTypes(deviceClassObject.value("discoveryParamTypes").toArray());
|
||||
if (!discoveryParamVerification.first) {
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||
# #
|
||||
# Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> #
|
||||
# Copyright (C) 2014-2018 Michael Zanetti <michael.zanetti@guh.io> #
|
||||
# Copyright (C) 2014-2019 Michael Zanetti <michael.zanetti@nymea.io> #
|
||||
# #
|
||||
# This file is part of nymea. #
|
||||
# #
|
||||
@ -79,6 +79,7 @@ def extractParamTypes(paramTypes, deviceClassName, typeClass, typeName):
|
||||
for paramType in paramTypes:
|
||||
try:
|
||||
variableName = '%sParamTypeId' % (deviceClassName + typeName[0].capitalize() + typeName[1:] + typeClass + paramType['name'][0].capitalize() + paramType['name'][1:])
|
||||
print("....variable:", variableName)
|
||||
if not variableName in variableNames:
|
||||
variableNames.append(variableName)
|
||||
printInfo('Define ParamTypeId %s = %s' % (variableName, paramType['id']))
|
||||
@ -138,6 +139,9 @@ def extractDeviceClasses(deviceClasses):
|
||||
if 'paramTypes' in deviceClass:
|
||||
extractParamTypes(deviceClass['paramTypes'], deviceClass['name'], "", 'device')
|
||||
|
||||
if 'settingsTypes' in deviceClass:
|
||||
extractParamTypes(deviceClass['settingsTypes'], deviceClass['name'], "", 'settings')
|
||||
|
||||
if 'discoveryParamTypes' in deviceClass:
|
||||
extractParamTypes(deviceClass['discoveryParamTypes'], deviceClass['name'], "", 'discovery')
|
||||
|
||||
|
||||
@ -220,13 +220,27 @@ ParamTypes DeviceClass::paramTypes() const
|
||||
return m_paramTypes;
|
||||
}
|
||||
|
||||
/*! Set the \a params of this DeviceClass. \{Device}{Devices} created
|
||||
from this \l{DeviceClass} must have their actions matching to this template. */
|
||||
/*! Set the \a paramsTypes of this DeviceClass. \{Device}{Devices} created
|
||||
from this \l{DeviceClass} must have their params matching to this template. */
|
||||
void DeviceClass::setParamTypes(const ParamTypes ¶ms)
|
||||
{
|
||||
m_paramTypes = params;
|
||||
}
|
||||
|
||||
/*! Returns the settings description of this DeviceClass. \{Device}{Devices} created
|
||||
from this \l{DeviceClass} must have their settings matching to this template. */
|
||||
ParamTypes DeviceClass::settingsTypes() const
|
||||
{
|
||||
return m_settingsTypes;
|
||||
}
|
||||
|
||||
/*! Set the \a settingsTypes of this DeviceClass. \{Device}{Devices} created
|
||||
from this \l{DeviceClass} must have their settings matching to this template. */
|
||||
void DeviceClass::setSettingsTypes(const ParamTypes &settingsTypes)
|
||||
{
|
||||
m_settingsTypes = settingsTypes;
|
||||
}
|
||||
|
||||
/*! Returns the discovery params description of this DeviceClass. \{Device}{Devices} created
|
||||
from this \l{DeviceClass} must have their params matching to this template. */
|
||||
ParamTypes DeviceClass::discoveryParamTypes() const
|
||||
@ -305,7 +319,7 @@ QStringList DeviceClass::typeProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "createMethods" << "setupMethod"
|
||||
<< "interfaces" << "pairingInfo" << "discoveryParamTypes" << "discoveryParamTypes"
|
||||
<< "paramTypes" << "stateTypes" << "actionTypes" << "eventTypes";
|
||||
<< "paramTypes" << "settingsTypes" << "stateTypes" << "actionTypes" << "eventTypes";
|
||||
}
|
||||
|
||||
/*! Returns a list of mandatory JSON properties a DeviceClass JSON definition must have. */
|
||||
|
||||
@ -87,6 +87,9 @@ public:
|
||||
ParamTypes paramTypes() const;
|
||||
void setParamTypes(const ParamTypes ¶mTypes);
|
||||
|
||||
ParamTypes settingsTypes() const;
|
||||
void setSettingsTypes(const ParamTypes &settingsTypes);
|
||||
|
||||
ParamTypes discoveryParamTypes() const;
|
||||
void setDiscoveryParamTypes(const ParamTypes ¶mTypes);
|
||||
|
||||
@ -117,6 +120,7 @@ private:
|
||||
EventTypes m_eventTypes;
|
||||
ActionTypes m_actionTypes;
|
||||
ParamTypes m_paramTypes;
|
||||
ParamTypes m_settingsTypes;
|
||||
ParamTypes m_discoveryParamTypes;
|
||||
CreateMethods m_createMethods;
|
||||
SetupMethod m_setupMethod;
|
||||
|
||||
@ -3,7 +3,7 @@ NYMEA_VERSION_STRING=$$system('dpkg-parsechangelog | sed -n -e "s/^Version: //p"
|
||||
|
||||
# define protocol versions
|
||||
JSON_PROTOCOL_VERSION_MAJOR=2
|
||||
JSON_PROTOCOL_VERSION_MINOR=1
|
||||
JSON_PROTOCOL_VERSION_MINOR=2
|
||||
REST_API_VERSION=1
|
||||
|
||||
COPYRIGHT_YEAR_FROM=2013
|
||||
|
||||
@ -65,6 +65,15 @@
|
||||
"defaultValue": false
|
||||
}
|
||||
],
|
||||
"settingsTypes": [
|
||||
{
|
||||
"id": "367f7ba4-5039-47be-abd8-59cc8eaf4b9a",
|
||||
"name": "setting1",
|
||||
"displayName": "Setting 1",
|
||||
"type": "int",
|
||||
"defaultValue": 5
|
||||
}
|
||||
],
|
||||
"stateTypes": [
|
||||
{
|
||||
"id": "80baec19-54de-4948-ac46-31eabfaceb83",
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
2.1
|
||||
2.2
|
||||
{
|
||||
"methods": {
|
||||
"Actions.ExecuteAction": {
|
||||
@ -447,6 +447,18 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"Devices.SetDeviceSettings": {
|
||||
"description": "Change the settings of a device.",
|
||||
"params": {
|
||||
"deviceId": "Uuid",
|
||||
"settings": [
|
||||
"$ref:Param"
|
||||
]
|
||||
},
|
||||
"returns": {
|
||||
"deviceError": "$ref:DeviceError"
|
||||
}
|
||||
},
|
||||
"Devices.SetPluginConfiguration": {
|
||||
"description": "Set a plugin's params.",
|
||||
"params": {
|
||||
@ -1101,7 +1113,7 @@
|
||||
}
|
||||
},
|
||||
"Devices.DeviceChanged": {
|
||||
"description": "Emitted whenever the params or name of a Device changed (by EditDevice or ReconfigureDevice).",
|
||||
"description": "Emitted whenever the params or name of a Device are changed (by EditDevice or ReconfigureDevice).",
|
||||
"params": {
|
||||
"device": "$ref:Device"
|
||||
}
|
||||
@ -1112,6 +1124,14 @@
|
||||
"deviceId": "Uuid"
|
||||
}
|
||||
},
|
||||
"Devices.DeviceSettingChanged": {
|
||||
"description": "Emitted whenever the setting of a Device is changed.",
|
||||
"params": {
|
||||
"deviceId": "Uuid",
|
||||
"paramTypeId": "Uuid",
|
||||
"value": "Variant"
|
||||
}
|
||||
},
|
||||
"Devices.PluginConfigurationChanged": {
|
||||
"description": "Emitted whenever a plugin's configuration is changed.",
|
||||
"params": {
|
||||
@ -1366,6 +1386,9 @@
|
||||
"params": [
|
||||
"$ref:Param"
|
||||
],
|
||||
"settings": [
|
||||
"$ref:Param"
|
||||
],
|
||||
"setupComplete": "Bool",
|
||||
"states": [
|
||||
{
|
||||
@ -1397,6 +1420,9 @@
|
||||
"$ref:ParamType"
|
||||
],
|
||||
"pluginId": "Uuid",
|
||||
"settingsTypes": [
|
||||
"$ref:ParamType"
|
||||
],
|
||||
"setupMethod": "$ref:SetupMethod",
|
||||
"stateTypes": [
|
||||
"$ref:StateType"
|
||||
|
||||
@ -84,6 +84,8 @@ private slots:
|
||||
void editDevices_data();
|
||||
void editDevices();
|
||||
|
||||
void testDeviceSettings();
|
||||
|
||||
void reconfigureDevices_data();
|
||||
void reconfigureDevices();
|
||||
|
||||
@ -867,6 +869,86 @@ void TestDevices::editDevices()
|
||||
verifyDeviceError(response);
|
||||
}
|
||||
|
||||
void TestDevices::testDeviceSettings()
|
||||
{
|
||||
// add device
|
||||
QVariantList deviceParams;
|
||||
QVariantMap httpportParam;
|
||||
httpportParam.insert("paramTypeId", httpportParamTypeId);
|
||||
httpportParam.insert("value", 8889);
|
||||
deviceParams.append(httpportParam);
|
||||
|
||||
QVariantMap params;
|
||||
params.insert("deviceClassId", mockDeviceClassId);
|
||||
params.insert("name", "Mock");
|
||||
params.insert("deviceParams", deviceParams);
|
||||
QVariant response = injectAndWait("Devices.AddConfiguredDevice", params);
|
||||
verifyDeviceError(response);
|
||||
DeviceId deviceId = DeviceId(response.toMap().value("params").toMap().value("deviceId").toString());
|
||||
|
||||
// check if default settings are loaded
|
||||
params.clear();
|
||||
params.insert("deviceId", deviceId);
|
||||
response = injectAndWait("Devices.GetConfiguredDevices", params);
|
||||
QVariantList devices = response.toMap().value("params").toMap().value("devices").toList();
|
||||
QVERIFY2(devices.count() == 1, "Error creating device");
|
||||
|
||||
QVariantMap device = devices.first().toMap();
|
||||
QVERIFY2(DeviceId(device.value("id").toString()) == deviceId, "DeviceId not matching");
|
||||
|
||||
QVariantList settings = device.value("settings").toList();
|
||||
QCOMPARE(settings.count(), 1);
|
||||
|
||||
QCOMPARE(settings.first().toMap().value("paramTypeId").toString(), mockSetting1ParamTypeId.toString());
|
||||
QVERIFY2(settings.first().toMap().value("value").toInt() == 5, "Setting 1 default value not matching");
|
||||
|
||||
// change a setting
|
||||
params.clear();
|
||||
params.insert("deviceId", deviceId);
|
||||
settings.clear();
|
||||
QVariantMap setting;
|
||||
setting.insert("paramTypeId", mockSetting1ParamTypeId);
|
||||
setting.insert("value", 7);
|
||||
settings.append(setting);
|
||||
params.insert("settings", settings);
|
||||
response = injectAndWait("Devices.SetDeviceSettings", params);
|
||||
|
||||
// Check if the change happened
|
||||
params.clear();
|
||||
params.insert("deviceId", deviceId);
|
||||
response = injectAndWait("Devices.GetConfiguredDevices", params);
|
||||
devices = response.toMap().value("params").toMap().value("devices").toList();
|
||||
QVERIFY2(devices.count() == 1, "Error creating device");
|
||||
|
||||
device = devices.first().toMap();
|
||||
QVERIFY2(DeviceId(device.value("id").toString()) == deviceId, "DeviceId not matching");
|
||||
|
||||
settings = device.value("settings").toList();
|
||||
QCOMPARE(settings.count(), 1);
|
||||
|
||||
QCOMPARE(settings.first().toMap().value("paramTypeId").toString(), mockSetting1ParamTypeId.toString());
|
||||
QVERIFY2(settings.first().toMap().value("value").toInt() == 7, "Setting 1 changed value not matching");
|
||||
|
||||
restartServer();
|
||||
|
||||
// Check if the change persisted
|
||||
params.clear();
|
||||
params.insert("deviceId", deviceId);
|
||||
response = injectAndWait("Devices.GetConfiguredDevices", params);
|
||||
devices = response.toMap().value("params").toMap().value("devices").toList();
|
||||
QVERIFY2(devices.count() == 1, "Error creating device");
|
||||
|
||||
device = devices.first().toMap();
|
||||
QVERIFY2(DeviceId(device.value("id").toString()) == deviceId, "DeviceId not matching");
|
||||
|
||||
settings = device.value("settings").toList();
|
||||
QCOMPARE(settings.count(), 1);
|
||||
|
||||
QCOMPARE(settings.first().toMap().value("paramTypeId").toString(), mockSetting1ParamTypeId.toString());
|
||||
QVERIFY2(settings.first().toMap().value("value").toInt() == 7, "Setting 1 changed value not persisting restart");
|
||||
|
||||
}
|
||||
|
||||
void TestDevices::reconfigureDevices_data()
|
||||
{
|
||||
QVariantList asyncChangeDeviceParams;
|
||||
|
||||
@ -80,6 +80,7 @@ ParamTypeId ip4ParamTypeId = ParamTypeId("9e5f86a0-4bb3-4892-bff8-3fc4032af6e2")
|
||||
ParamTypeId ip6ParamTypeId = ParamTypeId("43bf3832-dd48-4090-a836-656e8b60216e");
|
||||
ParamTypeId urlParamTypeId = ParamTypeId("fa67229f-fcef-496f-b671-59a4b48f3ab5");
|
||||
ParamTypeId macParamTypeId = ParamTypeId("e93db587-7919-48f3-8c88-1651de63c765");
|
||||
ParamTypeId mockSetting1ParamTypeId = ParamTypeId("367f7ba4-5039-47be-abd8-59cc8eaf4b9a");
|
||||
|
||||
|
||||
// Parent device
|
||||
|
||||
@ -82,6 +82,7 @@ extern ParamTypeId ip4ParamTypeId;
|
||||
extern ParamTypeId ip6ParamTypeId;
|
||||
extern ParamTypeId urlParamTypeId;
|
||||
extern ParamTypeId macParamTypeId;
|
||||
extern ParamTypeId mockSetting1ParamTypeId;
|
||||
|
||||
// Parent / Child device
|
||||
extern EventTypeId mockParentChildEventId;
|
||||
|
||||
Reference in New Issue
Block a user