diff --git a/libnymea-app-core/configuration/networkmanager.cpp b/libnymea-app-core/configuration/networkmanager.cpp
index 4bbd4b72..dddf7d65 100644
--- a/libnymea-app-core/configuration/networkmanager.cpp
+++ b/libnymea-app-core/configuration/networkmanager.cpp
@@ -27,7 +27,7 @@ void NetworkManager::init()
{
m_jsonClient->sendCommand("NetworkManager.GetNetworkStatus", QVariantMap(), this, "getStatusReply");
m_jsonClient->sendCommand("NetworkManager.GetNetworkDevices", QVariantMap(), this, "getDevicesReply");
- m_jsonClient->sendCommand("NetworkManager.GetWirelessAccessPoints", QVariantMap(), this, "getAccessPointsReply");
+// m_jsonClient->sendCommand("NetworkManager.GetWirelessAccessPoints", QVariantMap(), this, "getAccessPointsReply");
}
NetworkManager::NetworkManagerState NetworkManager::state() const
@@ -95,7 +95,7 @@ void NetworkManager::disconnectInterface(const QString &interface)
void NetworkManager::getStatusReply(const QVariantMap ¶ms)
{
- qDebug() << "NetworkManager reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
+// qDebug() << "NetworkManager reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
QVariantMap statusMap = params.value("params").toMap().value("status").toMap();
@@ -120,7 +120,7 @@ void NetworkManager::getStatusReply(const QVariantMap ¶ms)
void NetworkManager::getDevicesReply(const QVariantMap ¶ms)
{
- qDebug() << "Dwvices reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
+// qDebug() << "Devices reply" << qUtf8Printable(QJsonDocument::fromVariant(params).toJson(QJsonDocument::Indented));
foreach (const QVariant &deviceVariant, params.value("params").toMap().value("wiredNetworkDevices").toList()) {
QVariantMap deviceMap = deviceVariant.toMap();
diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp
index 58e41e52..07dcb704 100644
--- a/libnymea-app-core/devicemanager.cpp
+++ b/libnymea-app-core/devicemanager.cpp
@@ -93,7 +93,7 @@ void DeviceManager::notificationReceived(const QVariantMap &data)
{
QString notification = data.value("notification").toString();
if (notification == "Devices.StateChanged") {
-// qDebug() << "Device state changed" << data.value("params");
+ qDebug() << "Device state changed" << data.value("params");
Device *dev = m_devices->getDevice(data.value("params").toMap().value("deviceId").toUuid());
if (!dev) {
qWarning() << "Device state change notification received for an unknown device";
@@ -132,6 +132,22 @@ void DeviceManager::notificationReceived(const QVariantMap &data)
return;
}
qDebug() << "*** device unpacked" << oldDevice->stateValue("98e4476f-e745-4a7f-b795-19269cb70c40");
+ } else if (notification == "Devices.DeviceSettingChanged") {
+ QUuid deviceId = data.value("params").toMap().value("deviceId").toUuid();
+ QString paramTypeId = data.value("params").toMap().value("paramTypeId").toString();
+ QVariant value = data.value("params").toMap().value("value");
+ qDebug() << "Device settings changed notification for device" << deviceId << data.value("params").toMap().value("settings").toList();
+ Device *dev = m_devices->getDevice(deviceId);
+ if (!dev) {
+ qWarning() << "Device settings changed notification for a device we don't know" << deviceId.toString();
+ return;
+ }
+ Param *p = dev->settings()->getParam(paramTypeId);
+ if (!p) {
+ qWarning() << "Device" << dev->name() << dev->id().toString() << "does not have a setting of id" << paramTypeId;
+ return;
+ }
+ p->setValue(value);
} else {
qWarning() << "DeviceManager unhandled device notification received" << notification;
}
@@ -239,9 +255,9 @@ void DeviceManager::getConfiguredDevicesResponse(const QVariantMap ¶ms)
device->setStateValue(stateTypeId, value);
// qDebug() << "Set device state value:" << device->stateValue(stateTypeId) << value;
}
-// qDebug() << "Configured Device JSON:" << qUtf8Printable(QJsonDocument::fromVariant(deviceVariant).toJson(QJsonDocument::Indented));
+ qDebug() << "Configured Device JSON:" << qUtf8Printable(QJsonDocument::fromVariant(deviceVariant).toJson(QJsonDocument::Indented));
devices()->addDevice(device);
-// qDebug() << "*** Added device:" << endl << device;
+ qDebug() << "*** Added device:" << endl << device;
}
}
m_fetchingData = false;
@@ -373,6 +389,14 @@ void DeviceManager::editDevice(const QUuid &deviceId, const QString &name)
m_jsonClient->sendCommand("Devices.EditDevice", params, this, "editDeviceResponse");
}
+void DeviceManager::setDeviceSettings(const QUuid &deviceId, const QVariantList &settings)
+{
+ QVariantMap params;
+ params.insert("deviceId", deviceId);
+ params.insert("settings", settings);
+ m_jsonClient->sendCommand("Devices.SetDeviceSettings", params);
+}
+
void DeviceManager::reconfigureDevice(const QUuid &deviceId, const QVariantList &deviceParams)
{
QVariantMap params;
diff --git a/libnymea-app-core/devicemanager.h b/libnymea-app-core/devicemanager.h
index 2b4fa8cd..6257a770 100644
--- a/libnymea-app-core/devicemanager.h
+++ b/libnymea-app-core/devicemanager.h
@@ -69,6 +69,7 @@ public:
Q_INVOKABLE void confirmPairing(const QUuid &pairingTransactionId, const QString &secret = QString());
Q_INVOKABLE void removeDevice(const QUuid &deviceId, RemovePolicy policy = RemovePolicyNone);
Q_INVOKABLE void editDevice(const QUuid &deviceId, const QString &name);
+ Q_INVOKABLE void setDeviceSettings(const QUuid &deviceId, const QVariantList &settings);
Q_INVOKABLE void reconfigureDevice(const QUuid &deviceId, const QVariantList &deviceParams);
Q_INVOKABLE void reconfigureDiscoveredDevice(const QUuid &deviceId, const QUuid &deviceDescriptorId);
Q_INVOKABLE int executeAction(const QUuid &deviceId, const QUuid &actionTypeId, const QVariantList ¶ms = QVariantList());
diff --git a/libnymea-app-core/jsonrpc/jsontypes.cpp b/libnymea-app-core/jsonrpc/jsontypes.cpp
index 55d3461a..9c56b2dc 100644
--- a/libnymea-app-core/jsonrpc/jsontypes.cpp
+++ b/libnymea-app-core/jsonrpc/jsontypes.cpp
@@ -91,6 +91,13 @@ DeviceClass *JsonTypes::unpackDeviceClass(const QVariantMap &deviceClassMap, QOb
}
deviceClass->setParamTypes(paramTypes);
+ // SettingsTypes
+ ParamTypes *settingsTypes = new ParamTypes(deviceClass);
+ foreach (QVariant settingsType, deviceClassMap.value("settingsTypes").toList()) {
+ settingsTypes->addParamType(JsonTypes::unpackParamType(settingsType.toMap(), settingsTypes));
+ }
+ deviceClass->setSettingsTypes(settingsTypes);
+
// discovery ParamTypes
ParamTypes *discoveryParamTypes = new ParamTypes(deviceClass);
foreach (QVariant paramType, deviceClassMap.value("discoveryParamTypes").toList()) {
@@ -219,7 +226,6 @@ Device* JsonTypes::unpackDevice(const QVariantMap &deviceMap, DeviceClasses *dev
Params *params = device->params();
if (!params) {
params = new Params(device);
- device->setParams(params);
}
foreach (QVariant param, deviceMap.value("params").toList()) {
Param *p = params->getParam(param.toMap().value("paramTypeId").toString());
@@ -231,6 +237,20 @@ Device* JsonTypes::unpackDevice(const QVariantMap &deviceMap, DeviceClasses *dev
}
device->setParams(params);
+ Params *settings = device->settings();
+ if (!settings) {
+ settings = new Params(device);
+ }
+ foreach (QVariant setting, deviceMap.value("settings").toList()) {
+ Param *p = settings->getParam(setting.toMap().value("paramTypeId").toString());
+ if (!p) {
+ p = new Param();
+ settings->addParam(p);
+ }
+ JsonTypes::unpackParam(setting.toMap(), p);
+ }
+ device->setSettings(settings);
+
States *states = device->states();
if (!states) {
states = new States(device);
diff --git a/libnymea-common/types/device.cpp b/libnymea-common/types/device.cpp
index 06511d2e..29f400e1 100644
--- a/libnymea-common/types/device.cpp
+++ b/libnymea-common/types/device.cpp
@@ -79,11 +79,29 @@ void Device::setParams(Params *params)
if (m_params) {
m_params->deleteLater();
}
+ params->setParent(this);
m_params = params;
emit paramsChanged();
}
}
+Params *Device::settings() const
+{
+ return m_settings;
+}
+
+void Device::setSettings(Params *settings)
+{
+ if (m_settings != settings) {
+ if (m_settings) {
+ m_settings->deleteLater();
+ }
+ settings->setParent(this);
+ m_settings = settings;
+ emit settingsChanged();
+ }
+}
+
States *Device::states() const
{
return m_states;
@@ -95,6 +113,7 @@ void Device::setStates(States *states)
if (m_states) {
m_states->deleteLater();
}
+ states->setParent(this);
m_states = states;
emit statesChanged();
}
@@ -147,6 +166,15 @@ QDebug operator<<(QDebug &dbg, Device *device)
dbg << " Param " << i << ": " << pt->id().toString() << ": " << pt->name() << " = " << "*** Unknown value ***" << endl;
}
}
+ for (int i = 0; i < device->deviceClass()->settingsTypes()->rowCount(); i++) {
+ ParamType *pt = device->deviceClass()->settingsTypes()->get(i);
+ Param *p = device->settings()->getParam(pt->id().toString());
+ if (p) {
+ dbg << " Setting " << i << ": " << pt->id().toString() << ": " << pt->name() << " = " << p->value() << endl;
+ } else {
+ dbg << " Setting " << i << ": " << pt->id().toString() << ": " << pt->name() << " = " << "*** Unknown value ***" << endl;
+ }
+ }
for (int i = 0; i < device->deviceClass()->stateTypes()->rowCount(); i++) {
StateType *st = device->deviceClass()->stateTypes()->get(i);
State *s = device->states()->getState(st->id());
diff --git a/libnymea-common/types/device.h b/libnymea-common/types/device.h
index bc7e59de..e5617f32 100644
--- a/libnymea-common/types/device.h
+++ b/libnymea-common/types/device.h
@@ -40,6 +40,7 @@ class Device : public QObject
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(bool setupComplete READ setupComplete NOTIFY setupCompleteChanged)
Q_PROPERTY(Params *params READ params NOTIFY paramsChanged)
+ Q_PROPERTY(Params *settings READ settings NOTIFY settingsChanged)
Q_PROPERTY(States *states READ states NOTIFY statesChanged)
Q_PROPERTY(DeviceClass *deviceClass READ deviceClass CONSTANT)
@@ -60,6 +61,9 @@ public:
Params *params() const;
void setParams(Params *params);
+ Params *settings() const;
+ void setSettings(Params *settings);
+
States *states() const;
void setStates(States *states);
@@ -75,6 +79,7 @@ private:
QUuid m_id;
bool m_setupComplete;
Params *m_params = nullptr;
+ Params *m_settings = nullptr;
States *m_states = nullptr;
DeviceClass *m_deviceClass = nullptr;
@@ -83,6 +88,7 @@ signals:
void nameChanged();
void setupCompleteChanged();
void paramsChanged();
+ void settingsChanged();
void statesChanged();
};
diff --git a/libnymea-common/types/deviceclass.cpp b/libnymea-common/types/deviceclass.cpp
index ec77e279..e541d1fb 100644
--- a/libnymea-common/types/deviceclass.cpp
+++ b/libnymea-common/types/deviceclass.cpp
@@ -174,10 +174,27 @@ ParamTypes *DeviceClass::paramTypes() const
void DeviceClass::setParamTypes(ParamTypes *paramTypes)
{
+ if (m_paramTypes) {
+ m_paramTypes->deleteLater();
+ }
m_paramTypes = paramTypes;
emit paramTypesChanged();
}
+ParamTypes *DeviceClass::settingsTypes() const
+{
+ return m_settingsTypes;
+}
+
+void DeviceClass::setSettingsTypes(ParamTypes *settingsTypes)
+{
+ if (m_settingsTypes) {
+ m_settingsTypes->deleteLater();
+ }
+ m_settingsTypes = settingsTypes;
+ emit settingsTypesChanged();
+}
+
ParamTypes *DeviceClass::discoveryParamTypes() const
{
return m_discoveryParamTypes;
@@ -185,6 +202,9 @@ ParamTypes *DeviceClass::discoveryParamTypes() const
void DeviceClass::setDiscoveryParamTypes(ParamTypes *paramTypes)
{
+ if (m_discoveryParamTypes) {
+ m_discoveryParamTypes->deleteLater();
+ }
m_discoveryParamTypes = paramTypes;
emit discoveryParamTypesChanged();
}
@@ -196,6 +216,9 @@ StateTypes *DeviceClass::stateTypes() const
void DeviceClass::setStateTypes(StateTypes *stateTypes)
{
+ if (m_stateTypes) {
+ m_stateTypes->deleteLater();
+ }
m_stateTypes = stateTypes;
emit stateTypesChanged();
}
@@ -207,6 +230,9 @@ EventTypes *DeviceClass::eventTypes() const
void DeviceClass::setEventTypes(EventTypes *eventTypes)
{
+ if (m_eventTypes) {
+ m_eventTypes->deleteLater();
+ }
m_eventTypes = eventTypes;
emit eventTypesChanged();
}
@@ -218,6 +244,9 @@ ActionTypes *DeviceClass::actionTypes() const
void DeviceClass::setActionTypes(ActionTypes *actionTypes)
{
+ if (m_actionTypes) {
+ m_actionTypes->deleteLater();
+ }
m_actionTypes = actionTypes;
emit actionTypesChanged();
}
diff --git a/libnymea-common/types/deviceclass.h b/libnymea-common/types/deviceclass.h
index ff819ca4..21ccb3f7 100644
--- a/libnymea-common/types/deviceclass.h
+++ b/libnymea-common/types/deviceclass.h
@@ -47,6 +47,7 @@ class DeviceClass : public QObject
Q_PROPERTY(QStringList interfaces READ interfaces CONSTANT)
Q_PROPERTY(QString baseInterface READ baseInterface CONSTANT)
Q_PROPERTY(ParamTypes *paramTypes READ paramTypes NOTIFY paramTypesChanged)
+ Q_PROPERTY(ParamTypes *settingsTypes READ settingsTypes NOTIFY settingsTypesChanged)
Q_PROPERTY(ParamTypes *discoveryParamTypes READ discoveryParamTypes NOTIFY discoveryParamTypesChanged)
Q_PROPERTY(StateTypes *stateTypes READ stateTypes NOTIFY stateTypesChanged)
Q_PROPERTY(EventTypes *eventTypes READ eventTypes NOTIFY eventTypesChanged)
@@ -93,6 +94,9 @@ public:
ParamTypes *paramTypes() const;
void setParamTypes(ParamTypes *paramTypes);
+ ParamTypes *settingsTypes() const;
+ void setSettingsTypes(ParamTypes *settingsTypes);
+
ParamTypes *discoveryParamTypes() const;
void setDiscoveryParamTypes(ParamTypes *paramTypes);
@@ -117,14 +121,16 @@ private:
SetupMethod m_setupMethod;
QStringList m_interfaces;
- ParamTypes *m_paramTypes;
- ParamTypes *m_discoveryParamTypes;
- StateTypes *m_stateTypes;
- EventTypes *m_eventTypes;
- ActionTypes *m_actionTypes;
+ ParamTypes *m_paramTypes = nullptr;
+ ParamTypes *m_settingsTypes = nullptr;
+ ParamTypes *m_discoveryParamTypes = nullptr;
+ StateTypes *m_stateTypes = nullptr;
+ EventTypes *m_eventTypes = nullptr;
+ ActionTypes *m_actionTypes = nullptr;
signals:
void paramTypesChanged();
+ void settingsTypesChanged();
void discoveryParamTypesChanged();
void stateTypesChanged();
void eventTypesChanged();
diff --git a/libnymea-common/types/params.cpp b/libnymea-common/types/params.cpp
index f4279c39..339afdc8 100644
--- a/libnymea-common/types/params.cpp
+++ b/libnymea-common/types/params.cpp
@@ -41,6 +41,9 @@ int Params::count() const
Param *Params::get(int index) const
{
+ if (index < 0 || index >= m_params.count()) {
+ return nullptr;
+ }
return m_params.at(index);
}
@@ -51,7 +54,7 @@ Param *Params::getParam(QString paramTypeId) const
return param;
}
}
- return 0;
+ return nullptr;
}
int Params::paramCount() const
diff --git a/nymea-app/ui/components/SwipeDelegateGroup.qml b/nymea-app/ui/components/SwipeDelegateGroup.qml
index 209e945e..7b2bf720 100644
--- a/nymea-app/ui/components/SwipeDelegateGroup.qml
+++ b/nymea-app/ui/components/SwipeDelegateGroup.qml
@@ -19,13 +19,13 @@ Item {
if (d.delegateCache.indexOf(thisItem) < 0) {
d.delegateCache.push(thisItem);
- print("cache is now", d.delegateCache.length)
+// print("cache is now", d.delegateCache.length)
thisItem.Component.destruction.connect(function() {
- print("item destroyed", thisItem)
+// print("item destroyed", thisItem)
var idx = d.delegateCache.indexOf(thisItem)
d.delegateCache.splice(idx, 1)
- print("cache is now", d.delegateCache.length)
+// print("cache is now", d.delegateCache.length)
})
thisItem.swipe.opened.connect(function() {
diff --git a/nymea-app/ui/delegates/ParamDelegate.qml b/nymea-app/ui/delegates/ParamDelegate.qml
index a7c3f43f..dcad42d3 100644
--- a/nymea-app/ui/delegates/ParamDelegate.qml
+++ b/nymea-app/ui/delegates/ParamDelegate.qml
@@ -33,7 +33,7 @@ ItemDelegate {
}
Loader {
id: loader
- Layout.fillWidth: sourceComponent === textFieldComponent
+ Layout.fillWidth: true// sourceComponent === textFieldComponent || sourceComponent === stringComponent
sourceComponent: {
print("loading paramdelegate:", root.writable, root.paramType.type)
if (!root.writable) {
@@ -93,6 +93,8 @@ ItemDelegate {
}
return root.param.value;
}
+ horizontalAlignment: Text.AlignRight
+ elide: Text.ElideRight
}
}
Component {
@@ -150,26 +152,34 @@ ItemDelegate {
Component {
id: spinnerComponent
- SpinBox {
- value: root.param.value ? root.param.value : 0
- from: root.paramType.minValue
- ? root.paramType.minValue
- : root.paramType.type.toLowerCase() === "uint"
- ? 0
- : -2000000000
- to: root.paramType.maxValue
- ? root.paramType.maxValue
- : 2000000000
- editable: true
- width: 150
- onValueModified: root.param.value = value
- textFromValue: function(value) {
- return value
- }
- Component.onCompleted: {
- if (root.value === undefined) {
- root.value = value
+ RowLayout {
+ spacing: app.margins
+
+ SpinBox {
+ value: root.param.value ? root.param.value : 0
+ from: root.paramType.minValue
+ ? root.paramType.minValue
+ : root.paramType.type.toLowerCase() === "uint"
+ ? 0
+ : -2000000000
+ to: root.paramType.maxValue
+ ? root.paramType.maxValue
+ : 2000000000
+ editable: true
+ width: 150
+ onValueModified: root.param.value = value
+ textFromValue: function(value) {
+ return value
}
+ Component.onCompleted: {
+ if (root.value === undefined) {
+ root.value = value
+ }
+ }
+ }
+ Label {
+ text: root.paramType.unitString
+ visible: text.length > 0
}
}
}
diff --git a/nymea-app/ui/thingconfiguration/ConfigureThingPage.qml b/nymea-app/ui/thingconfiguration/ConfigureThingPage.qml
index d2ac5435..dcaf6293 100644
--- a/nymea-app/ui/thingconfiguration/ConfigureThingPage.qml
+++ b/nymea-app/ui/thingconfiguration/ConfigureThingPage.qml
@@ -68,8 +68,10 @@ Page {
Flickable {
anchors.fill: parent
+ contentHeight: contentColumn.implicitHeight
ColumnLayout {
+ id: contentColumn
width: parent.width
Label {
@@ -119,6 +121,62 @@ Page {
}
}
+ Label {
+ Layout.fillWidth: true
+ Layout.leftMargin: app.margins
+ Layout.rightMargin: app.margins
+ Layout.topMargin: app.margins
+ text: qsTr("Thing settings")
+ color: app.accentColor
+ visible: root.deviceClass.settingsTypes.count > 0
+ }
+
+ Repeater {
+ id: settingsRepeater
+ model: root.device.settings
+ delegate: ParamDelegate {
+ Layout.fillWidth: true
+ paramType: root.deviceClass.settingsTypes.getParamType(model.id)
+ value: root.device.settings.get(index).value
+ writable: true
+ property bool dirty: root.device.settings.get(index).value !== value
+ onDirtyChanged: settingsRepeater.checkDirty()
+ }
+ function checkDirty() {
+ for (var i = 0; i < settingsRepeater.count; i++) {
+ if (settingsRepeater.itemAt(i).dirty) {
+ dirty = true;
+ return;
+ }
+ }
+ dirty = false;
+ }
+ property bool dirty: false
+ }
+ Button {
+ Layout.fillWidth: true
+ Layout.leftMargin: app.margins
+ Layout.rightMargin: app.margins
+ text: qsTr("Apply")
+ enabled: settingsRepeater.dirty
+ visible: settingsRepeater.count > 0
+
+ onClicked: {
+ var params = []
+ for (var i = 0; i < settingsRepeater.count; i++) {
+ if (!settingsRepeater.itemAt(i).dirty) {
+ continue;
+ }
+ var setting = {}
+ setting["paramTypeId"] = settingsRepeater.itemAt(i).param.paramTypeId
+ setting["value"] = settingsRepeater.itemAt(i).param.value
+ params.push(setting)
+ }
+
+ engine.deviceManager.setDeviceSettings(root.device.id, params);
+ }
+ }
+
// ThinDivider {}
}
diff --git a/packaging/android/AndroidManifest.xml b/packaging/android/AndroidManifest.xml
index a73cc177..86f661d5 100644
--- a/packaging/android/AndroidManifest.xml
+++ b/packaging/android/AndroidManifest.xml
@@ -45,7 +45,7 @@
application still try to draw after
"applicationStateChanged(Qt::ApplicationSuspended)"
signal is sent! -->
-
+