Files
DP44/enriched-qwen3-coder-next/DataPRO/RibeyeCommands.md

412 lines
16 KiB
Markdown
Raw Normal View History

2026-04-17 14:55:32 -04:00
---
source_files:
- DataPRO/RibeyeCommands/CommandBase.cs
- DataPRO/RibeyeCommands/CalibrationCommands.cs
- DataPRO/RibeyeCommands/InformationCommands.cs
- DataPRO/RibeyeCommands/CommandPacket.cs
- DataPRO/RibeyeCommands/ArmCommands.cs
generated_at: "2026-04-16T03:49:10.362478+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "fc23195a4e943669"
---
# Ribeye Command Library Documentation
## 1. Purpose
This module provides a structured command abstraction layer for interacting with the **Ribeye** data acquisition system hardware. It implements concrete command classes for diagnostics, information retrieval, and arm/trigger control, built atop a common base (`CommandBase`) that handles low-level packet serialization, deserialization, and communication via the `ICommunication` interface. The library enables developers to issue structured commands (e.g., query serial number, arm device, retrieve current positions) and retrieve structured results, abstracting away the underlying ASCII-based protocol with `#`-delimited parameters and checksums.
## 2. Public Interface
### `CommandBase` (abstract class)
- **Namespace**: `DTS.DASLib.Command.Ribeye`
- **Inherits**: `AbstractCommandBase`
- **Purpose**: Base class for all Ribeye commands; manages `CommandPacket` for command/response and provides string conversion utilities.
#### Constructors
- `CommandBase(ICommunication sock)`
Initializes a new command instance with default timeout, creates a new `CommandPacket` for `command`.
- `CommandBase(ICommunication sock, int TimeoutMillisec)`
Initializes with explicit timeout, creates a new `CommandPacket` for `command`.
#### Overridden Methods
- `void CommandToString(ref List<List<string>> lines)`
Appends the ASCII representation of `command.OriginalBytes` (excluding `\r`/`\n`) to `lines`.
- `void ResponseToString(ref List<List<string>> lines)`
Appends up to the first 30 ASCII characters of `response.OriginalBytes` (excluding `\r`/`\n`) to `lines`, or `"Empty response!"` if null.
- `CommandPacketBase GetCommandPacket()`
Returns a new empty `CommandPacket`.
- `CommandPacketBase GetCommandPacket(byte[] buffer)`
Returns a new `CommandPacket` initialized from `buffer`.
---
### `DiagnosticsCommands` (abstract class)
- **Namespace**: `DTS.DASLib.Command.Ribeye`
- **Inherits**: `CommandBase`
- **Purpose**: Base class for diagnostics commands; sets `command.Type = CommandType.Diagnostics`.
#### Constructors
- `DiagnosticsCommands(ICommunication sock)`
- `DiagnosticsCommands(ICommunication sock, int TimeoutMillisec)`
Both set `command.Type = CommandType.Diagnostics` and call `command.SetCommand((byte)_Command, _Command.ToString())`.
#### Protected Members
- `abstract Commands _Command { get; }`
Must be implemented by derived classes to specify the command byte and name.
---
### `QueryCurrentPositions` (concrete class)
- **Inherits**: `DiagnosticsCommands`
- **Purpose**: Queries current deflection positions (in mV) for all stack channels.
#### Constructors
- `QueryCurrentPositions(ICommunication sock)`
- `QueryCurrentPositions(ICommunication sock, int TimeoutMillisec)`
Initializes `command.Parameter[0] = "CURRENT_POSITIONS"`.
#### Properties
- `int NumberOfChannels { get; }`
Number of stack channels returned in `Positions`.
- `float[] Positions { get; }`
Array of deflection values (mV) per channel.
#### Overridden Methods
- `CommandReceiveAction WholePackage()`
Parses response:
- `response.GetParameter(1, out int NumberOfPositions)` → sets `_numChannels`.
- `response.GetParameter(2, out string PositionString)` → splits by `,`, then handles firmware quirk where last element contains space-separated values.
- Parses each element as `float` into `_Positions`.
---
### `InformationCommands` (abstract class)
- **Namespace**: `DTS.DASLib.Command.Ribeye`
- **Inherits**: `CommandBase`
- **Purpose**: Base class for information queries; sets `command.Type = CommandType.Information`.
#### Constructors
- `InformationCommands(ICommunication sock)`
- `InformationCommands(ICommunication sock, int TimeoutMillisec)`
Both set `command.Type = CommandType.Information` and call `command.SetCommand((byte)_Command, _Command.ToString())`.
#### Protected Members
- `abstract Commands _Command { get; }`
Must be implemented by derived classes.
---
### `QuerySerialNumber` (concrete class)
- **Inherits**: `InformationCommands`
- **Purpose**: Queries device serial number.
#### Constructors
- `QuerySerialNumber(ICommunication sock)`
- `QuerySerialNumber(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "SERIAL_NUMBER"`.
#### Properties
- `string SerialNumber { get; }`
Serial number string from `response.Parameter[1]`.
#### Overridden Methods
- `CommandReceiveAction WholePackage()`
On success, extracts serial number via `response.GetParameter(1, out _serialnumber)`; silently ignores exceptions.
---
### `QueryNumberOfLEDs` (concrete class)
- **Inherits**: `InformationCommands`
- **Purpose**: Queries number of LEDs on device.
#### Constructors
- `QueryNumberOfLEDs(ICommunication sock)`
- `QueryNumberOfLEDs(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "HOW_MANY_LEDS"`.
#### Properties
- `uint NumberOfLEDs { get; }`
LED count from `response.Parameter[1]`.
#### Overridden Methods
- `CommandReceiveAction WholePackage()`
On success, extracts LED count via `response.GetParameter(1, out _numberOfLEDs)`.
- `void ResponseToString(ref List<List<string>> lines)`
Appends `"NumberOfLEDs: {value}"` to `lines`.
---
### `QueryDataAvailable` (concrete class)
- **Inherits**: `InformationCommands`
- **Purpose**: Queries data collection timing parameters (note: uses `Commands.QueryNumberOfLEDs` command enum, but `"DUMPINFO"` parameter).
#### Constructors
- `QueryDataAvailable(ICommunication sock)`
- `QueryDataAvailable(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "DUMPINFO"`.
#### Properties
- `float TotalMS { get; }`
Sum of `PreTriggerMS` and `PostTriggerMS`.
- `float PreTriggerMS { get; }`
Absolute value of negative pre-trigger time (ms).
- `float PostTriggerMS { get; }`
Post-trigger time (ms).
#### Overridden Methods
- `CommandReceiveAction WholePackage()`
On success:
- `response.GetParameter(1, out int NegativePreTriggerMS)``_preTriggerMS = Math.Abs(NegativePreTriggerMS)`
- `response.GetParameter(2, out _postTriggerMS)`
- `_totalMS = _preTriggerMS + _postTriggerMS`
---
### `ArmCommands` (abstract class)
- **Namespace**: `DTS.DASLib.Command.Ribeye`
- **Inherits**: `CommandBase`
- **Purpose**: Base class for arm/trigger commands; sets `command.Type = CommandType.Arm`.
#### Constructors
- `ArmCommands(ICommunication sock)`
- `ArmCommands(ICommunication sock, int TimeoutMillisec)`
Both set `command.Type = CommandType.Arm` and call `command.SetCommand((byte)_Command, _Command.ToString())`.
#### Protected Members
- `abstract Commands _Command { get; }`
---
### `Arm` (concrete class)
- **Inherits**: `ArmCommands`
- **Purpose**: Arms the device for data collection.
#### Constructors
- `Arm(ICommunication sock)`
- `Arm(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "ARM"`.
#### Properties (setters)
- `uint TStopMS { set; }`
Sets `command.Parameter[1]`.
- `uint TPostMS { set; }`
Sets `command.Parameter[2]`.
---
### `QueryArmAndTriggerStatus` (concrete class)
- **Inherits**: `ArmCommands`
- **Purpose**: Queries current arm/trigger status.
#### Constructors
- `QueryArmAndTriggerStatus(ICommunication sock)`
- `QueryArmAndTriggerStatus(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "S"`.
#### Properties
- `bool IsArmed { get; set; }`
- `bool IsRecording { get; set; }`
- `bool IsTriggered { get; set; }`
#### Overridden Methods
- `CommandReceiveAction WholePackage()`
Parses `response.Parameter[1]` as `int StatusCode`. Maps via `StatusCodeEnum`:
- `Idle` → all `false`
- `Armed``IsArmed = IsRecording = true`
- `Busy` → all `true`
- `DataAvailable`/default → all `false`
---
### `Disarm` (concrete class)
- **Inherits**: `ArmCommands`
- **Purpose**: Disarms the device.
#### Constructors
- `Disarm(ICommunication sock)`
- `Disarm(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "D"`.
---
### `PrepareForDataCollection` (concrete class)
- **Inherits**: `ArmCommands`
- **Purpose**: Prepares device for data collection (e.g., erases buffer).
#### Constructors
- `PrepareForDataCollection(ICommunication sock)`
- `PrepareForDataCollection(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "ERASE"`.
---
### `DownloadTestData` (concrete class)
- **Inherits**: `ArmCommands`
- **Purpose**: Downloads test data (note: uses `Commands.QueryArmAndTriggerStatus` enum, but `"DUMPBIN"` parameter).
#### Constructors
- `DownloadTestData(ICommunication sock)`
- `DownloadTestData(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "DUMPBIN"`.
#### Properties
- `ushort[] Data { get; }`
Raw unsigned 16-bit sample data.
- `int StartTimeMS { set; }`
Sets `command.Parameter[1]`.
- `int StopTimeMS { set; }`
Sets `command.Parameter[2]`.
- `uint NumberOfChannels { get; }`
Extracted from `response.Parameter[1]`.
- `int ExpectedNumberOfSamples { get; }`
Extracted from `response.Parameter[2]`.
#### Methods
- `void GetChannelData(int channel, out short[] signedADC)`
Converts `ushort[] _Data` to signed `short[]` per channel (interleaved → deinterleaved). Throws if `channel` out of range.
#### Overridden Methods
- `CommandReceiveAction WholePackage()`
Parses `response.Parameter[1]` (channels), `[2]` (samples), then converts `DownloadPacket.Data` to `_Data` (16-bit unsigned, little-endian with per-sample checksum byte).
- `CommandReceiveAction ReceiveBlockOK(ICommunicationReport report)`
Custom handling for `DownloadPacket` verification and parsing.
- `CommandReceiveAction WholePackagePost()`
Builds `QueryEventDataReport` with `short[][]` data.
---
### `Trigger` (concrete class)
- **Inherits**: `ArmCommands`
- **Purpose**: Manually triggers data acquisition.
#### Constructors
- `Trigger(ICommunication sock)`
- `Trigger(ICommunication sock, int TimeoutMillisec)`
Sets `command.Parameter[0] = "T"`.
---
### `CommandPacket` (concrete class)
- **Namespace**: `DTS.DASLib.Command.Ribeye`
- **Inherits**: `CommandPacketBase`
- **Purpose**: Represents a command/response packet in the Ribeye protocol.
#### Nested Types
- `enum CommandType { Reserved, Arm, Attribute, Diagnostics, EventData, FirmwareUpdate, Information, QAandUtility, Realtime }`
- `enum PacketState { Unknown, TooShort, OK }`
#### Fields
- `string[] Parameter`
Array of `#`-delimited parameters.
- `byte Checksum`
Computed checksum over parameters.
#### Constructors
- `CommandPacket()`
Initializes `Parameter = new string[0]`, `ShouldLog = true`.
- `CommandPacket(byte[] Bytes)`
Parses ASCII packet: splits on `#`, ignores `\r`/`\n`.
#### Methods
- `PacketState VerifyPacket(byte[] Bytes)`
Returns `PacketState.OK` if `Bytes.Length >= 4`, ends with `\r\n`, and not error indicator (`?`).
Returns `TooShort` if length < 4 or missing `\r\n`.
- `byte[] ToBytes()`
Serializes to ASCII: `param1#param2#...#checksum\r\n`.
- `void ComputeCRCs()`
Calls `ComputeChecksum()` (sum of all parameter bytes + `#`).
- `void GetParameter(int Position, out T Value)`
Parses `Parameter[Position]` as `T` (supports `double`, `float`, `int`, `string`, etc.).
- `void SetParameter(int Position, T Value)`
Sets `Parameter[Position] = value.ToString()`.
#### Static Members
- `void GetNextSequenceNumber()`
Thread-safe increment of global sequence number.
---
### `DownloadPacket` (concrete class)
- **Inherits**: `CommandPacket`
- **Purpose**: Specialized packet for binary data downloads.
#### Fields
- `byte[] Data`
Binary payload after header.
#### Constructors
- `DownloadPacket(byte[] Bytes)`
Parses header (up to `\r`), then copies remaining bytes to `Data`.
#### Static Methods
- `PacketState VerifyPacket(byte[] Bytes, ref uint BytesExpected)`
- If `BytesExpected == 0`: parses header (3 params), computes expected length:
`BytesExpected = (numChannels * 2 + 1) * numSamples + headerLength`.
- Returns `OK` if `Bytes.Length >= BytesExpected`, else `TooShort`.
---
## 3. Invariants
- **Packet Protocol**: All commands/responses use ASCII with `#` as parameter delimiter, terminated by `\r\n`. Checksum is computed over parameters only (sum of bytes).
- **Parameter Indexing**: `GetParameter`/`SetParameter` use 0-based indexing. Index `0` is always the command name (e.g., `"ARM"`, `"SERIAL_NUMBER"`).
- **Command Type**: Each command class sets `command.Type` to its category (`Diagnostics`, `Information`, `Arm`, etc.) in the constructor.
- **Response Parsing**: `WholePackage()` is only invoked after `response` is fully populated (via `VerifyPacket` and `DownloadPacket`/`CommandPacket` construction).
- **Checksum Verification**: `CommandPacket.VerifyPacket` does **not** validate checksum correctness—only checks for presence of `\r\n` terminator. Checksum is computed but not validated in `VerifyPacket`.
- **Thread Safety**: `GetNextSequenceNumber` uses a lock on `GlobalSequenceNumberLock`.
- **Data Conversion**: `DownloadTestData` interprets binary data as little-endian 16-bit samples with interleaved checksum bytes (per sample), but conversion logic appears flawed (`i / _NumberOfChannels` offset is suspicious).
---
## 4. Dependencies
### External Dependencies (from imports)
- `DTS.Common.ICommunication.ICommunication`
Interface for network/socket communication.
- `DTS.Common.Enums.DASFactory.DFConstantsAndEnums.CommandStatus`
Used for `response.Status` and `StatusNoError`.
- `DTS.Common.DASResource.Strings`
Used for localized error strings (e.g., `QueryEventData_GetChannelData_Err1`).
- `DTS.Common.Utilities.Logging.APILogger`
Used for logging failures in `WholePackagePost`.
- `DTS.DASLib.Command.CommandPacketBase`
Base class for `CommandPacket` (not shown, but assumed to define `SequenceNumber`, `Status`, `OriginalBytes`, etc.).
### Inherited Dependencies
- `AbstractCommandBase` (from `DTS.DASLib.Command`)
Provides core command execution logic, timeout handling, and `baseCommand`/`baseResponse`.
### Inherited By
- All Ribeye command classes (`QueryCurrentPositions`, `QuerySerialNumber`, `Arm`, etc.) depend on `CommandBase`.
- `DownloadTestData` depends on `DownloadPacket` for binary data handling.
---
## 5. Gotchas
- **Incorrect Command Enum Usage**:
- `QueryDataAvailable` sets `_Command = Commands.QueryNumberOfLEDs` (0x01) but uses `"DUMPINFO"` parameter.
- `DownloadTestData` sets `_Command = Commands.QueryArmAndTriggerStatus` (0x03) but uses `"DUMPBIN"` parameter.
This suggests historical copy-paste errors preserved intentionally.
- **Checksum Handling**:
`CommandPacket.VerifyPacket` does **not** validate checksum correctness—only checks for `\r\n` termination. Checksum is computed but never checked for validity.
- **Firmware Workaround**:
`QueryCurrentPositions.WholePackage()` contains a hack to split the last position value if it contains a space (e.g., `"1.23 4.56"` → two values). This masks a firmware bug.
- **Parameter Indexing**:
`QuerySerialNumber` and `QueryDataAvailable` use `Parameter[1]` for the first data value (not `Parameter[0]`), since `Parameter[0]` holds the command name. This is consistent but non-intuitive.
- **Data Conversion in `DownloadTestData`**:
The conversion loop for `_Data` has a suspicious offset:
`ByteArray[2 * i + i / _NumberOfChannels]`
This implies a variable-length checksum per channel, which contradicts the comment "per sample checksum". Likely incorrect.
- **Silent Error Handling**:
`QuerySerialNumber.WholePackage()` catches exceptions during `GetParameter` but only logs via `e.ToString()` (no actual logging). Errors may go unnoticed.
- **`DownloadTestData.Data` Type**:
Returns `ushort[]` but `GetChannelData` converts to `short[]`. Users must be aware of signed/unsigned mismatch.
- **`QueryArmAndTriggerStatus` Status Mapping**:
`DataAvailable` state maps to all flags `false`, which may be counterintuitive (data available but not armed/recording/triggered).
- **`QueryDataAvailable` Enum Mismatch**:
Uses `Commands.QueryNumberOfLEDs` enum value but `"DUMPINFO"` command string—likely a typo preserved for compatibility.
- **No Validation of Timeout**:
`TimeoutMillisec` is passed to base class, but no validation or sanity checks are present in constructors.