9cad9ed0fc
v2-ci / build (push) Failing after 41s
v2-ci / unit-tests (tests/Core/ZB.MOM.WW.OtOpcUa.Cluster.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.ControlPlane.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Runtime.Tests) (push) Has been skipped
v2-ci / unit-tests (tests/Server/ZB.MOM.WW.OtOpcUa.Security.Tests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.Host.IntegrationTests) (push) Has been skipped
v2-ci / integration (tests/Server/ZB.MOM.WW.OtOpcUa.OpcUaServer.IntegrationTests) (push) Has been skipped
Adds <summary>/<param>/<returns>/<inheritdoc> where missing and removes project bookkeeping IDs (task/tracking refs) from shipped code comments, so the docs read cleanly and CommentChecker is quiet except for known false positives (PLC/protocol terms, event/IEqualityComparer inheritdoc). Doc/comment-only; no logic changed; solution builds clean.
98 lines
5.2 KiB
C#
98 lines
5.2 KiB
C#
using Serilog;
|
|
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Core.Scripting;
|
|
|
|
/// <summary>
|
|
/// The API user scripts see as the global <c>ctx</c>. Abstract — concrete subclasses
|
|
/// (e.g. <c>VirtualTagScriptContext</c>, <c>AlarmScriptContext</c>) plug in the
|
|
/// actual tag-backend + logger + virtual-tag writer for each evaluation. By design
|
|
/// (see <c>docs/v2/plan.md</c>), scripts can read any tag, write only to virtual
|
|
/// tags, and have no other .NET reach — no HttpClient, no File, no Process, no
|
|
/// reflection.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Every member on this type MUST be serializable in the narrow sense that
|
|
/// <c>DependencyExtractor</c> can recognize tag-access call sites from the
|
|
/// script AST. Method names used from scripts are locked — renaming
|
|
/// <see cref="GetTag"/> or <see cref="SetVirtualTag"/> is a breaking change for every
|
|
/// authored script and the dependency extractor must update in lockstep.
|
|
/// </para>
|
|
/// <para>
|
|
/// New helpers (<see cref="Now"/>, <see cref="Deadband"/>) are additive: adding a
|
|
/// method doesn't invalidate existing scripts. Do not remove or rename without a
|
|
/// plan-level decision + migration for authored scripts.
|
|
/// </para>
|
|
/// </remarks>
|
|
public abstract class ScriptContext
|
|
{
|
|
/// <summary>
|
|
/// Read a tag's current value + quality + source timestamp. Path syntax is
|
|
/// <c>Enterprise/Site/Area/Line/Equipment/TagName</c> (forward-slash delimited,
|
|
/// matching the Equipment-namespace browse tree). Returns a
|
|
/// <see cref="DataValueSnapshot"/> so scripts branch on quality without a second
|
|
/// call.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <paramref name="path"/> MUST be a string literal in the script source — dynamic
|
|
/// paths (variables, concatenation, method-returned strings) are rejected at
|
|
/// publish by <c>DependencyExtractor</c>. This is intentional: the static
|
|
/// dependency set is required for the change-driven scheduler to subscribe to the
|
|
/// right upstream tags at load time.
|
|
/// <para>
|
|
/// The reserved <c>{{equip}}</c> token may appear in the path literal; it is
|
|
/// substituted with the owning equipment's tag-base prefix at deployment time.
|
|
/// See <c>docs/ScriptEditor.md</c> — Equipment-relative tag paths.
|
|
/// </para>
|
|
/// </remarks>
|
|
/// <param name="path">The literal tag path to read.</param>
|
|
/// <returns>A snapshot of the tag's current value, quality, and source timestamp.</returns>
|
|
public abstract DataValueSnapshot GetTag(string path);
|
|
|
|
/// <summary>
|
|
/// Write a value to a virtual tag. Operator scripts cannot write to driver-sourced
|
|
/// tags — the OPC UA dispatch in <c>DriverNodeManager</c> rejects that separately
|
|
/// with <c>BadUserAccessDenied</c>. This method is the only write path
|
|
/// virtual tags have.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Path rules identical to <see cref="GetTag"/> — literal only, dependency
|
|
/// extractor tracks the write targets so the engine knows what downstream
|
|
/// subscribers to notify. The <c>{{equip}}</c> token is supported in the same way
|
|
/// as for <see cref="GetTag"/>.
|
|
/// </remarks>
|
|
/// <param name="path">The literal tag path to write to.</param>
|
|
/// <param name="value">The value to write to the virtual tag.</param>
|
|
public abstract void SetVirtualTag(string path, object? value);
|
|
|
|
/// <summary>
|
|
/// Current UTC timestamp. Prefer this over <see cref="DateTime.UtcNow"/> in
|
|
/// scripts so the harness can supply a deterministic clock for tests.
|
|
/// </summary>
|
|
public abstract DateTime Now { get; }
|
|
|
|
/// <summary>
|
|
/// Per-script Serilog logger. Output lands in the dedicated <c>scripts-*.log</c>
|
|
/// sink with structured property <c>ScriptName</c> = the script's configured name.
|
|
/// Use at error level to surface problems; main <c>opcua-*.log</c> receives a
|
|
/// companion WARN entry so operators see script errors in the primary log.
|
|
/// </summary>
|
|
public abstract ILogger Logger { get; }
|
|
|
|
/// <summary>
|
|
/// Deadband helper — returns <c>true</c> when <paramref name="current"/> differs
|
|
/// from <paramref name="previous"/> by more than <paramref name="tolerance"/>.
|
|
/// Useful for alarm predicates that shouldn't flicker on small noise. Pure
|
|
/// function; no side effects.
|
|
/// </summary>
|
|
/// <param name="current">The current value to check.</param>
|
|
/// <param name="previous">The previous value to compare against.</param>
|
|
/// <param name="tolerance">The minimum change magnitude to detect (must be >= 0).
|
|
/// Negative values cause the function to always return true; NaN always returns false.</param>
|
|
/// <returns><c>true</c> when <paramref name="current"/> differs from <paramref name="previous"/>
|
|
/// by more than <paramref name="tolerance"/>; otherwise <c>false</c>.</returns>
|
|
public static bool Deadband(double current, double previous, double tolerance)
|
|
=> Math.Abs(current - previous) > tolerance;
|
|
}
|