Files
2026-04-17 14:55:32 -04:00

340 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- DataPRO/IService/StateMachine/StatusAndParameters/Configure/GroupChannelWithMeta.cs
- DataPRO/IService/StateMachine/StatusAndParameters/Configure/ConfigureStatusParameters.cs
- DataPRO/IService/StateMachine/StatusAndParameters/Configure/ConfigureStatusInformation.cs
generated_at: "2026-04-16T04:01:25.793483+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "14ca5b532e4bb3a2"
---
# Configure
## Documentation: `ConfigureStatusParameters` and `ConfigureStatusInformation` Module
---
### 1. **Purpose**
This module provides the state and control logic for the *configuration phase* of the DAS (Data Acquisition System) lifecycle, specifically handling channel assignment resolution, hardware configuration application, and power/excitation state transitions. It enables asynchronous configuration of multiple DAS units with rich metadata about channel conflicts, missing sensors, and hardware incompatibilities, while supporting both production and diagnostic workflows. The module decouples configuration intent (expressed via `ConfigureStatusParameters`) from runtime state and progress tracking (managed by `ConfigureStatusInformation`), allowing integration with UI, testing, or headless environments via delegates.
---
### 2. **Public Interface**
#### `ConfigureStatusParameters`
- **`public bool RequireIdFoundForSensorsWithIds { get; set; } = true;`**
If `true`, sensors with a non-empty EID must be found on the configured hardware; otherwise, configuration may proceed without them.
- **`public bool AllowMissingSensors { get; set; } = false;`**
If `true`, allows channels to be assigned without a corresponding sensor (e.g., for dummy testing).
- **`public bool AllowSensorsOutOfPosition { get; set; } = true;`**
If `true`, permits sensors to be assigned to channels other than their specified physical position.
- **`public ITestSetup TestSetupConfiguration { get; set; }`**
Reference to the test setup configuration used during channel resolution.
- **`public delegate ISensorData GetSensorDelegate(IGroupChannel groupChannel);`**
Delegate to retrieve sensor metadata (`ISensorData`) for a given group channel.
- **`public GetSensorDelegate GetSensorAction { get; set; }`**
Implementation of `GetSensorDelegate`; required for sensor lookup during channel resolution.
- **`public delegate ISensorCalibration GetSensorCalibrationDelegate(ISensorData sensor, ExcitationVoltageOptions.ExcitationVoltageOption excitation);`**
Delegate to retrieve calibration data for a sensor under a specific excitation.
- **`public GetSensorCalibrationDelegate GetCalibrationAction { get; set; }`**
Implementation of `GetSensorCalibrationDelegate`; used to apply calibration to hardware channels.
- **`public delegate int GetDatabaseIdDelegate(IDASCommunication das);`**
Delegate to map a DAS unit to its database ID.
- **`public GetDatabaseIdDelegate GetDatabaseIdAction { get; set; }`**
Implementation of `GetDatabaseIdDelegate`; used to correlate hardware units with database records.
- **`public delegate void SetSensorCalibrationDelegate(ISensorData sd, ISensorCalibration sc);`**
Delegate to persist calibration data back to the sensor.
- **`public SetSensorCalibrationDelegate SetSensorCalibrationAction { get; set; }`**
Implementation of `SetSensorCalibrationDelegate`.
- **`public bool AllowSensorIdToBlankChannel { get; set; }`**
If `true`, allows assignment of a sensor with an EID to a channel that has no EID (blank channel).
- **`public bool TurnOffExcitation { get; set; } = false;`**
Flag indicating that excitation should be turned off *before* applying configuration. Reverted upon starting the turn-off process.
- **`public IDASCommunication[] UnitsToConfigure { get; set; } = new IDASCommunication[0];`**
Array of DAS units to be configured.
- **`public bool DoStrictCheck { get; set; } = true;`**
If `true`, perform strict validation of configuration (e.g., hardware compatibility, EID match).
- **`public bool EventConfig { get; set; } = true;`**
If `true`, write configuration to the *event* file store (legacy SLICE feature); otherwise, use the *diagnostic* store.
- **`public bool DummyConfig { get; set; } = false;`**
If `true`, perform configuration for dummy (non-data-collecting) mode.
- **`public double[] MaxAAF { get; set; } = new double[0];`**
Array of maximum Anti-Alias Filter (AAF) rates per unit (used for SLICE/TDAS).
- **`public bool ConfigureDigitalOutputs { get; set; } = true;`**
If `true`, configure digital outputs; set to `false` to skip (e.g., for trigger checks).
- **`public ErrorCallback ErrorRequiringActionAction { get; set; }`**
Callback invoked when user interaction is required (e.g., AAF errors).
- **`public bool TurnOffAAFRealtime { get; set; } = true;`**
If `true`, disable AAF for real-time acquisition to reduce latency.
- **`public bool ResetHardwareEventLines { get; set; } = false;`**
If `true`, reset hardware event lines before applying configuration.
- **`public bool PrepareForDiagnostics { get; set; } = false;`**
If `true`, prepare units for diagnostics (e.g., turn on excitation, switches) after configuration.
- **`public IReadOnlyDictionary<string, double> SampleRateLookup { get; set; } = new Dictionary<string, double>();`**
Lookup table mapping unit serial numbers to data collection sample rates.
- **`public IReadOnlyDictionary<string, float> AAFRateLookup { get; set; } = new Dictionary<string, float>();`**
Lookup table mapping unit serial numbers to AAF rates.
- **`public bool SkipTurnOnPower { get; set; } = false;`**
If `true`, skip powering up units after configuration (e.g., to keep units in low-power state).
- **`public bool SetConfiguration { get; set; } = true;`**
If `true`, actually write configuration to hardware; if `false`, only prepare for diagnostics.
- **`public DSPFilterType DSPFilterType { get; set; }`**
DSP filter type to apply during configuration.
- **`public bool DiscardDiagnostics { get; set; } = true;`**
If `true`, discard existing diagnostic data before applying new configuration.
- **`public ConfigureStatusParameters()`**
Constructor; initializes `DSPFilterType` via `ResetDSPFilterType()`.
- **`public void Reset()`**
Resets all properties to their default values.
- **`public override string ToString()`**
Returns a human-readable string representation of all configuration parameters.
---
#### `ConfigureStatusInformation`
- **`public enum StatusValues { ... }`**
Enum of possible status notifications (e.g., `ApplyingConfiguration`, `Completed`, `ChannelOutOfPosition`, `EIDNotFound`, `LowPowerSuccess`, etc.).
- **`public bool NoChannelsAssigned { get; internal set; } = true;`**
`true` if no channels have been assigned yet.
- **`public bool AllChannelsResolved { get; internal set; } = false;`**
`true` if all channels requiring resolution have been successfully resolved.
- **`public bool ChannelsOutOfPosition { get; internal set; } = false;`**
`true` if one or more sensors are assigned to channels other than their specified position.
- **`public bool HaveAppliedConfigAllUnits { get; set; } = false;`**
`true` if all units in `UnitsToConfigure` were successfully configured.
- **`public ManualResetEvent CancelEvent { get; }`**
Signaled to request cancellation of ongoing tasks.
- **`public ManualResetEvent DoneEvent { get; }`**
Signaled when all work (configuration, power, diagnostics) is complete.
- **`public ActionCompleteDelegate CompleteAction { get; set; }`**
Callback invoked on completion of the configuration process.
- **`public SetProgressValueDelegate ProgressAction { get; set; }`**
Callback invoked with progress updates (0100).
- **`public StatusIntDelegate StatusAction { get; set; }`**
Callback invoked with `StatusValues` enum values.
- **`public StatusExIntDelegate StatusExAction { get; set; }`**
Callback invoked with extended status (e.g., per-unit success/failure).
- **`public IDASCommunication[] UnitsConfigured { get; set; } = new IDASCommunication[0];`**
List of units successfully configured.
- **`public async Task Cancel()`**
Initiates cancellation: sets `CancelEvent`, waits for completion, and reports `Cancelling`/`Cancelled` status.
- **`public void TurnOffExcitation()`**
Asynchronously turns off excitation on all units, updates global `ExcitationOn` status, and signals `LowPowerSuccess`/`LowPowerFailure`.
- **`public void ApplyConfig()`**
Starts asynchronous configuration process:
- If `TurnOffExcitation` is set, invokes `TurnOffExcitation()` first.
- Otherwise, applies configuration via `ConfigurationService.SetConfiguration(...)`.
- If `PrepareForDiagnostics` is set and `SkipTurnOnPower` is `false`, calls `PrepareForDiagnostics()`.
- **`public void ManuallyResolveChannel(IGroupChannel channel, IDASChannel hardwareChannel)`**
Manually assigns a hardware channel to a group channel. Validates:
- Channel is not blank/disabled.
- Sensor exists and is compatible.
- Hardware channel is not already assigned.
- EID constraints (if sensor has EID, and `AllowSensorIdToBlankChannel` is `false`, EID must match).
Throws `InvalidAssignmentException` on failure.
- **`public void ManuallyUnresolveChannel(IGroupChannel channel)`**
Removes manual assignment of a channel. Fails if channel is not resolved or if assignment was EID-locked.
Throws `InvalidAssignmentException`.
- **`public class InvalidAssignmentException : Exception`**
Exception thrown on manual assignment errors.
- **`Reasons` enum**: `BlankChannel`, `NoSensor`, `ChannelDisabled`, `SensorNotFound`, `IncompatibleHardware`, `ChannelAlreadyAssigned`, `EID_Locked`, `EIDRequiredAndMissing`, `ChannelNotAssigned`.
- Contains `GroupChannel` and `Reason`.
- **`public void Reset()`**
Resets all status flags, clears channel resolution lists, and nullifies delegates.
---
#### `GroupChannelWithMeta` *(internal helper)*
- **`public bool ChannelConflict { get; set; }`**
`true` if this channel conflicts with another assignment.
- **`public IGroupChannel ConflictingChannel { get; set; }`**
Reference to the conflicting channel (if any).
- **`public IGroupChannel Channel { get; set; }`**
The group channel being described.
- **`public IGroup Group { get; set; }`**
The group containing the channel.
- **`public bool MissingID { get; set; }`**
`true` if sensor EID is missing (but expected).
- **`public bool MissingSensor { get; set; }`**
`true` if no sensor is associated with the channel.
- **`public bool EIDOutOfPlace { get; set; }`**
`true` if the sensors EID is present but assigned to a different channel than expected.
- **`public bool HWNotFound { get; set; }`**
`true` if the hardware channel could not be found.
- **`public bool HWChannelIncompatible { get; set; }`**
`true` if the hardware channel is incompatible with the sensor.
- **`public IDASChannel DASChannel { get; set; }`**
The resolved hardware channel (if any).
- **`public bool AssignedByEID { get; set; }`**
`true` if this channel was auto-resolved via EID matching.
---
### 3. **Invariants**
- **Channel Resolution State**:
A channel is *either* in `_resolvedChannels` *or* `_unresolvedChannels`, never both.
`IsResolved(ch)` and `IsUnresolved(ch)` are mutually exclusive.
- **Hardware Channel Uniqueness**:
A hardware channel (`IDASChannel`) may be assigned to *only one* group channel at a time. Enforced in `AddResolvedChannel` and `ManuallyResolveChannel`.
- **EID Locking**:
If a channel is resolved via EID (`AssignedByEID == true`), it cannot be manually reassigned to a different hardware channel (`EID_Locked` exception).
- **Sensor Compatibility**:
`IsSensorHwCompatible` enforces strict compatibility rules:
- Bridge mode must match.
- Digital input mode must match (if applicable).
- Supported excitation must exist *and* have calibration data.
- Squib/Digital Output sensors must match their respective hardware types.
- **Configuration Atomicity**:
`ApplyConfig` only proceeds to `PrepareForDiagnostics` if no cancellation occurred (`!CancelEvent.WaitOne(...)`).
- **Excitation State Consistency**:
Global `ExcitationOn` status is updated only after successful `TurnOffExcitation` or `PrepareForDiagnostics`.
- `TurnOffExcitation` → sets `ExcitationOn = false` on success.
- `PrepareForDiagnostics` → sets `ExcitationOn = true` on success.
---
### 4. **Dependencies**
#### **Imports / Dependencies Used**
- **`DTS.Common.Interface.*`**:
- `Channels` (`IGroupChannel`, `IDASChannel`, `AnalogInputDASChannel`, etc.)
- `DASFactory` (`IDASCommunication`, `IDASFactory`)
- `Sensors` (`ISensorData`, `ISensorCalibration`)
- `StatusAndProgressBar` (`IStatusInfo`, `IStatusParameters`, delegates)
- `Groups.GroupList` (`IGroup`)
- `TestSetups.TestSetupsList` (`ITestSetup`)
- **`DTS.Common.Classes.DSP`**: `DSPFilterCollection`, `DSPFilterType`
- **`DTS.Common.Enums`**: `ExcitationVoltageOptions`
- **`DTS.DASLib.Service.StateMachine.StatusAndParameters.Configure`**: `GroupChannelWithMeta`
- **`DTS.DASLib.Service.StateMachine`**: `States.Instance.ConfigureStart.Status.*`, `ConfigurationService`, `DiagnosticsService`, `ArmingService`
- **`System.Threading.Tasks`**: `Task`, `Task.Run`
- **`System.Collections.Generic`**, **`System.Linq`**, **`System.Text`**, **`System.Threading`**, **`System`**
#### **Consumers / Usage**
- **`ConfigureStatusParameters`** is used by:
- `ConfigurationService.SetConfiguration(...)` (to receive configuration intent)
- UI or test harness to configure behavior before invoking `ApplyConfig()`
- **`ConfigureStatusInformation`** is used by:
- `ConfigurationService.SetConfiguration(...)` (to report progress/status)
- `DiagnosticsService.PrepareForDiagnostics(...)`
- `ArmingService.EnterLowPowerMode(...)`
- UI to monitor and control configuration state (via delegates)
- **`GroupChannelWithMeta`** is used internally by `ConfigureStatusInformation` to track channel resolution state.
---
### 5. **Gotchas**
- **`AllChannelsResolved` Logic Inversion**:
`AllChannelsResolved` is set to `true` when `_unresolvedChannels.Any()` is `false` (i.e., *no unresolved channels*), but the property name suggests it should be `true` when *all are resolved*. This is counterintuitive and could cause bugs if misread.
- **`TurnOffExcitation` Flag Reset Timing**:
`param.TurnOffExcitation` is reset to `false` *inside* `TurnOffExcitation()` *before* the task completes. If `ApplyConfig()` is called again before `TurnOffExcitation()` finishes, it may skip re-initiating turn-off.
- **`UnitsToConfigure` Mutability During `ApplyConfig`**:
In `ApplyConfig()`, if a unit in `UnitsToConfigure` is not found in `dasFactory.GetDASList()`, it is *removed from the local list* (`unitsToConfigure`) but *not from the original `param.UnitsToConfigure`*. This can cause `HaveAppliedConfigAllUnits` to be `false` even though no error was reported for that unit.
- **`PrepareForDiagnostics` Spin-Wait**:
`PrepareForDiagnostics()` uses a fixed spin-wait loop (`PREPARE_SPIN_TIME = 200`, `EXPECTED_PREPARE_TIME = 8000`) instead of relying solely on `ManualResetEvent`. Progress is updated manually, but this is inefficient and not cancellation-aware.
- **`InvalidAssignmentException` Message Format**:
The exception message includes the `Reason` enum *and* the channels `ToString()` representation. If `IGroupChannel.ToString()` is not informative, debugging may be difficult.
- **`AllowSensorIdToBlankChannel` Default**:
Default is `false`, meaning sensors with EIDs *cannot* be assigned to blank channels unless explicitly allowed. This may be unexpected in test scenarios.
- **`ResetDSPFilterType()` Uses Empty String**:
`ResetDSPFilterType()` calls `GetFilter(string.Empty)`. If the filter collection does not define a default for empty string, this may return an unexpected or null filter.
- **Thread Safety of `UnitsConfigured`**:
`AddConfiguredDevice()` uses `lock(MyLock)` to safely append to `UnitsConfigured`, but `UnitsConfigured` is exposed as a public property. External code could modify the array directly, bypassing the lock.
- **`PrepareForDiagnostics` Fails if `UnitsConfigured` is Empty**:
`PrepareForDiagnostics()` checks `!status.UnitsConfigured.Any()` and fails early. However, `UnitsConfigured` is only populated *during* `ApplyConfig()`. If `PrepareForDiagnostics` is called independently (e.g., in diagnostics-only flow), it will always fail.
- **No Handling of `GetCalibrationAction` Returning `null`**:
In `AddResolvedChannel`, if `GetCalibrationAction` returns `null` for all supported excitations, no calibration is applied, but no error is raised. This may silently leave hardware uncalibrated.
- **`EIDOutOfPlace` Flag Misleading**:
`EIDOutOfPlace` is set only in `AddResolvedChannel`, but never set to `true` in `AddUnresolvedChannel`. It is unclear how out-of-position channels are tracked if they are unresolved.