Auto: focas-f3a — cnc_rdalmhistry alarm-history extension
Adds FocasAlarmProjection with two modes (ActiveOnly default, ActivePlusHistory) that polls cnc_rdalmhistry on connect + on a configurable cadence (5 min default, HistoryDepth=100 capped at 250). Emits historic events via IAlarmSource with SourceTimestampUtc set from the CNC's reported timestamp; dedup keyed on (OccurrenceTime, AlarmNumber, AlarmType). Ships the ODBALMHIS packed-buffer decoder + encoder in Wire/FocasAlarmHistoryDecoder.cs and threads ReadAlarmHistoryAsync through IFocasClient (default no-op so existing transport variants stay back-compat). FocasDriver now implements IAlarmSource. 13 new unit tests cover: mode switch, dedup, distinct-timestamp emission, type-as-key behaviour, OccurrenceTime passthrough (not Now), HistoryDepth clamp/fallback, and decoder round-trip. All 341 FOCAS unit tests still pass. Docs: docs/drivers/FOCAS.md (new), docs/v2/focas-deployment.md (new), docs/v2/implementation/focas-wire-protocol.md (new), docs/v2/implementation/focas-simulator-plan.md (new), docs/drivers/FOCAS-Test-Fixture.md (alarm-history bullet appended). Closes #267
This commit is contained in:
@@ -18,6 +18,86 @@ public sealed class FocasDriverOptions
|
||||
/// decimal-place division applied to position values before publishing.
|
||||
/// </summary>
|
||||
public FocasFixedTreeOptions FixedTree { get; init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Alarm projection knobs (issue #267, plan PR F3-a). Default mode is
|
||||
/// <see cref="FocasAlarmProjectionMode.ActiveOnly"/> — the projection only surfaces
|
||||
/// currently-active alarms. Operators who want the on-CNC ring-buffer history
|
||||
/// replayed as historic OPC UA events (so dashboards see the real CNC timestamp,
|
||||
/// not the moment the projection polled) flip this to
|
||||
/// <see cref="FocasAlarmProjectionMode.ActivePlusHistory"/>.
|
||||
/// </summary>
|
||||
public FocasAlarmProjectionOptions AlarmProjection { get; init; } = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Mode for the FOCAS alarm projection (issue #267, plan PR F3-a). Default
|
||||
/// <see cref="ActiveOnly"/> matches today's behaviour — only currently-active
|
||||
/// alarms surface as OPC UA events. <see cref="ActivePlusHistory"/> additionally
|
||||
/// polls <c>cnc_rdalmhistry</c> on connect + on a configurable cadence and emits the
|
||||
/// ring-buffer entries as historic events, deduped by <c>(OccurrenceTime, AlarmNumber,
|
||||
/// AlarmType)</c> so a polled entry never re-fires.
|
||||
/// </summary>
|
||||
public enum FocasAlarmProjectionMode
|
||||
{
|
||||
/// <summary>Surface only currently-active CNC alarms. No history poll. Default.</summary>
|
||||
ActiveOnly = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Surface active alarms plus the on-CNC ring-buffer history. The projection
|
||||
/// polls <c>cnc_rdalmhistry</c> on connect and on
|
||||
/// <see cref="FocasAlarmProjectionOptions.HistoryPollInterval"/> ticks afterward.
|
||||
/// Each new entry (keyed by <c>(OccurrenceTime, AlarmNumber, AlarmType)</c>)
|
||||
/// fires an <see cref="Core.Abstractions.IAlarmSource.OnAlarmEvent"/> with
|
||||
/// <c>SourceTimestampUtc</c> set from the CNC's reported timestamp, not Now.
|
||||
/// </summary>
|
||||
ActivePlusHistory = 1,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FOCAS alarm-projection knobs (issue #267, plan PR F3-a). Carries the mode switch +
|
||||
/// the cadence / depth tuning for the <c>cnc_rdalmhistry</c> poll loop. Defaults match
|
||||
/// "operator dashboard with five-minute refresh" — the single most common deployment
|
||||
/// shape per the F3-a deployment doc.
|
||||
/// </summary>
|
||||
public sealed record FocasAlarmProjectionOptions
|
||||
{
|
||||
/// <summary>Default poll interval — 5 minutes. Matches dashboard-class cadences.</summary>
|
||||
public static readonly TimeSpan DefaultHistoryPollInterval = TimeSpan.FromMinutes(5);
|
||||
|
||||
/// <summary>
|
||||
/// Default ring-buffer depth requested per poll — <c>100</c>. Most FANUC controllers
|
||||
/// keep ~100 entries by default; pulling the full depth on every poll keeps the
|
||||
/// dedup set authoritative across reconnects without burning extra wire bandwidth on
|
||||
/// entries the dedup key would discard anyway.
|
||||
/// </summary>
|
||||
public const int DefaultHistoryDepth = 100;
|
||||
|
||||
/// <summary>
|
||||
/// Hard ceiling on <see cref="HistoryDepth"/>. The projection clamps user-requested
|
||||
/// depths above this value down — typical CNC ring buffers cap well below this and
|
||||
/// letting an operator type <c>10000</c> by accident shouldn't take down the wire
|
||||
/// session with a giant <c>cnc_rdalmhistry</c> request.
|
||||
/// </summary>
|
||||
public const int MaxHistoryDepth = 250;
|
||||
|
||||
/// <summary>Active-only (default) vs Active-plus-history. See <see cref="FocasAlarmProjectionMode"/>.</summary>
|
||||
public FocasAlarmProjectionMode Mode { get; init; } = FocasAlarmProjectionMode.ActiveOnly;
|
||||
|
||||
/// <summary>
|
||||
/// Cadence at which the projection re-polls <c>cnc_rdalmhistry</c> when
|
||||
/// <see cref="Mode"/> is <see cref="FocasAlarmProjectionMode.ActivePlusHistory"/>.
|
||||
/// Default <see cref="DefaultHistoryPollInterval"/> = 5 minutes. Only applies after
|
||||
/// the on-connect poll fires.
|
||||
/// </summary>
|
||||
public TimeSpan HistoryPollInterval { get; init; } = DefaultHistoryPollInterval;
|
||||
|
||||
/// <summary>
|
||||
/// Number of most-recent ring-buffer entries to request per poll. Clamped to
|
||||
/// <c>[1..<see cref="MaxHistoryDepth"/>]</c> at projection startup so misconfigured
|
||||
/// values can't hammer the CNC. Default <see cref="DefaultHistoryDepth"/> = 100.
|
||||
/// </summary>
|
||||
public int HistoryDepth { get; init; } = DefaultHistoryDepth;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
Reference in New Issue
Block a user