53d222e0f7
Adds the Calculation pseudo-driver (tags computed by C# scripts over other tags' live values) plus the host seam that feeds it: - IDependencyConsumer capability interface (Core.Abstractions) + DriverTypeNames.Calculation. - CalculationDriver : IDriver, ISubscribable, IReadable, IDependencyConsumer — change-gate + dedupe (VirtualTagActor parity), timer-group scheduler, Bad-transition + script-log emission, Good recovery; reuses the T0-4 CalculationEvaluator. - DriverHostActor spawns a DependencyConsumerMuxAdapter per dependency-consuming driver, registering its refs on the per-node DependencyMuxActor and forwarding DependencyValueChanged → OnDependencyValue; re-registers on every apply, torn down with the driver. - Factory + probe registered in DriverFactoryBootstrap (keeps the T0-3 guard green); guard test csproj references the driver so the bin-scan discovers the factory. - DeploymentArtifact injects the resolved scriptSource (scriptId → SourceCode) into a calc tag's delivered TagConfig so the host-blind driver can compile it. - DraftValidator deploy gates: CalculationScriptMissing / CalculationScriptNotFound (scriptId existence) + CalculationDependencyCycle (DependencyGraph.DetectCycles over calc→calc edges). - Tests: driver units (dep-ref extraction, change-gate, dedupe, Bad+script-log+recovery, timer, read), tag-config parsing, DraftValidator gates (self/2-cycle/cross-driver-terminal), and a Runtime integration test proving values FLOW mux → adapter → driver → calc-of-calc end-to-end. Claude-Session: https://claude.ai/code/session_01LVneM3eh1UtJxEisFXgmox
45 lines
2.6 KiB
C#
45 lines
2.6 KiB
C#
namespace ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
|
|
/// <summary>
|
|
/// Optional composable driver capability: the driver consumes <b>other</b> tags' live values.
|
|
/// The host registers the declared <see cref="DependencyRefs"/> with its per-node dependency mux
|
|
/// and forwards every matching value change into <see cref="OnDependencyValue"/> — the seam that
|
|
/// lets a host-blind driver (e.g. the <c>Calculation</c> pseudo-driver) read the address space's
|
|
/// live values without any cross-driver plumbing of its own.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// The mechanism mirrors how a <c>VirtualTagActor</c> registers interest on the
|
|
/// <c>DependencyMuxActor</c>: the mux already receives every driver's
|
|
/// <c>AttributeValuePublished</c> keyed by wire-ref (under v3, RawPath), so a driver that
|
|
/// implements this interface simply piggy-backs on that fan-out. A calc tag's computed output
|
|
/// re-enters the mux via the ordinary driver publish path, so calc-of-calc chains work with no
|
|
/// extra machinery — which is exactly why the deploy-time cycle gate is mandatory.
|
|
/// </para>
|
|
/// <para>
|
|
/// Implementations of <see cref="OnDependencyValue"/> are invoked from an actor context and
|
|
/// <b>must be non-blocking</b> — do the work inline and cheaply (the compile cache makes
|
|
/// steady-state calc evaluation a bounded method invocation), never block on I/O.
|
|
/// </para>
|
|
/// </remarks>
|
|
public interface IDependencyConsumer
|
|
{
|
|
/// <summary>
|
|
/// Wire-refs (RawPaths) this driver needs fed to it, derived from its authored tags. The host
|
|
/// re-reads this after <see cref="IDriver.InitializeAsync"/> / <see cref="IDriver.ReinitializeAsync"/>
|
|
/// and (re)registers the set with its dependency mux on every apply, so a tag/script edit that
|
|
/// changes the set converges without a bespoke notification.
|
|
/// </summary>
|
|
IReadOnlyCollection<string> DependencyRefs { get; }
|
|
|
|
/// <summary>
|
|
/// Host push of a single dependency value change. Called from an actor context, so the
|
|
/// implementation must be non-blocking.
|
|
/// </summary>
|
|
/// <param name="rawPath">The changed dependency's wire-ref (RawPath).</param>
|
|
/// <param name="value">The new value (may be null).</param>
|
|
/// <param name="statusCode">The OPC UA status code carried with the value (0 = Good).</param>
|
|
/// <param name="timestampUtc">The source timestamp of the change.</param>
|
|
void OnDependencyValue(string rawPath, object? value, uint statusCode, DateTime timestampUtc);
|
|
}
|