aboutsummaryrefslogtreecommitdiffstats

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-cmake in 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)