Skip to content

Services

OpcSharp provides typed service interfaces for the most common OPC UA operations.

Attribute Service

Read and write node attributes.

// Read multiple values
var results = await client.ReadAsync(new[]
{
    new ReadValueId { NodeId = new NodeId(0, 2258), AttributeId = AttributeIds.Value },
    new ReadValueId { NodeId = new NodeId(0, 2259), AttributeId = AttributeIds.Value }
});

// Write a value
var statusCodes = await client.WriteAsync(new[]
{
    new WriteValue
    {
        NodeId = new NodeId(2, "MyVar"),
        AttributeId = AttributeIds.Value,
        Value = new DataValue(new Variant(42))
    }
});

Browse Service

Navigate the server’s address space.

// Browse children of the Objects folder
var browseResults = await client.BrowseAsync(new[]
{
    new BrowseDescription
    {
        NodeId = ObjectIds.ObjectsFolder,
        BrowseDirection = BrowseDirection.Forward,
        ReferenceTypeId = ReferenceTypeIds.HierarchicalReferences,
        IncludeSubtypes = true,
        ResultMask = (uint)BrowseResultMask.All
    }
});

foreach (var reference in browseResults[0].References)
{
    Console.WriteLine($"{reference.DisplayName} ({reference.NodeId})");
}

// Limit references per node (useful for large address spaces)
var pagedResults = await client.BrowseAsync(new[]
{
    new BrowseDescription
    {
        NodeId = ObjectIds.ObjectsFolder,
        BrowseDirection = BrowseDirection.Forward
    }
}, requestedMaxReferencesPerNode: 100);

BrowseNext

Handle continuation points when the server returns more references than the requested limit:

var results = await client.BrowseAsync(browseDescriptions, requestedMaxReferencesPerNode: 10);

// Follow continuation points to get all references
while (results[0].ContinuationPoint != null)
{
    var nextResults = await client.BrowseNextAsync(
        new[] { results[0].ContinuationPoint });
    // process nextResults...
    results = nextResults;
}

// Release continuation points without fetching more results
await client.BrowseNextAsync(
    new[] { continuationPoint }, releaseContinuationPoints: true);

RegisterNodes / UnregisterNodes

Optimize repeated access to the same nodes. The server may return optimized handles that reduce overhead on subsequent Read/Write calls:

// Register nodes for repeated access
var registeredNodes = await client.RegisterNodesAsync(
    new[] { new NodeId(0, 2258), new NodeId(0, 2259) });

// Use the registered NodeIds for faster Read/Write operations
var values = await client.ReadAsync(new[]
{
    new ReadValueId { NodeId = registeredNodes[0], AttributeId = AttributeIds.Value },
    new ReadValueId { NodeId = registeredNodes[1], AttributeId = AttributeIds.Value }
});

// Unregister when done
await client.UnregisterNodesAsync(registeredNodes);

TranslateBrowsePathsToNodeIds

Resolve nodes by path instead of NodeId:

// Batch API — takes BrowsePath[]
var results = await client.TranslateBrowsePathsToNodeIdsAsync(new[]
{
    new BrowsePath
    {
        StartingNode = ObjectIds.ObjectsFolder,
        RelativePath = RelativePath.Parse("Server/ServerStatus/CurrentTime")
    }
});

// Convenience API — single path
var result = await client.TranslateBrowsePathAsync(
    ObjectIds.ObjectsFolder,
    "Server/ServerStatus/CurrentTime");

Method Service

Call methods on the server.

var results = await client.CallAsync(new[]
{
    new CallMethodRequest
    {
        ObjectId = new NodeId(2, "MyObject"),
        MethodId = new NodeId(2, "MyMethod"),
        InputArguments = new Variant[] { new Variant(42), new Variant("hello") }
    }
});

Subscription Service

Create and manage subscriptions for real-time data.

// Create a subscription
var subscription = await client.CreateSubscriptionAsync(
    publishingInterval: 1000,
    lifetimeCount: 60,
    maxKeepAliveCount: 10);

// Delete subscriptions
var statusCodes = await client.DeleteSubscriptionsAsync(
    new[] { subscription.SubscriptionId });

SetPublishingMode

Pause and resume notifications without deleting the subscription:

// Disable publishing (notifications are queued on the server)
await client.SetPublishingModeAsync(false,
    new[] { subscription.SubscriptionId });

// Re-enable publishing (queued notifications are delivered)
await client.SetPublishingModeAsync(true,
    new[] { subscription.SubscriptionId });

Republish

Re-request a missed notification message by sequence number:

// Re-request notification with sequence number 42
var message = await client.RepublishAsync(
    subscription.SubscriptionId,
    retransmitSequenceNumber: 42);

Console.WriteLine($"Recovered notification: seq={message.SequenceNumber}, " +
    $"published={message.PublishTime}, data={message.NotificationData.Length} items");

MonitoredItem Service

Add items to a subscription to watch for changes.

// Create monitored items
var items = await client.CreateMonitoredItemsAsync(
    subscription.SubscriptionId,
    new[]
    {
        new MonitoredItemCreateRequest
        {
            ItemToMonitor = new ReadValueId
            {
                NodeId = new NodeId(0, 2258),
                AttributeId = AttributeIds.Value
            },
            MonitoringMode = MonitoringMode.Reporting,
            RequestedParameters = new MonitoringParameters
            {
                SamplingInterval = 500,
                QueueSize = 10,
                DiscardOldest = true
            }
        }
    });

// Handle data changes
client.DataChanged += (sender, args) =>
{
    Console.WriteLine($"Node {args.NodeId}: {args.Value}");
};

// Modify monitored items at runtime
var modifyResults = await client.ModifyMonitoredItemsAsync(
    subscription.SubscriptionId,
    new[]
    {
        new MonitoredItemModifyRequest
        {
            MonitoredItemId = items[0].MonitoredItemId,
            RequestedParameters = new MonitoringParameters
            {
                SamplingInterval = 100
            }
        }
    });

// Delete monitored items
var deleteResults = await client.DeleteMonitoredItemsAsync(
    subscription.SubscriptionId,
    new[] { items[0].MonitoredItemId });

SetMonitoringMode

Enable, disable, or switch monitored items to sampling mode without deleting them:

// Disable monitoring (stops notifications but keeps the item)
await client.SetMonitoringModeAsync(
    subscription.SubscriptionId,
    MonitoringMode.Disabled,
    new[] { items[0].MonitoredItemId });

// Switch to sampling (server samples but doesn't send notifications)
await client.SetMonitoringModeAsync(
    subscription.SubscriptionId,
    MonitoringMode.Sampling,
    new[] { items[0].MonitoredItemId });

// Re-enable reporting
await client.SetMonitoringModeAsync(
    subscription.SubscriptionId,
    MonitoringMode.Reporting,
    new[] { items[0].MonitoredItemId });

Discovery Service

Discover available endpoints on a server.

// Get available endpoints
var endpoints = await client.GetEndpointsAsync();
foreach (var ep in endpoints)
{
    Console.WriteLine($"{ep.EndpointUrl} — {ep.SecurityPolicyUri} [{ep.SecurityMode}]");
}

Note: FindServersAsync() is available on the lower-level IDiscoveryService interface, not directly on IOpcSharpClient.