8.7 KiB
source_files, generated_at, model, schema_version, sha256
| source_files | generated_at | model | schema_version | sha256 | |
|---|---|---|---|---|---|
|
2026-04-16T03:32:13.517351+00:00 | Qwen/Qwen3-Coder-Next-FP8 | 1 | 8fbd8ac85721cb74 |
StateMachines
Documentation: OverallArmStatusStateMachine
1. Purpose
The OverallArmStatusStateMachine class implements a state machine that tracks and manages the high-level operational status of an arm subsystem (likely related to data acquisition or recording hardware) within the DTS system. It uses the Stateless library to define transitions between states such as Recording, IDLE, WaitingForTrigger, Downloading, and Disarmed, based on triggers like Recording, DoneRecording, Disarm, and DASNotFound. Its primary role is to maintain a canonical "overall arm status" state, emit notifications on state changes via the OverallStatusStateChange event, and serve as a central coordination point for status reporting across the application (e.g., updating a global status UI field). It does not manage low-level arm logic but aggregates and reflects higher-level transitions.
2. Public Interface
Constructor
public OverallArmStatusStateMachine()
- Initializes the
IEventAggregatorviaContainerLocator.Container.Resolve<IEventAggregator>(). - Calls
Initialize()to configure the underlyingStateless.StateMachine.
Events
public event OverallStatusStateChangeDelegate OverallStatusStateChange;
- Delegate:
public delegate void OverallStatusStateChangeDelegate(ArmStateMachineStates.States previousState, ArmStateMachineStates.States nextState); - Fired whenever the overall status transitions to a new state (i.e.,
CurrentOverallStatusStatechanges). The event includes the previous and next state.
Methods
public ArmStateMachineStates.States GetDASStatus()
- Returns the current overall status state (
CurrentOverallStatusState).
public void FireTrigger(Triggers trigger, ArmStateMachineStates.States state)
- Fires a named trigger with an associated target state parameter (note: this is unusual—see Gotchas).
- Internally maps each
Triggersenum value to a pre-configuredTriggerWithParameters<ArmStateMachineStates.States>and invokesStateMachine.Fire(trigger, state). - Logs exceptions via
APILogger.Log(ex.Message); does not rethrow. - Special case:
Triggers.PostTestProcessingincorrectly firesDoneRecordingTriggerinstead of a dedicatedPostTestProcessingTrigger.
Nested Types
public enum Triggers: Defines 37+ named triggers (e.g.,Recording,Disarm,DASNotFound,Downloading,WaitingForTrigger,WaitingForSchedule,WaitingForInterval,ReadyForDownload,DoneRecording,NoDataToDownload,DataNeverDownloaded,Streaming,FlashClear,Error,GettingEventInfo,CheckingForData,Rearming,IDLE,IntervalRecording,NonIntervalRecording,RunButton,a,c,d,e,h,n,rr,tt,uu,yy).- Note: Several triggers (
a,c,d,e,h,n,rr,tt,uu,yy) appear to be placeholder or legacy names with no documented purpose.
- Note: Several triggers (
3. Invariants
- Initial State: The state machine always starts in
ArmStateMachineStates.States.CheckingForDAS. - Current State Tracking:
CurrentOverallStatusStateis updated only viaSetOverallStatus(), which:- Compares
newStatetoCurrentOverallStatusState. - Logs transitions via
APILogger.Log(...). - Invokes
OverallStatusStateChangeonly if the state changes.
- Compares
- State Machine Library: Uses
Stateless.StateMachine<ArmStateMachineStates.States, Triggers>. - Parameterized Triggers: All transitions that accept a state parameter use
SetTriggerParameters<ArmStateMachineStates.States>(), meaning every trigger expects a target state as an argument when fired (e.g.,Fire(trigger, targetState)). - No Explicit Error Handling in Transitions: Transitions do not define custom
OnEntryFrom/OnExitlogic beyond callingSetOverallStatus(); no fallback or recovery behavior is defined in the state configuration.
4. Dependencies
Imports/Usings
Stateless– Core state machine library.Prism.Ioc.ContainerLocator– For resolvingIEventAggregator.DTS.Common.Enums.TSRAIRGo– ProvidesArmStateMachineStates.States(not shown in this file).DTS.Common.Utilities.Logging– ProvidesAPILogger.SystemandPrism.Events– ForIEventAggregator.
External Dependencies
ArmStateMachineStates.States: An external enum defining the valid states (e.g.,CheckingForDAS,IDLE,Recording,Disarmed,Downloading,ClearingFlash,WaitingForTrigger,WaitingForSchedule,WaitingForInterval,PostTestProcessing,GettingEventInfo,ReadyForDownload,Streaming). Its definition is not included here.APILogger: Static logging utility.ContainerLocator: Prism DI container accessor (assumesIEventAggregatoris registered).
Consumers
- Any component needing to update or query the overall arm status (e.g., UI, telemetry, control logic) must:
- Subscribe to
OverallStatusStateChangeto react to state changes. - Call
FireTrigger()to signal events. - Call
GetDASStatus()to poll the current state.
- Subscribe to
5. Gotchas
-
Unusual Trigger Signature: All triggers are defined as
TriggerWithParameters<ArmStateMachineStates.States>, meaning everyFire()call must supply a target state (e.g.,Fire(RecordingTrigger, ArmStateMachineStates.States.Recording)). This is atypical—most state machines infer the next state from the transition configuration. The comment inFireTrigger()("why specify state here? shouldn't that be done based on current state/trigger?") confirms this design is questionable and likely error-prone. -
Incorrect Trigger Mapping: In
FireTrigger(),Triggers.PostTestProcessingincorrectly firesDoneRecordingTriggerinstead of a dedicatedPostTestProcessingTrigger. This may cause unintended state transitions (e.g., skippingPostTestProcessingstate entirely). -
Unused Triggers: The
Triggersenum includes 10 cryptic triggers (a,c,d,e,h,n,rr,tt,uu,yy) with no corresponding configuration inInitialize(). These are likely legacy or placeholders and should be removed or documented. -
No Handling for
ErrorTrigger: WhileErrorTriggeris declared, it is not used in any state configuration (no.Permit()or.OnEntryFrom()references it). Attempting to fire it will throw aStatelessexception (trigger not defined for current state). -
Ignored Triggers May Cause Silent Failures: Several states use
.Ignore()for specific triggers (e.g.,ClearingFlashignoresReadyForDownload,NoDataToDownload,DataNeverDownloaded). Firing these triggers in those states will throw an exception (not silently ignored), contradicting the intent of.Ignore()inStateless(which does allow the trigger but prevents transition). VerifyStatelessbehavior—this may be a source of runtime exceptions. -
No Public Setter for State: The current state is read-only via
GetDASStatus(). There is no way to manually override or reset the state machine (e.g., for testing or recovery), which may complicate error recovery. -
Logging Side Effect:
SetOverallStatus()logs every transition, which may be excessive in high-frequency scenarios. No filtering or throttling is applied. -
Missing State Definitions: The states used (e.g.,
ArmStateMachineStates.States.CheckingForDAS) are referenced but not defined in this file. Their semantics and relationships depend on the externalArmStateMachineStates.Statesenum. -
No Validation on State Parameter:
FireTrigger()accepts anyArmStateMachineStates.Statesas the second parameter. Passing an invalid or inconsistent state (e.g.,Fire(RecordingTrigger, ArmStateMachineStates.States.Disarmed)) may result in runtime exceptions or undefined behavior. -
Exception Swallowing:
FireTrigger()catches and logs all exceptions (includingStatelessexceptions likeInvalidOperationExceptionfor invalid transitions), but does not propagate them. This can mask critical failures. -
No Thread Safety: The class does not indicate thread-safety. Concurrent calls to
FireTrigger()or state queries may cause race conditions. -
Graph Generation Side Effect:
Stateless.Graph.UMLDotGraph.Format(...)is called but the result is discarded (string graph = ...; graph = ...;). This suggests debugging code was left in place.
Documentation generated from source file Common/DTS.Common.DataModel/StateMachines/OverallArmStatusStateMachine.cs.