412 lines
16 KiB
Markdown
412 lines
16 KiB
Markdown
---
|
|
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. |