Add support for device settings

This commit is contained in:
Michael Zanetti 2019-06-06 02:56:04 +02:00
parent 7b4f317567
commit 77a3e851bd
20 changed files with 379 additions and 27 deletions

View File

@ -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 &params)
return createReply(returns);
}
JsonReply *DeviceHandler::SetDeviceSettings(const QVariantMap &params)
{
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 &params) const
{
QVariantMap returns;
@ -685,6 +711,15 @@ void DeviceHandler::deviceChangedNotification(Device *device)
emit DeviceChanged(params);
}
void DeviceHandler::deviceSettingChangedNotification(const DeviceId deviceId, const ParamTypeId &paramTypeId, 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)) {

View File

@ -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 &params);
Q_INVOKABLE JsonReply *EditDevice(const QVariantMap &params);
Q_INVOKABLE JsonReply *RemoveConfiguredDevice(const QVariantMap &params);
Q_INVOKABLE JsonReply *SetDeviceSettings(const QVariantMap &params);
Q_INVOKABLE JsonReply *GetEventTypes(const QVariantMap &params) const;
Q_INVOKABLE JsonReply *GetActionTypes(const QVariantMap &params) const;
@ -62,6 +63,7 @@ signals:
void DeviceRemoved(const QVariantMap &params);
void DeviceAdded(const QVariantMap &params);
void DeviceChanged(const QVariantMap &params);
void DeviceSettingChanged(const QVariantMap &params);
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 &paramTypeId, const QVariant &value);
void devicesDiscovered(const DeviceClassId &deviceClassId, const QList<DeviceDescriptor> deviceDescriptors);
void deviceSetupFinished(Device *device, DeviceManager::DeviceError status);

View File

@ -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 &param)
return variantMap;
}
QVariantList JsonTypes::packParams(const ParamList &paramList)
{
QVariantList ret;
foreach (const Param &param, paramList) {
ret << packParam(param);
}
return ret;
}
/*! Returns a variant map of the given \a paramDescriptor. */
QVariantMap JsonTypes::packParamDescriptor(const ParamDescriptor &paramDescriptor)
{
@ -797,11 +808,16 @@ QVariantMap JsonTypes::packDeviceClass(const DeviceClass &deviceClass, const QLo
foreach (const ParamType &paramType, 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 &paramType, 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 &param, 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;

View File

@ -194,6 +194,7 @@ public:
static QVariantMap packStateDescriptor(const StateDescriptor &stateDescriptor);
static QVariantMap packStateEvaluator(const StateEvaluator &stateEvaluator);
static QVariantMap packParam(const Param &param);
static QVariantList packParams(const ParamList &paramList);
static QVariantMap packParamType(const ParamType &paramType, const PluginId &pluginId, const QLocale &locale);
static QVariantMap packParamDescriptor(const ParamDescriptor &paramDescriptor);
static QVariantMap packVendor(const Vendor &vendor, const QLocale &locale);

View File

@ -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);

View File

@ -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);

View File

@ -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 &params)
@ -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 &params, 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 &paramTypeIdString, 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 &paramTypeIdString, 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 &param, 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 &paramTypeId, 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;

View File

@ -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 &params);
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 &paramTypeId, const QVariant &value);
private:
bool verifyPluginMetadata(const QJsonObject &data);

View File

@ -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 &paramTypeId, const QVariant &value
m_params = params;
}
ParamList Device::settings() const
{
return m_settings;
}
bool Device::hasSetting(const ParamTypeId &paramTypeId) const
{
return m_settings.hasParam(paramTypeId);
}
void Device::setSettings(const ParamList &settings)
{
m_settings = settings;
foreach (const Param &param, m_settings) {
emit settingChanged(param.paramTypeId(), param.value());
}
}
QVariant Device::setting(const ParamTypeId &paramTypeId) const
{
foreach (Param setting, m_settings) {
if (setting.paramTypeId() == paramTypeId) {
return setting.value();
}
}
return QVariant();
}
void Device::setSettingValue(const ParamTypeId &paramTypeId, 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
{

View File

@ -56,6 +56,13 @@ public:
QVariant paramValue(const ParamTypeId &paramTypeId) const;
void setParamValue(const ParamTypeId &paramName, const QVariant &value);
ParamList settings() const;
bool hasSetting(const ParamTypeId &paramTypeId) const;
void setSettings(const ParamList &settings);
QVariant setting(const ParamTypeId &paramTypeId) const;
void setSettingValue(const ParamTypeId &paramTypeId, 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 &paramTypeId, 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;

View File

@ -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) {

View File

@ -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')

View File

@ -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 &params)
{
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. */

View File

@ -87,6 +87,9 @@ public:
ParamTypes paramTypes() const;
void setParamTypes(const ParamTypes &paramTypes);
ParamTypes settingsTypes() const;
void setSettingsTypes(const ParamTypes &settingsTypes);
ParamTypes discoveryParamTypes() const;
void setDiscoveryParamTypes(const ParamTypes &paramTypes);
@ -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;

View File

@ -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

View File

@ -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",

View File

@ -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"

View File

@ -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;

View File

@ -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

View File

@ -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;