170 lines
9.6 KiB
Markdown
170 lines
9.6 KiB
Markdown
---
|
||
source_files:
|
||
- DataPRO/TDASCommands/TestTriggerCommands.cs
|
||
- DataPRO/TDASCommands/CommandBase.cs
|
||
- DataPRO/TDASCommands/TDASCommandPacketBase.cs
|
||
generated_at: "2026-04-16T03:47:17.202169+00:00"
|
||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||
schema_version: 1
|
||
sha256: "095345d9b2c6bf7d"
|
||
---
|
||
|
||
# TDASCommands
|
||
|
||
**Documentation: TDAS Test Trigger Commands Module**
|
||
|
||
---
|
||
|
||
### 1. Purpose
|
||
|
||
This module implements command classes for interacting with TDAS hardware modules to perform test trigger operations—specifically, arming, querying status, and disabling the trigger. It provides two public command types: `TestTrigger` (single-module, unicast) and `TestTriggerBroadcast` (single-module broadcast, unicast to a specific module index). These commands construct and send ASCII-based protocol commands (`TESTTRIG` or `*<N>TESTTRIG`) to TDAS devices and parse the ASCII response to extract the trigger status (`ARMED` or `OFF`). The module relies on the shared `CommandBase` and `TDASCommandPacketBase` infrastructure for communication, sequencing, and response handling.
|
||
|
||
---
|
||
|
||
### 2. Public Interface
|
||
|
||
#### `TestTrigger` class
|
||
*Public, concrete command class for single-module test trigger operations.*
|
||
|
||
- **`int ModuleIndex`**
|
||
Gets or sets the module index (0–9). Setting it enforces `<10` and disables `RackCommand`.
|
||
|
||
- **`SubCommandValues SubCommand`**
|
||
Gets/sets the subcommand to send: `ARM`, `STATUS`, or `OFF`.
|
||
- *Getter* parses `_CommandString.SubCommand` as `SubCommandValues`.
|
||
- *Setter* writes the enum value as a string into `_CommandString.SubCommand`.
|
||
|
||
- **`StatusValues TriggerStatus`**
|
||
Gets the parsed trigger status from the last response: `ARMED` or `OFF`.
|
||
- *Getter* parses `_CommandString.Status` as `StatusValues`.
|
||
- Value is populated during `ProcessData()`.
|
||
|
||
- **`TestTrigger(ICommunication sock)`**
|
||
Constructor with default 30s timeout. Initializes `TDASCommandPacketBase` with `TestTriggerCommandString`, sets `RebuildBytes = true`, `RackCommand = false`, and default `SubCommand = STATUS`.
|
||
|
||
- **`TestTrigger(ICommunication sock, int msTimeout)`**
|
||
Constructor with configurable timeout. Same initialization as above, but uses provided timeout.
|
||
|
||
#### `TestTriggerBroadcast` class
|
||
*Public, concrete command class for broadcast test trigger to a specific module.*
|
||
|
||
- **`SubCommandValues SubCommand`**
|
||
Same semantics as `TestTrigger.SubCommand`, operating on `_CommandString.SubCommand` of the underlying `TestTriggerBroadcastCommandString`.
|
||
|
||
- **`TestTriggerBroadcast(ICommunication sock, int moduleIndex)`**
|
||
Constructor with default timeout. Initializes `TDASCommandPacketBase` with `TestTriggerBroadcastCommandString(moduleIndex)`, sets `RackCommand = false`, `RebuildBytes = true`, and default `SubCommand = STATUS`.
|
||
|
||
- **`TestTriggerBroadcast(ICommunication sock, int moduleIndex, int msTimeout)`**
|
||
Constructor with configurable timeout. Same initialization as above.
|
||
|
||
#### Internal helper classes (not part of public API, but referenced for completeness)
|
||
|
||
- **`TestTriggerCommandString`**
|
||
*Internal* subclass of `CommandString`.
|
||
- `_CommandString => "TESTTRIG"`
|
||
- `_CommandDescription => "Test trigger"`
|
||
- `SubCommand` and `Status` properties (string) store subcommand and response status.
|
||
- `GetParameters()` returns `" <SubCommand>"` as ASCII bytes.
|
||
|
||
- **`TestTriggerBroadcastCommandString`**
|
||
*Internal* subclass of `CommandString`.
|
||
- `_CommandString => "*<N>TESTTRIG"` (if `ModuleIndex >= 0`) or `"*TESTTRIG"` otherwise.
|
||
- `_CommandDescription` mirrors `_CommandString`.
|
||
- `ModuleIndex`, `SubCommand` properties.
|
||
- Constructor accepts `moduleIndex`.
|
||
- `GetParameters()` same as `TestTriggerCommandString`.
|
||
|
||
---
|
||
|
||
### 3. Invariants
|
||
|
||
- **ModuleIndex constraint**:
|
||
`ModuleIndex` must be `<10` (enforced in `TDASCommandPacketBase.ModuleIndex` setter). Setting it to `>=10` throws an exception.
|
||
|
||
- **RackCommand mutual exclusion**:
|
||
Setting `ModuleIndex` in `TDASCommandPacketBase` sets `RackCommand = false`. `RackCommand` is only `true` when `ModuleIndex` is unset (default `' '` space) and not explicitly set to a digit.
|
||
|
||
- **Default subcommand**:
|
||
All constructors initialize `_CommandString.SubCommand = "STATUS"`.
|
||
|
||
- **Response parsing invariant**:
|
||
`ProcessData()` in `TestTrigger` parses the response into tokens; status is assigned from `tokens[1]` if `tokens.Length >= 2`. If parsing fails, `_CommandString.Status` remains unchanged.
|
||
|
||
- **Response format assumption**:
|
||
TDAS responses are ASCII, newline-terminated (`\r\n`), and contain the command string followed by a space and status (e.g., `TESTTRIG ARMED\r\n`). Parsing assumes this format.
|
||
|
||
- **`RebuildBytes = true`**:
|
||
All `TestTrigger*` constructors set `RebuildBytes = true`, ensuring `CommandString.GetBytes()` regenerates the byte array on each `ToBytes()` call (critical for dynamic `SubCommand` changes).
|
||
|
||
---
|
||
|
||
### 4. Dependencies
|
||
|
||
#### Imports / References (from source):
|
||
- `DTS.Common.ICommunication` → `ICommunication` interface for socket communication.
|
||
- `DTS.DASLib.Command.TDAS` namespace:
|
||
- `CommandBase` (base class for all commands, provides `ProcessData`, `ResponseData`, `SyncExecute`, throttling).
|
||
- `TDASCommandPacketBase` (packet construction, verification, MDB mode support).
|
||
- `CommandString` (abstract base for command strings).
|
||
- `System.Text.Encoding` (ASCII encoding/decoding).
|
||
- `System.Threading` (used in `CommandBase` for `SemaphoreSlim` throttling).
|
||
|
||
#### Inferred callers:
|
||
- Likely instantiated by higher-level test or configuration logic (e.g., test harnesses, calibration tools).
|
||
- Uses `CommandBase` infrastructure, so depends on:
|
||
- `APILogger` (for logging errors and command/response).
|
||
- Throttling via `CommandBase.InitializeSemaphore()` (default: 3 concurrent operations, 100ms delay).
|
||
|
||
#### Dependencies on other modules:
|
||
- `TDASCommandPacketBase` → depends on `MDB_BLOCK` (for data mode parsing), `CommandPacketBase` (base), and `CommandString`.
|
||
- `CommandBase` → depends on logging infrastructure (`TextLogger`, `APILogger`), threading (`SemaphoreSlim`), and `AbstractCommandBase`.
|
||
|
||
---
|
||
|
||
### 5. Gotchas
|
||
|
||
- **`ModuleIndex` parsing is fragile**:
|
||
`ModuleIndex` getter in `TDASCommandPacketBase` uses `int.Parse(new string(_moduleIndex, 1))`. If `_moduleIndex` is `' '` (space), this throws `FormatException`. This is avoided in `TestTrigger` constructors because `ModuleIndex` is never explicitly set, but if used directly, it may fail.
|
||
|
||
- **`TriggerStatus` may be stale or empty**:
|
||
`TriggerStatus` reads `_CommandString.Status`, which is only updated in `ProcessData()`. If `ResponseData` is accessed before `ProcessData()` runs (e.g., via `ResponseData` getter), `ProcessData()` executes—but if the response is malformed or missing, `_CommandString.Status` may remain `null` or unchanged, causing `Enum.Parse` to throw.
|
||
|
||
- **`ProcessData()` in `TestTrigger` is custom and narrow**:
|
||
Unlike `CommandBase.ProcessData()`, `TestTrigger.ProcessData()` manually parses the response using `GetCommandPortion()` and `ResponseData.Split`. It assumes the response contains the command string followed by a space and status. Deviations (e.g., extra whitespace, different order) may cause parsing failure.
|
||
|
||
- **No validation of `SubCommand` enum values in setter**:
|
||
`SubCommand` setter directly assigns `value.ToString()` to `_CommandString.SubCommand`. If an invalid enum value is passed (e.g., via reflection or cast), no validation occurs—though `Enum.Parse` in getter may throw.
|
||
|
||
- **`TestTriggerBroadcastCommandString.ModuleIndex` is not validated**:
|
||
The broadcast command accepts any `moduleIndex`, but the command string uses `*<N>TESTTRIG`. If `moduleIndex < 0`, it falls back to `*TESTTRIG` (broadcast to all modules). This may be unintended.
|
||
|
||
- **Throttling is global and static**:
|
||
`CommandBase` uses static `_pool` and `_semaphoreDelay`. If `InitializeSemaphore()` is not called, defaults (`spots=3`, `delay=100ms`) apply. This affects all `TestTrigger`/`TestTriggerBroadcast` instances.
|
||
|
||
- **`RebuildBytes` must be `true` for dynamic updates**:
|
||
If `RebuildBytes` is accidentally set to `false`, changing `SubCommand` will not affect the outgoing command bytes until `RebuildBytes = true` or `cs.RebuildBytes()` is called.
|
||
|
||
- **No error handling in `ProcessData()` for malformed responses**:
|
||
If `ResponseData` does not contain the expected format (e.g., missing `\r\n`, insufficient tokens), `ProcessData()` silently returns without updating `_CommandString.Status`. This may lead to stale status values.
|
||
|
||
- **`GetParameters()` returns a leading space**:
|
||
Both `TestTriggerCommandString` and `TestTriggerBroadcastCommandString` return `" <SubCommand>"` (note leading space). This matches TDAS protocol expectations but is non-obvious.
|
||
|
||
- **`ModuleIndex` setter in `TDASCommandPacketBase` throws on `>=10`**:
|
||
This is a hard constraint. If future hardware supports >10 modules, this will break.
|
||
|
||
- **`ExpectsData = true` by default in `CommandString`**:
|
||
`TestTrigger`/`TestTriggerBroadcast` do not override this, so `ExpectsData = true`. If the TDAS response for `TESTTRIG` is status-only (no data), `VerifyPacket()` may behave unexpectedly (see `TDASCommandPacketBase.VerifyPacket()` logic).
|
||
|
||
- **`ToCommandString()` strips control characters**:
|
||
`ToCommandString()` removes `\r\n` and `\0`, which may obscure debugging if raw bytes are needed.
|
||
|
||
- **`CommandBase.ProcessData()` may throw**:
|
||
If `ResponseData` contains `"ERR"`, `ProcessData()` throws `InvalidOperationException`. This is caught only if the caller handles it.
|
||
|
||
- **`TestTriggerBroadcast` does not expose `ModuleIndex`**:
|
||
The `moduleIndex` is stored in the internal `TestTriggerBroadcastCommandString`, but not exposed as a property. Callers must track it externally.
|
||
|
||
---
|
||
|
||
*End of documentation.* |