From 5c2e2889993ce915ac333cc5dc09028facf48b11 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Sun, 28 Jul 2019 01:35:48 +0200 Subject: [PATCH 1/4] Add support for OAuth when setting up things --- libnymea-app-core/devicemanager.cpp | 11 ++++ libnymea-app-core/devicemanager.h | 1 + libnymea-app-core/jsonrpc/jsontypes.cpp | 2 + libnymea-common/types/deviceclass.h | 3 +- .../ui/thingconfiguration/SetupWizard.qml | 58 +++++++++++++++++-- 5 files changed, 70 insertions(+), 5 deletions(-) diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp index 4c17657d..32e4e680 100644 --- a/libnymea-app-core/devicemanager.cpp +++ b/libnymea-app-core/devicemanager.cpp @@ -297,6 +297,7 @@ void DeviceManager::pairDeviceResponse(const QVariantMap ¶ms) void DeviceManager::confirmPairingResponse(const QVariantMap ¶ms) { + qDebug() << "ConfirmPairingResponse" << params; emit confirmPairingReply(params.value("params").toMap()); } @@ -362,6 +363,16 @@ void DeviceManager::pairDevice(const QUuid &deviceClassId, const QUuid &deviceDe m_jsonClient->sendCommand("Devices.PairDevice", params, this, "pairDeviceResponse"); } +void DeviceManager::pairDevice(const QUuid &deviceClassId, const QString &name, const QVariantList &deviceParams) +{ + qDebug() << "JsonRpc: pair device " << deviceClassId.toString(); + QVariantMap params; + params.insert("name", name); + params.insert("deviceClassId", deviceClassId.toString()); + params.insert("deviceParams", deviceParams); + m_jsonClient->sendCommand("Devices.PairDevice", params, this, "pairDeviceResponse"); +} + void DeviceManager::confirmPairing(const QUuid &pairingTransactionId, const QString &secret) { qDebug() << "JsonRpc: confirm pairing" << pairingTransactionId.toString(); diff --git a/libnymea-app-core/devicemanager.h b/libnymea-app-core/devicemanager.h index 57ae3777..a0029bf0 100644 --- a/libnymea-app-core/devicemanager.h +++ b/libnymea-app-core/devicemanager.h @@ -69,6 +69,7 @@ public: Q_INVOKABLE void addDevice(const QUuid &deviceClassId, const QString &name, const QVariantList &deviceParams); Q_INVOKABLE void addDiscoveredDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId, const QString &name, const QVariantList &deviceParams); Q_INVOKABLE void pairDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId, const QString &name); + Q_INVOKABLE void pairDevice(const QUuid &deviceClassId, const QString &name, const QVariantList &deviceParams); 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); diff --git a/libnymea-app-core/jsonrpc/jsontypes.cpp b/libnymea-app-core/jsonrpc/jsontypes.cpp index 2c4374a3..288e68e1 100644 --- a/libnymea-app-core/jsonrpc/jsontypes.cpp +++ b/libnymea-app-core/jsonrpc/jsontypes.cpp @@ -492,6 +492,8 @@ DeviceClass::SetupMethod JsonTypes::stringToSetupMethod(const QString &setupMeth return DeviceClass::SetupMethodEnterPin; } else if (setupMethodString == "SetupMethodPushButton") { return DeviceClass::SetupMethodPushButton; + } else if (setupMethodString == "SetupMethodOAuth") { + return DeviceClass::SetupMethodOAuth; } return DeviceClass::SetupMethodJustAdd; } diff --git a/libnymea-common/types/deviceclass.h b/libnymea-common/types/deviceclass.h index 686e613e..0041bdca 100644 --- a/libnymea-common/types/deviceclass.h +++ b/libnymea-common/types/deviceclass.h @@ -61,7 +61,8 @@ public: SetupMethodJustAdd, SetupMethodDisplayPin, SetupMethodEnterPin, - SetupMethodPushButton + SetupMethodPushButton, + SetupMethodOAuth, }; Q_ENUM(SetupMethod) diff --git a/nymea-app/ui/thingconfiguration/SetupWizard.qml b/nymea-app/ui/thingconfiguration/SetupWizard.qml index 1fd99780..4b9d3334 100644 --- a/nymea-app/ui/thingconfiguration/SetupWizard.qml +++ b/nymea-app/ui/thingconfiguration/SetupWizard.qml @@ -3,6 +3,8 @@ import QtQuick.Layouts 1.1 import QtQuick.Controls 2.1 import QtQuick.Controls.Material 2.1 import Nymea 1.0 +import QtWebView 1.1 + import "../components" import "../delegates" @@ -60,18 +62,29 @@ Page { target: engine.deviceManager onPairDeviceReply: { busyOverlay.shown = false + if (params["deviceError"] !== "DeviceErrorNoError") { + busyOverlay.shown = false; + internalPageStack.push(resultsPage, {success: false}) + return; + + } + + d.pairingTransactionId = params["pairingTransactionId"]; + switch (params["setupMethod"]) { case "SetupMethodPushButton": - d.pairingTransactionId = params["pairingTransactionId"]; print("response", params["displayMessage"], d.pairingTransactionId) internalPageStack.push(pairingPageComponent, {text: params["displayMessage"]}) break; case "SetupMethodDisplayPin": - d.pairingTransactionId = params["pairingTransactionId"]; internalPageStack.push(pairingPageComponent, {text: params["displayMessage"], setupMethod: params["setupMethod"]}) break; + case "SetupMethodOAuth": + print("OAuth URL:", params["oAuthUrl"]); + internalPageStack.push(oAuthPageComponent, {oAuthUrl: params["oAuthUrl"]}) + break; default: - print("Setup method", params["setupMethod"], "not handled"); + print("Setup method reply not handled:", JSON.stringify(params)); } } onConfirmPairingReply: { @@ -364,7 +377,23 @@ Page { case 1: case 2: case 3: - engine.deviceManager.pairDevice(root.deviceClass.id, d.deviceDescriptor.id, nameTextField.text); + case 4: + if (root.device) { +// if (d.deviceDescriptor) { +// engine.deviceManager.pairDevice(root.deviceClass.id, d.deviceDescriptor.id, nameTextField.text); +// } else { +// engine.deviceManager.pairDevice(root.deviceClass.id, nameTextField.text, params); +// } + console.warn("Unhandle setupMethod!") + return; + } else { + if (d.deviceDescriptor) { + engine.deviceManager.pairDevice(root.deviceClass.id, d.deviceDescriptor.id, nameTextField.text); + } else { + engine.deviceManager.pairDevice(root.deviceClass.id, nameTextField.text, params); + } + } + break; } @@ -422,6 +451,27 @@ Page { } } + Component { + id: oAuthPageComponent + Page { + id: oAuthPage + property alias oAuthUrl: oAuthWebView.url + + WebView { + id: oAuthWebView + anchors.fill: parent + + onUrlChanged: { + print("OAUTH URL changed", url) + if (url.toString().indexOf("https://127.0.0.1") == 0) { + print("Redirect URL detected!"); + engine.deviceManager.confirmPairing(d.pairingTransactionId, url) + } + } + } + } + } + Component { id: resultsPage From 42e8f455b221c531205a3ed2032f2d39a8ad02ac Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Fri, 9 Aug 2019 19:27:09 +0200 Subject: [PATCH 2/4] more work on oauth --- libnymea-app-core/devicemanager.cpp | 3 ++- libnymea-app-core/devicemanager.h | 2 +- libnymea-app-core/jsonrpc/jsontypes.cpp | 2 ++ libnymea-common/types/deviceclass.h | 1 + .../ui/thingconfiguration/SetupWizard.qml | 20 ++++++++++++------- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp index 32e4e680..93185796 100644 --- a/libnymea-app-core/devicemanager.cpp +++ b/libnymea-app-core/devicemanager.cpp @@ -373,12 +373,13 @@ void DeviceManager::pairDevice(const QUuid &deviceClassId, const QString &name, m_jsonClient->sendCommand("Devices.PairDevice", params, this, "pairDeviceResponse"); } -void DeviceManager::confirmPairing(const QUuid &pairingTransactionId, const QString &secret) +void DeviceManager::confirmPairing(const QUuid &pairingTransactionId, const QString &secret, const QString &username) { qDebug() << "JsonRpc: confirm pairing" << pairingTransactionId.toString(); QVariantMap params; params.insert("pairingTransactionId", pairingTransactionId.toString()); params.insert("secret", secret); + params.insert("username", username); m_jsonClient->sendCommand("Devices.ConfirmPairing", params, this, "confirmPairingResponse"); } diff --git a/libnymea-app-core/devicemanager.h b/libnymea-app-core/devicemanager.h index a0029bf0..49623473 100644 --- a/libnymea-app-core/devicemanager.h +++ b/libnymea-app-core/devicemanager.h @@ -70,7 +70,7 @@ public: Q_INVOKABLE void addDiscoveredDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId, const QString &name, const QVariantList &deviceParams); Q_INVOKABLE void pairDevice(const QUuid &deviceClassId, const QUuid &deviceDescriptorId, const QString &name); Q_INVOKABLE void pairDevice(const QUuid &deviceClassId, const QString &name, const QVariantList &deviceParams); - Q_INVOKABLE void confirmPairing(const QUuid &pairingTransactionId, const QString &secret = QString()); + Q_INVOKABLE void confirmPairing(const QUuid &pairingTransactionId, const QString &secret = QString(), const QString &username = 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); diff --git a/libnymea-app-core/jsonrpc/jsontypes.cpp b/libnymea-app-core/jsonrpc/jsontypes.cpp index 288e68e1..42e5c65d 100644 --- a/libnymea-app-core/jsonrpc/jsontypes.cpp +++ b/libnymea-app-core/jsonrpc/jsontypes.cpp @@ -494,6 +494,8 @@ DeviceClass::SetupMethod JsonTypes::stringToSetupMethod(const QString &setupMeth return DeviceClass::SetupMethodPushButton; } else if (setupMethodString == "SetupMethodOAuth") { return DeviceClass::SetupMethodOAuth; + } else if (setupMethodString == "SetupMethodUserAndPassword") { + return DeviceClass::SetupMethodUserAndPassword; } return DeviceClass::SetupMethodJustAdd; } diff --git a/libnymea-common/types/deviceclass.h b/libnymea-common/types/deviceclass.h index 0041bdca..eace4368 100644 --- a/libnymea-common/types/deviceclass.h +++ b/libnymea-common/types/deviceclass.h @@ -63,6 +63,7 @@ public: SetupMethodEnterPin, SetupMethodPushButton, SetupMethodOAuth, + SetupMethodUserAndPassword, }; Q_ENUM(SetupMethod) diff --git a/nymea-app/ui/thingconfiguration/SetupWizard.qml b/nymea-app/ui/thingconfiguration/SetupWizard.qml index 4b9d3334..207adfc3 100644 --- a/nymea-app/ui/thingconfiguration/SetupWizard.qml +++ b/nymea-app/ui/thingconfiguration/SetupWizard.qml @@ -73,14 +73,11 @@ Page { switch (params["setupMethod"]) { case "SetupMethodPushButton": - print("response", params["displayMessage"], d.pairingTransactionId) - internalPageStack.push(pairingPageComponent, {text: params["displayMessage"]}) - break; case "SetupMethodDisplayPin": + case "SetupMethodUserAndPassword": internalPageStack.push(pairingPageComponent, {text: params["displayMessage"], setupMethod: params["setupMethod"]}) break; case "SetupMethodOAuth": - print("OAuth URL:", params["oAuthUrl"]); internalPageStack.push(oAuthPageComponent, {oAuthUrl: params["oAuthUrl"]}) break; default: @@ -378,13 +375,14 @@ Page { case 2: case 3: case 4: + case 5: if (root.device) { // if (d.deviceDescriptor) { // engine.deviceManager.pairDevice(root.deviceClass.id, d.deviceDescriptor.id, nameTextField.text); // } else { // engine.deviceManager.pairDevice(root.deviceClass.id, nameTextField.text, params); // } - console.warn("Unhandle setupMethod!") + console.warn("Unhandled setupMethod!") return; } else { if (d.deviceDescriptor) { @@ -434,17 +432,25 @@ Page { wrapMode: Text.WordWrap horizontalAlignment: Text.AlignHCenter } + + TextField { + id: usernameTextField + Layout.fillWidth: true + visible: pairingPage.setupMethod === "SetupMethodUserAndPassword" + } + TextField { id: pinTextField Layout.fillWidth: true - visible: pairingPage.setupMethod === "SetupMethodDisplayPin" + visible: pairingPage.setupMethod === "SetupMethodDisplayPin" || pairingPage.setupMethod === "SetupMethodUserAndPassword" } + Button { Layout.fillWidth: true text: "OK" onClicked: { - engine.deviceManager.confirmPairing(d.pairingTransactionId, pinTextField.displayText); + engine.deviceManager.confirmPairing(d.pairingTransactionId, pinTextField.displayText, usernameTextField.displayText); } } } From 93cb26e3d61937e8b383ad21311204b96f500012 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Fri, 23 Aug 2019 15:05:18 +0200 Subject: [PATCH 3/4] Display the error message in case of failed pairing --- nymea-app/ui/thingconfiguration/SetupWizard.qml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/nymea-app/ui/thingconfiguration/SetupWizard.qml b/nymea-app/ui/thingconfiguration/SetupWizard.qml index 207adfc3..39f9837d 100644 --- a/nymea-app/ui/thingconfiguration/SetupWizard.qml +++ b/nymea-app/ui/thingconfiguration/SetupWizard.qml @@ -86,7 +86,7 @@ Page { } onConfirmPairingReply: { busyOverlay.shown = false - internalPageStack.push(resultsPage, {success: params["deviceError"] === "DeviceErrorNoError", deviceId: params["deviceId"]}) + internalPageStack.push(resultsPage, {success: params["deviceError"] === "DeviceErrorNoError", deviceId: params["deviceId"], message: params["displayMessage"]}) } onAddDeviceReply: { busyOverlay.shown = false; @@ -443,6 +443,7 @@ Page { id: pinTextField Layout.fillWidth: true visible: pairingPage.setupMethod === "SetupMethodDisplayPin" || pairingPage.setupMethod === "SetupMethodUserAndPassword" + echoMode: TextField.Password } @@ -450,7 +451,8 @@ Page { Layout.fillWidth: true text: "OK" onClicked: { - engine.deviceManager.confirmPairing(d.pairingTransactionId, pinTextField.displayText, usernameTextField.displayText); + engine.deviceManager.confirmPairing(d.pairingTransactionId, pinTextField.text, usernameTextField.displayText); + busyOverlay.shown = true; } } } @@ -486,6 +488,7 @@ Page { property bool success property string deviceId + property string message readonly property var device: root.device ? root.device : engine.deviceManager.devices.getDevice(deviceId) @@ -508,6 +511,13 @@ Page { text: resultsView.success ? qsTr("All done. You can now start using %1.").arg(resultsView.device.name) : qsTr("Something went wrong setting up this thing..."); } + Label { + Layout.fillWidth: true + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + text: resultsView.message + } + Button { Layout.fillWidth: true text: qsTr("Ok") From 74dc39a5dd9fb6d60ec87c7cc0f9ef986986a805 Mon Sep 17 00:00:00 2001 From: Michael Zanetti Date: Wed, 28 Aug 2019 12:00:55 +0200 Subject: [PATCH 4/4] stack backwards compatible --- libnymea-app-core/devicemanager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libnymea-app-core/devicemanager.cpp b/libnymea-app-core/devicemanager.cpp index 93185796..e5f8c036 100644 --- a/libnymea-app-core/devicemanager.cpp +++ b/libnymea-app-core/devicemanager.cpp @@ -379,7 +379,9 @@ void DeviceManager::confirmPairing(const QUuid &pairingTransactionId, const QStr QVariantMap params; params.insert("pairingTransactionId", pairingTransactionId.toString()); params.insert("secret", secret); - params.insert("username", username); + if (!username.isEmpty()) { + params.insert("username", username); + } m_jsonClient->sendCommand("Devices.ConfirmPairing", params, this, "confirmPairingResponse"); }