Skip to content

xentropic-dev/zopcua

Repository files navigation

🏭 zopcua

A Zig wrapper for open62541, an open-source OPC UA implementation.

License: MIT CI GitHub Stars Zig 0.14

⚠️ Development Status

This library is under active development and NOT ready for production use.

Feature Parity: 28% complete (see ROADMAP.md)

Progress: [█████░░░░░░░░░░░░░░░] 28%
  • Requires Zig 0.15.2
  • See branch/tag history for previous Zig versions
  • APIs are unstable and subject to change

Project Goals

This wrapper aims to make working with open62541 feel native to Zig by:

  1. Memory Safety - Proper allocator usage, clear ownership semantics, no manual memory management
  2. Zig Idioms - Error return types, tagged unions, comptime features instead of C conventions
  3. Type Safety - Strongly-typed wrappers eliminating void pointers and C-style type erasure
  4. Abstraction - Hide C complexities like bitfields, null-terminated strings, and manual struct initialization

This library will not reach full feature parity with open62541 for some time. If you need functionality that isn't yet wrapped, please open an issue!

Features

✅ Currently Implemented

Server:

  • Server lifecycle (init, start, stop, iterate, runUntilInterrupt)
  • Variable nodes (add with full attribute control)
  • Object nodes (add with attributes)
  • Namespace management (add, lookup by name/index)
  • Custom server configuration (port, security mode)

Client:

  • Client lifecycle (init, connect, disconnect)
  • Read operations (readValueAttribute)
  • Write operations (writeValueAttribute)
  • Browse operations (browse, browseNext with full control)
  • Custom client configuration (timeout, security mode)

Data Types:

  • NodeId (numeric, string, GUID, bytestring)
  • Variant (scalars and arrays for all basic types)
  • QualifiedName, LocalizedText, ExpandedNodeId
  • VariableAttributes, ObjectAttributes
  • Browse types and masks
  • Comprehensive error types

🚧 Planned/In Progress

  • Subscriptions & monitored items (high priority)
  • Method calls (medium priority)
  • Events & alarms (medium priority)
  • Server-side read/write operations
  • Client node management
  • History access
  • PubSub
  • Security & certificates
  • Discovery services

See ROADMAP.md for detailed progress tracking.

Documentation

📚 View the full API documentation

Guides:

Installation

Add zopcua to your project:

zig fetch --save git+https://github.com/xentropic-dev/zopcua.git

Then in your build.zig:

const std = @import("std");
const zopcua = @import("zopcua");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "my-app",
        .root_module = b.createModule(.{
            .root_source_file = b.path("src/main.zig"),
            .target = target,
            .optimize = optimize,
        }),
    });

    // Add zopcua - automatically handles module import and platform-specific linking
    zopcua.setup(exe, .{});

    b.installArtifact(exe);
}

That's it! The setup function automatically:

  • Adds the ua module to your executable
  • Links required system libraries (ws2_32, advapi32, crypt32, bcrypt on Windows)
  • Links required frameworks (Security, CoreFoundation on macOS)
  • Handles all platform-specific configuration

mbedTLS Dependency

zopcua requires mbedTLS for cryptographic operations and secure communication. By default, mbedTLS is statically linked from vendored sources - no system installation required.

If you prefer to use system-installed mbedTLS libraries instead:

zopcua.setup(exe, .{
    .mbedtls = .system,  // Use system mbedTLS instead of vendored
});

When using system mbedTLS, ensure the libraries are installed:

  • macOS: brew install mbedtls
  • Ubuntu/Debian: sudo apt install libmbedtls-dev
  • Other Linux: Use your distribution's package manager

Quick Start

Minimal Server

const std = @import("std");
const ua = @import("ua");

pub fn main() !void {
    var server = try ua.Server.init();
    defer server.deinit();

    try server.runUntilInterrupt(); // Blocks until Ctrl-C
}

Server with Variable

const std = @import("std");
const ua = @import("ua");

pub fn main() !void {
    var server = try ua.Server.init();
    defer server.deinit();

    _ = try server.addVariableNode(
        ua.NodeId.initString(1, "temperature"),
        ua.StandardNodeId.objects_folder,
        ua.ReferenceType.organizes,
        ua.QualifiedName.init(1, "Temperature"),
        ua.StandardNodeId.base_data_variable_type,
        .{
            .value = ua.Variant.scalar(f64, 23.5),
            .display_name = ua.LocalizedText.init("en-US", "Temperature"),
            .access_level = .{ .read = true, .write = true },
        },
    );

    try server.runUntilInterrupt();
}

Client Reading Values

const std = @import("std");
const ua = @import("ua");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    var client = try ua.Client.init();
    defer client.deinit();

    try client.connect("opc.tcp://localhost:4840");
    defer client.disconnect() catch {};

    const node_id = ua.NodeId.initString(1, "temperature");
    const variant = try client.readValueAttribute(allocator, node_id);
    defer variant.deinit(allocator);

    std.debug.print("Temperature: {d}\n", .{variant.double});
}

See docs/EXAMPLES.md for more examples including writing values, browsing, arrays, objects, namespaces, and error handling.

Building

# Build the library (uses vendored mbedTLS by default)
zig build

# Build with system mbedTLS
zig build -Dmbedtls=system

# Run tests
zig build test

# Generate documentation
zig build docs

License

This wrapper library is licensed under the MIT License. See LICENSE for details.

The underlying open62541 library is licensed under the Mozilla Public License 2.0. See the open62541 repository for details.

Contributing

Contributions are welcome! Here's how you can help:

  1. Check ROADMAP.md to see what features need implementation
  2. Look for missing features - The library is at 28% parity with open62541, lots to do!
  3. Submit PRs with new features, bug fixes, or improved documentation
  4. Open issues for features you need or bugs you encounter
  5. Add tests for new functionality

High Priority Areas

  • Subscriptions & monitored items
  • Method calls
  • Server-side read/write operations
  • Client node management
  • Additional attribute operations

See the roadmap for a complete breakdown of missing features.

About

A Zig wrapper for open62541 that makes OPC UA development feel native to Zig through idiomatic patterns and abstracted C complexities.

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages