BobinkQtOpcUa
A C++ library that wraps Qt OPC UA 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-cmakein PATH) - OpenSSL development headers
Build
git clone --recurse-submodules https://github.com/user/BobinkQtOpcUa.git
cd BobinkQtOpcUa
qt-cmake -S . -B build/Debug -G Ninja -DCMAKE_BUILD_TYPE=Debug
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.
QtCreator can also be used to configure, build and run the project.
Run the demo
./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:
import Bobink
Connect to a server
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:
Bobink.connectDirect(Bobink.Basic256Sha256, Bobink.SignAndEncrypt)
Authentication
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
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:
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:
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
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:
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:
git submodule add https://github.com/user/BobinkQtOpcUa.git deps/bobink
git submodule update --init --recursive
# 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")
Editor setup (QML Language Server)
The build generates .qmlls.ini files so that qmlls can resolve both Qt and local Bobink QML imports.
Neovim — works out of the box if your LSP config picks up qmlls.
Qt Creator — enable the language server under Edit > Preferences > Language Client > QML Language Server.
QML formatting — a .qmlformat.ini is included at the project root. qmlformat picks it up automatically from the terminal (qmlformat -i file.qml). Qt Creator does not respect .qmlformat.ini or its own Code Style settings when formatting (QTCREATORBUG-29668) — use the command line instead.
Submodule users — since QT_QML_GENERATE_QMLLS_INI and the demo are only enabled for top-level builds, add these to your own project:
# Enable .qmlls.ini generation
set(QT_QML_GENERATE_QMLLS_INI ON CACHE BOOL "")
# Add the build QML directory so qmlls can resolve the Bobink import
qt_add_qml_module(YourApp
URI YourApp
...
IMPORT_PATH "${CMAKE_BINARY_DIR}/qml")
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)
