# 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 (`/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") ``` ## 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](https://bugreports.qt.io/browse/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: ```cmake # 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) ```