aboutsummaryrefslogtreecommitdiffstats
path: root/README.md
blob: a39694556a54474b0507506edc509321fe0567b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# BobinkQtOpcUa

A C++ library that wraps [Qt OPC UA](https://doc.qt.io/qt-6/qtopcua-index.html) into simple QML components for Qt Quick applications. Hide OPC UA complexity behind a clean, declarative API.

## Quick start

### Prerequisites

- CMake >= 3.16, Ninja
- Qt 6.10.2+ (with `qt-cmake` in PATH)
- OpenSSL development headers

### Build

```bash
git clone --recurse-submodules https://github.com/user/BobinkQtOpcUa.git
cd BobinkQtOpcUa

qt-cmake -S . -B build -G Ninja
qt-cmake --build build --parallel
```

The first configure automatically builds the bundled dependencies (open62541 and QtOpcUa) from git submodules under `deps/`. Subsequent builds skip this step.

### Run the demo

```bash
./build/bin/BobinkDemo
```

The demo app discovers local OPC UA servers, connects with configurable authentication and security, and lets you monitor and write to nodes.

## Usage

Import the `Bobink` QML module:

```qml
import Bobink
```

### Connect to a server

```qml
Connections {
    target: Bobink
    function onConnectedChanged() {
        console.log("Connected:", Bobink.connected)
    }
    function onConnectionError(message) {
        console.log("Error:", message)
    }
    function onCertificateTrustRequested(certInfo) {
        // Show certInfo to user, then call:
        Bobink.acceptCertificate()  // or rejectCertificate()
    }
}

Button {
    text: "Connect"
    onClicked: {
        Bobink.serverUrl = "opc.tcp://localhost:4840"
        Bobink.connectToServer()
    }
}
```

`connectToServer()` discovers endpoints and auto-selects the most secure one. If that fails, use `connectDirect()` with explicit security settings:

```qml
Bobink.connectDirect(Bobink.Basic256Sha256, Bobink.SignAndEncrypt)
```

### Authentication

```qml
OpcUaAuth {
    id: auth
    mode: OpcUaAuth.Anonymous  // or UserPass, Certificate
    username: "user"
    password: "pass"
}

// Set before connecting
Bobink.auth = auth
Bobink.connectToServer()
```

### Monitor and write nodes

```qml
OpcUaMonitoredNode {
    id: tempNode
    nodeId: "ns=2;s=Temperature"
    monitored: true  // creates an OPC UA monitored item
    publishingInterval: 500  // ms

    onValueChanged: console.log("Temperature:", value)
    onWriteCompleted: (success, message) => console.log(message)
}

// Display live value
Text { text: "Temperature: " + tempNode.value }

// Write a new value
Button {
    text: "Set to 25"
    enabled: tempNode.writable
    onClicked: tempNode.writeValue(25)
}
```

Type coercion is automatic -- QML values are converted to the node's OPC UA data type. For arrays, pass a comma-separated string: `writeValue("1, 2, 3")`.

Write to specific array elements with index range syntax:

```qml
tempNode.writeValueAtRange("42", "0")       // first element
tempNode.writeValueAtRange("1, 2, 3", "0:2") // elements 0-2
```

### Node metadata

Each `OpcUaMonitoredNode` exposes an `info` property with metadata read once on setup:

```qml
Text { text: node.info.displayName }
Text { text: node.info.dataType }
Text { text: node.info.description }
// Also: nodeClass, valueRank, arrayDimensions, accessLevel,
//        status, sourceTimestamp, serverTimestamp
```

### Server discovery

```qml
Component.onCompleted: {
    Bobink.discoveryUrl = "opc.tcp://localhost:4840"
    Bobink.startDiscovery()
}

ListView {
    model: Bobink.servers
    delegate: Text {
        text: modelData.serverName
        // Also available: modelData.applicationUri, modelData.discoveryUrls
    }
}
```

### PKI

Client certificates are auto-detected from the default PKI directory (`<AppDataLocation>/pki`). To configure manually:

```qml
Bobink.pkiDir = "/path/to/pki"
Bobink.certFile = "/path/to/cert.der"
Bobink.keyFile = "/path/to/key.pem"
Bobink.applyPki()
```

## Use as a git submodule

BobinkQtOpcUa can be added to your project as a git submodule:

```bash
git submodule add https://github.com/user/BobinkQtOpcUa.git deps/bobink
git submodule update --init --recursive
```

```cmake
# CMakeLists.txt
add_subdirectory(deps/bobink)

# Link against the library and its QML plugin
target_link_libraries(YourApp PRIVATE BobinkQtOpcUaplugin)

# Set RPATH so the open62541 backend plugin loads at runtime
set(CMAKE_BUILD_RPATH "${OPEN62541_INSTALL_DIR}/lib"
                      "${QTOPCUA_INSTALL_DIR}/lib")

# Tell Qt where to find the OPC UA backend plugin
target_compile_definitions(YourApp PRIVATE
    QTOPCUA_PLUGIN_PATH="${QTOPCUA_INSTALL_DIR}/plugins")
```

## Project structure

```
src/
  OpcUaClient.h/.cpp         Bobink singleton: connection, discovery, PKI
  OpcUaMonitoredNode.h/.cpp   Node monitoring, reading, writing
  OpcUaAuth.h/.cpp            Authentication configuration
demo/
  Main.qml                    Connection UI demo
  NodePage.qml                Node interaction demo
deps/
  open62541/                   C OPC UA stack (submodule)
  qtopcua/                     Qt OPC UA module (submodule)
```