feat(otopcua): capturing address-space builder for driver discovery
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
|
||||
|
||||
/// <summary>
|
||||
/// An <see cref="IAddressSpaceBuilder"/> that RECORDS the streamed tree instead of creating OPC UA
|
||||
/// nodes — used to capture an <see cref="ITagDiscovery"/> driver's discovered hierarchy so the
|
||||
/// runtime can graft it under an equipment node. Folder nesting is tracked (each child builder
|
||||
/// carries its accumulated path), so every variable records its full <see cref="DiscoveredNode.FolderPathSegments"/>.
|
||||
/// <para>Value nodes only: <see cref="AddProperty"/> is ignored and alarm marking returns a no-op sink
|
||||
/// (discovered alarms are out of scope — alarms come via the config path).</para>
|
||||
/// <para>Single-threaded: a driver's <c>DiscoverAsync</c> streams on one caller; the root and its child
|
||||
/// builders share one <see cref="List{T}"/>. Not thread-safe by design.</para>
|
||||
/// </summary>
|
||||
public sealed class CapturingAddressSpaceBuilder : IAddressSpaceBuilder
|
||||
{
|
||||
private readonly List<DiscoveredNode> _nodes;
|
||||
private readonly IReadOnlyList<string> _path;
|
||||
|
||||
/// <summary>Create a root capturing builder with an empty folder path and a fresh node list.</summary>
|
||||
public CapturingAddressSpaceBuilder() : this([], []) { }
|
||||
|
||||
private CapturingAddressSpaceBuilder(List<DiscoveredNode> nodes, IReadOnlyList<string> path)
|
||||
{
|
||||
_nodes = nodes;
|
||||
_path = path;
|
||||
}
|
||||
|
||||
/// <summary>All variables captured across the whole tree (shared by the root and every child scope).</summary>
|
||||
public IReadOnlyList<DiscoveredNode> Nodes => _nodes;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IAddressSpaceBuilder Folder(string browseName, string displayName)
|
||||
=> new CapturingAddressSpaceBuilder(_nodes, [.. _path, browseName]);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IVariableHandle Variable(string browseName, string displayName, DriverAttributeInfo attributeInfo)
|
||||
{
|
||||
_nodes.Add(new DiscoveredNode(
|
||||
FolderPathSegments: _path,
|
||||
BrowseName: browseName,
|
||||
DisplayName: displayName,
|
||||
FullReference: attributeInfo.FullName,
|
||||
DataType: attributeInfo.DriverDataType,
|
||||
IsArray: attributeInfo.IsArray,
|
||||
ArrayDim: attributeInfo.ArrayDim,
|
||||
Writable: attributeInfo.SecurityClass != SecurityClassification.ViewOnly,
|
||||
IsHistorized: attributeInfo.IsHistorized));
|
||||
return new NullHandle(attributeInfo.FullName);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void AddProperty(string browseName, DriverDataType dataType, object? value) { /* metadata only — ignored */ }
|
||||
|
||||
/// <summary>A variable handle whose alarm marking is a no-op (discovered alarms are out of scope).</summary>
|
||||
private sealed class NullHandle(string fullRef) : IVariableHandle
|
||||
{
|
||||
public string FullReference => fullRef;
|
||||
public IAlarmConditionSink MarkAsAlarmCondition(AlarmConditionInfo info) => new NullSink();
|
||||
}
|
||||
|
||||
/// <summary>A null sink that ignores alarm condition transitions.</summary>
|
||||
private sealed class NullSink : IAlarmConditionSink
|
||||
{
|
||||
public void OnTransition(AlarmEventArgs args) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Runtime.Drivers;
|
||||
|
||||
/// <summary>
|
||||
/// A flattened variable captured from a driver's <see cref="ITagDiscovery.DiscoverAsync"/> stream
|
||||
/// by <see cref="CapturingAddressSpaceBuilder"/>. Folder nesting is preserved in
|
||||
/// <see cref="FolderPathSegments"/> so the injector can re-root the node under an equipment.
|
||||
/// </summary>
|
||||
public sealed record DiscoveredNode(
|
||||
IReadOnlyList<string> FolderPathSegments,
|
||||
string BrowseName,
|
||||
string DisplayName,
|
||||
string FullReference,
|
||||
DriverDataType DataType,
|
||||
bool IsArray,
|
||||
uint? ArrayDim,
|
||||
bool Writable,
|
||||
bool IsHistorized);
|
||||
Reference in New Issue
Block a user