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-levelIDiscoveryServiceinterface, not directly onIOpcSharpClient.