summaryrefslogtreecommitdiffstats
path: root/demo/Main.qml
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-02-17 23:58:08 +0100
committerThomas Vanbesien <tvanbesi@proton.me>2026-02-17 23:58:08 +0100
commit343169dff6b062074fd3c4a5e240b449ffc4a449 (patch)
treea2ef1edc8dd1b1c1dbac757192fa681d8ec76717 /demo/Main.qml
downloadBobinkQtOpcUa-343169dff6b062074fd3c4a5e240b449ffc4a449.tar.gz
BobinkQtOpcUa-343169dff6b062074fd3c4a5e240b449ffc4a449.zip
Initial Bobink library: BobinkAuth, BobinkClient, and demo app
Implements the core OPC UA wrapper library with: - Build system with automatic dep building (open62541, QtOpcUa) - BobinkAuth: QML auth component (anonymous/userpass/certificate) - BobinkClient: QML singleton managing connection, LDS discovery, PKI configuration, endpoint selection, and certificate trust flow - Demo app for manual testing of the full connection flow
Diffstat (limited to 'demo/Main.qml')
-rw-r--r--demo/Main.qml188
1 files changed, 188 insertions, 0 deletions
diff --git a/demo/Main.qml b/demo/Main.qml
new file mode 100644
index 0000000..6d1327d
--- /dev/null
+++ b/demo/Main.qml
@@ -0,0 +1,188 @@
+import QtQuick
+import QtQuick.Controls
+import QtQuick.Layouts
+import Bobink
+
+ApplicationWindow {
+ width: 600
+ height: 600
+ visible: true
+ title: "Bobink Demo"
+
+ Connections {
+ target: BobinkClient
+ function onServersChanged() {
+ console.log("Discovered server list updated")
+ }
+ function onConnectedChanged() {
+ console.log("Connected:", BobinkClient.connected)
+ }
+ function onConnectionError(message) {
+ console.log("Connection error:", message)
+ }
+ function onDiscoveringChanged() {
+ console.log("Discovering:", BobinkClient.discovering)
+ }
+ }
+
+ ColumnLayout {
+ anchors.fill: parent
+ anchors.margins: 20
+ spacing: 12
+
+ Label { text: "Discovery URL"; font.bold: true }
+
+ RowLayout {
+ TextField {
+ id: discoveryUrlField
+ Layout.fillWidth: true
+ text: "opc.tcp://localhost:4840"
+ }
+ Button {
+ text: BobinkClient.discovering ? "Stop" : "Discover"
+ onClicked: {
+ if (BobinkClient.discovering) {
+ BobinkClient.stopDiscovery()
+ } else {
+ BobinkClient.discoveryUrl = discoveryUrlField.text
+ BobinkClient.startDiscovery()
+ }
+ }
+ }
+ }
+
+ Label {
+ text: BobinkClient.discovering
+ ? "Discovering... (" + BobinkClient.servers.length + " found)"
+ : BobinkClient.servers.length + " server(s)"
+ font.italic: true
+ }
+
+ ListView {
+ Layout.fillWidth: true
+ Layout.preferredHeight: 100
+ clip: true
+ model: BobinkClient.servers
+ delegate: ItemDelegate {
+ width: ListView.view.width
+ text: modelData.serverName + " — " + modelData.applicationUri
+ onClicked: {
+ if (modelData.discoveryUrls.length > 0)
+ serverUrlField.text = modelData.discoveryUrls[0]
+ }
+ }
+ ScrollBar.vertical: ScrollBar {}
+ }
+
+ Label { text: "PKI Directory"; font.bold: true }
+
+ RowLayout {
+ TextField {
+ id: pkiDirField
+ Layout.fillWidth: true
+ text: BobinkClient.pkiDir
+ onEditingFinished: BobinkClient.pkiDir = text
+ }
+ Button {
+ text: "Apply PKI"
+ onClicked: {
+ BobinkClient.pkiDir = pkiDirField.text
+ BobinkClient.applyPki()
+ console.log("PKI applied:", BobinkClient.pkiDir)
+ }
+ }
+ }
+
+ Label { text: "Server URL"; font.bold: true }
+
+ RowLayout {
+ TextField {
+ id: serverUrlField
+ Layout.fillWidth: true
+ placeholderText: "opc.tcp://..."
+ }
+ }
+
+ Label { text: "Authentication"; font.bold: true }
+
+ BobinkAuth {
+ id: auth
+ mode: {
+ switch (authModeCombo.currentIndex) {
+ case 0: return BobinkAuth.Anonymous
+ case 1: return BobinkAuth.UserPass
+ case 2: return BobinkAuth.Certificate
+ default: return BobinkAuth.Anonymous
+ }
+ }
+ username: usernameField.text
+ password: passwordField.text
+ certPath: certPathField.text
+ keyPath: keyPathField.text
+ }
+
+ ComboBox {
+ id: authModeCombo
+ Layout.fillWidth: true
+ model: ["Anonymous", "Username / Password", "Certificate"]
+ }
+
+ GridLayout {
+ columns: 2
+ visible: authModeCombo.currentIndex === 1
+ Layout.fillWidth: true
+
+ Label { text: "Username:" }
+ TextField {
+ id: usernameField
+ Layout.fillWidth: true
+ }
+ Label { text: "Password:" }
+ TextField {
+ id: passwordField
+ Layout.fillWidth: true
+ echoMode: TextInput.Password
+ }
+ }
+
+ GridLayout {
+ columns: 2
+ visible: authModeCombo.currentIndex === 2
+ Layout.fillWidth: true
+
+ Label { text: "Certificate:" }
+ TextField {
+ id: certPathField
+ Layout.fillWidth: true
+ placeholderText: "/path/to/cert.pem"
+ }
+ Label { text: "Private key:" }
+ TextField {
+ id: keyPathField
+ Layout.fillWidth: true
+ placeholderText: "/path/to/key.pem"
+ }
+ }
+
+ Button {
+ text: BobinkClient.connected ? "Disconnect" : "Connect"
+ Layout.fillWidth: true
+ onClicked: {
+ if (BobinkClient.connected) {
+ BobinkClient.disconnectFromServer()
+ } else {
+ BobinkClient.auth = auth
+ BobinkClient.serverUrl = serverUrlField.text
+ BobinkClient.connectToServer()
+ }
+ }
+ }
+
+ Label {
+ text: "Status: " + (BobinkClient.connected ? "Connected" : "Disconnected")
+ color: BobinkClient.connected ? "green" : "red"
+ }
+
+ Item { Layout.fillHeight: true }
+ }
+}