namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions; /// /// Driver capability for invoking OPC UA Methods on the upstream backend (the OPC UA /// Call service). Optional — only drivers whose backends carry method nodes /// implement it. Currently the OPC UA Client driver is the only implementer; tag-based /// drivers (Modbus, S7, FOCAS, Galaxy, AB-CIP, AB-Legacy, TwinCAT) don't expose method /// nodes so they don't need this surface. /// /// /// /// Per docs/v2/plan.md decision #4 (composable capability interfaces) — the /// server-side DriverNodeManager discovers method-bearing drivers via an /// is IMethodInvoker check and routes OnCallMethod handlers to /// . Drivers that don't implement the interface simply /// never have method nodes registered for them. /// /// /// The address-space mirror is driven by /// — drivers register the method node + its InputArguments / /// OutputArguments properties during discovery, then invocations land back on /// via the server-side dispatcher. /// /// public interface IMethodInvoker { /// /// Invoke an upstream OPC UA Method. The driver translates input arguments into the /// wire-level CallMethodRequest, dispatches via the active session, and packs /// the response back into a . Per-argument validation /// errors flow through ; method-level /// errors (BadMethodInvalid, BadUserAccessDenied, etc.) flow through /// . /// /// /// Stringified NodeId of the OPC UA Object that owns the method (the ObjectId /// field of CallMethodRequest). Same serialization as IReadable's /// fullReferencens=2;s=… / i=… / nsu=…;…. /// /// /// Stringified NodeId of the Method node itself (the MethodId field). /// /// /// Input arguments in declaration order. The driver wraps each value as a /// Variant; callers pass CLR primitives (plus arrays) — the wire-level /// encoding is the driver's concern. /// /// Per-call cancellation. /// /// Result of the call — see . Never throws for a /// Bad upstream status; the bad code is surfaced via the result so the caller /// can map it onto an OPC UA service-result for downstream clients. /// Task CallMethodAsync( string objectNodeId, string methodNodeId, object[] inputs, CancellationToken cancellationToken); } /// /// Result of a single OPC UA Call service invocation. /// /// /// Method-level status. 0 = Good. Bad codes pass through verbatim from the /// upstream so downstream clients see the canonical OPC UA error (e.g. /// BadMethodInvalid, BadUserAccessDenied, BadArgumentsMissing). /// /// /// Output argument values in declaration order. null when the upstream returned /// no output arguments (or returned a Bad status before producing any). /// /// /// Per-input-argument status codes. null when the upstream didn't surface /// per-argument validation results (typical for Good calls). Each entry is the OPC UA /// status code for the matching input argument — drivers can use this to surface /// BadTypeMismatch, BadOutOfRange, etc. on a specific argument. /// public sealed record MethodCallResult( uint StatusCode, object[]? Outputs, uint[]? InputArgumentResults);