init
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/SLICECommands/DownloadCommands/QueryEventDataReport.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/ResetEventList.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/QueryTotalEventCount.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/EventDataCommands.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/StartDownloadStreamData.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/DownloadByteConverter.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/QueryEthernetEventInfo.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/QueryEthernetEventData.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/QueryUARTEventData.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/QueryUARTEventInfo.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/QueryEventDataBase.cs
|
||||
- DataPRO/SLICECommands/DownloadCommands/GetNextDownloadStreamDataSamples.cs
|
||||
generated_at: "2026-04-16T03:55:13.365793+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "cc8105887de8cbfa"
|
||||
---
|
||||
|
||||
# Documentation: SLICE Event Data Download Commands
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides a set of command classes for querying, downloading, and managing event data from SLICE2 firmware devices. It implements a family of commands for retrieving event metadata (e.g., `QueryTotalEventCount`, `QueryUARTEventInfo`, `QueryEthernetEventInfo`) and event payload data (e.g., `QueryEventData`, `QueryUARTEventData`, `QueryEthernetEventData`), as well as streaming download mechanisms (`StartDownloadStreamData`, `GetNextDownloadStreamDataSamples`). The module serves as the software-side counterpart to firmware event recording functionality, enabling structured retrieval of ADC samples, UART logs, and Ethernet recorder data via command/response protocol over an `ICommunication` interface.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Classes
|
||||
|
||||
#### `QueryEventDataReport`
|
||||
- **Purpose**: A report object returned via callback after executing event data download commands.
|
||||
- **Properties**:
|
||||
- `object CallbackObject { get; set; }` — User-provided callback data.
|
||||
- `CommandStatus Status { get; set; }` — Execution status of the command.
|
||||
- `short[][] Data { get; set; }` — Downloaded ADC data, organized as `[channel][sample]`. *Note: This property is declared but not currently assigned in any `WholePackagePost` implementation in the provided source.*
|
||||
- **Constructor**:
|
||||
- `QueryEventDataReport(CommandStatus status, object cbData)` — Initializes the report with status and callback data.
|
||||
|
||||
#### `ResetEventList`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Sends command to reset the event list on the device.
|
||||
- **Constructors**:
|
||||
- `ResetEventList(ICommunication sock)`
|
||||
- `ResetEventList(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
#### `QueryTotalEventCount`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Queries the total number of events stored on the device.
|
||||
- **Properties**:
|
||||
- `ushort Count { get; }` — Total event count returned by the device.
|
||||
- **Constructors**:
|
||||
- `QueryTotalEventCount(ICommunication sock)`
|
||||
- `QueryTotalEventCount(ICommunication sock, int timeoutMillisec)`
|
||||
- **Overrides**:
|
||||
- `protected override CommandReceiveAction WholePackage()` — Parses response to extract `Count`.
|
||||
- `public override void ResponseToString(ref List<List<string>> lines)` — Appends `"Count: {Count}"`.
|
||||
|
||||
#### `EventDataCommands`
|
||||
- **Abstract base class** for all event data commands.
|
||||
- **Protected Enum** `Commands` (values: `Reserved=0x00`, `ResetEventList=0x01`, `QueryTotalEventCount=0x02`, `QueryMatchingEvents=0x03`, `QueryEventData=0x04`, `SetEventData=0x05`, `StartDownloadStreamData=0x06`, `GetNextDownloadStreamDataSamples=0x07`, `QueryUartEventInfo=0x09`, `QueryUartEventData=0x0A`, `SetUartEventData=0x0B`, `GenerateEvent=0x0C`, `QueryEthernetEventInfo=0x0D`, `QueryEthernetEventData=0x0E`, `SetEthernetEventData=0x0F`)
|
||||
- **Abstract Property**:
|
||||
- `protected abstract Commands Command { get; }`
|
||||
- **Constructors**:
|
||||
- `EventDataCommands(ICommunication sock)`
|
||||
- `EventDataCommands(ICommunication sock, int timeoutMillisec)`
|
||||
- **Behavior**: Sets `command.Type = CommandPacket.CommandType.EventData` and calls `command.SetCommand((byte)Command, Command.ToString())`.
|
||||
|
||||
#### `StartDownloadStreamData`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Initiates streaming event data download mode on the device (requires firmware ≥ A1N4). Any subsequent command stops streaming.
|
||||
- **Constants**:
|
||||
- `public const byte AllChannels = 0xFF`
|
||||
- **Properties**:
|
||||
- `ushort EventNumber { get; set; }` — Event number to stream. Sets parameter at offset 0.
|
||||
- `virtual ulong FirstSample { get; set; }` — First sample to stream. Sets parameter at offset 2.
|
||||
- `virtual ulong LastSample { get; set; }` — Last sample to stream. Sets parameter at offset 10.
|
||||
- **Constructors**:
|
||||
- `StartDownloadStreamData(ICommunication sock)`
|
||||
- `StartDownloadStreamData(ICommunication sock, int timeoutMillisec)`
|
||||
- **Behavior**: Allocates `command.Parameter = new byte[18]`.
|
||||
|
||||
#### `DownloadByteConverter`
|
||||
- **Purpose**: Parses raw byte stream from streaming download packets (`GetNextDownloadStreamDataSamples`).
|
||||
- **Nested Enum** `DlByteIndex` (offsets into packet header):
|
||||
- `Sync=0`, `Type=1`, `Command=2`, `Status=3`, `Group=4`, `Id=5`, `Datalength=6`, `SequenceNumber=8`, `HeaderCRC=10`, `DataCRC=12`, `DataADCStartOffset=14`, `DataADCEndOffset=22`, `DataStart=30`
|
||||
- **Properties**:
|
||||
- `ushort SeqNumber { get; }` — Sequence number of current packet.
|
||||
- `ushort SeqNumberPrev { get; }` — Previous sequence number (updated after parsing).
|
||||
- `ulong DlAdcStartOffset { get; }` — Start offset in ADC samples.
|
||||
- `ulong DlAdcEndOffset { get; }` — End offset in ADC samples.
|
||||
- `ulong DlStreamSampleNumber { get; }` — *Not assigned in constructor; appears unused.*
|
||||
- `ushort[] DlData { get; }` — ADC data samples (little-endian, signed offset not applied).
|
||||
- `uint[] DlChannels { get; }` — *Declared but not assigned; appears unused.*
|
||||
- **Constructor**:
|
||||
- `DownloadByteConverter(byte[] bytes)` — Parses packet header and data. Performs sequence number ordering check (logs out-of-order sequences to `Debug.WriteLine`).
|
||||
- **Helper Methods**:
|
||||
- `GetULong(byte[] bytes, int offset)` — Reads 8-byte little-endian value.
|
||||
- `GetUShort(byte[] bytes, int offset)` — Reads 2-byte big-endian value (parameter order).
|
||||
- `GetUInt(byte[] bytes, int offset)` — Reads 4-byte big-endian value.
|
||||
- `GetDownloadUShort(byte[] bytes, int offset)` — Reads 2-byte little-endian value (data order).
|
||||
|
||||
#### `QueryEthernetEventInfo`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Retrieves metadata about an Ethernet event recorder event.
|
||||
- **Properties**:
|
||||
- `ushort EventID { get; set; }` — Event ID to query (parameter input).
|
||||
- `ushort DataDownloaded { get; }` — Downloaded flag (1 = data present).
|
||||
- `ulong TotalByteCount { get; }` — Total bytes recorded.
|
||||
- `ulong TriggerByteCount { get; }` — Bytes recorded before trigger.
|
||||
- `ulong FaultByteCount { get; }` — Bytes recorded during fault condition.
|
||||
- `uint[] DataStartTimeStamp { get; }` — Timestamp array: `[seconds, nanoseconds]`.
|
||||
- **Constructors**:
|
||||
- `QueryEthernetEventInfo(ICommunication sock)`
|
||||
- `QueryEthernetEventInfo(ICommunication sock, int timeoutMillisec)`
|
||||
- **Overrides**:
|
||||
- `protected override CommandReceiveAction WholePackage()` — Parses 36-byte response.
|
||||
- `public override void ResponseToString(ref List<List<string>> lines)` — Appends all metadata fields.
|
||||
|
||||
#### `QueryEthernetEventData`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Retrieves payload data for an Ethernet event recorder event.
|
||||
- **Properties**:
|
||||
- `ushort EventID { get; set; }` — Event ID (parameter input).
|
||||
- `uint RequestByteCount { get; set; }` — Number of bytes to request.
|
||||
- `ulong StartDataOffsetBytes { get; set; }` — Byte offset to start reading.
|
||||
- `byte[] Data { get; }` — Downloaded payload bytes.
|
||||
- **Constants**:
|
||||
- `private const int PARAMETER_BYTE_COUNT = 14`
|
||||
- **Constructors**:
|
||||
- `QueryEthernetEventData(ICommunication sock)`
|
||||
- `QueryEthernetEventData(ICommunication sock, int timeoutMS)`
|
||||
- **Overrides**:
|
||||
- `protected override CommandReceiveAction WholePackage()` — Parses response header and payload.
|
||||
- `public override void CommandToString(...)` / `ResponseToString(...)` — Logs key parameters.
|
||||
|
||||
#### `QueryUARTEventData`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Retrieves payload data for a UART event recorder event.
|
||||
- **Constants**:
|
||||
- `public const int MAX_DATA_LENGTH = 2000`
|
||||
- `public const int PAYLOAD_HEADER_LENGTH = 14`
|
||||
- **Properties**:
|
||||
- `ushort EventNumber { get; set; }` — Event number.
|
||||
- `uint RequestByteCount { get; set; }` — Requested byte count.
|
||||
- `ulong RequestOffsetByteCount { get; set; }` — Byte offset.
|
||||
- `uint PayloadByteCount { get; }` — Actual bytes returned.
|
||||
- `ulong PayloadOffsetByteCount { get; }` — Offset of returned data.
|
||||
- `byte[] PayloadData { get; }` — Downloaded payload bytes.
|
||||
- **Constructors**:
|
||||
- `QueryUARTEventData(ICommunication sock)`
|
||||
- `QueryUARTEventData(ICommunication sock, int timeoutMillisec)`
|
||||
- **Overrides**:
|
||||
- `public override void Execute(...)` / `SyncExecute()` — Clears `_data` before execution.
|
||||
- `protected override CommandReceiveAction WholePackage()` — Parses header and payload.
|
||||
- `protected override CommandReceiveAction WholePackagePost()` — Creates `QueryEventDataReport` with status.
|
||||
- `public override void CommandToString(...)` / `ResponseToString(...)` — Logs key fields.
|
||||
|
||||
#### `QueryUARTEventInfo`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Retrieves metadata about a UART event recorder event.
|
||||
- **Properties**:
|
||||
- `ushort EventNumber { get; set; }` — Event number (parameter input).
|
||||
- `bool DataPresent { get; }` — `1 == _dataPresent`.
|
||||
- `bool DataDownloaded { get; }` — `1 == _dataDownloaded`.
|
||||
- `ulong TotalByteCount { get; }`
|
||||
- `ulong TriggerByteCount { get; }`
|
||||
- `ulong FaultByteCount { get; }`
|
||||
- `uint StartTimestamp { get; }`
|
||||
- `uint EndTimestamp { get; }`
|
||||
- `uint BaudRate { get; }`
|
||||
- **Constructors**:
|
||||
- `QueryUARTEventInfo(ICommunication sock)`
|
||||
- `QueryUARTEventInfo(ICommunication sock, int timeoutMillisec)`
|
||||
- **Overrides**:
|
||||
- `protected override CommandReceiveAction WholePackage()` — Parses 48-byte response.
|
||||
- `protected override CommandReceiveAction WholePackagePost()` — Creates `QueryEventDataReport` with status.
|
||||
- `public override void CommandToString(...)` / `ResponseToString(...)` — Logs key fields.
|
||||
|
||||
#### `QueryEventDataBase`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Base class for querying ADC event data. Supports single-channel or multi-channel (up to 3) downloads.
|
||||
- **Constants**:
|
||||
- `public const byte ALL_CHANNELS = 0xFF`
|
||||
- `private const ushort ADC_OFFSET = 0x8000`
|
||||
- **Properties**:
|
||||
- `ushort EventNumber { get; set; }` — Event number.
|
||||
- `virtual ulong FirstSample { get; set; }` — First sample index.
|
||||
- `virtual ulong LastSample { get; set; }` — Last sample index.
|
||||
- `byte Channel { get; set; }` — Channel selector. `0xFF` → 3 channels; else → 1 channel.
|
||||
- `int ChannelsDownloaded { get; set; }`
|
||||
- `int Count { get; }` — Number of samples downloaded (`_samplesDownloaded`).
|
||||
- **Constructors**:
|
||||
- `QueryEventDataBase(ICommunication sock)`
|
||||
- `QueryEventDataBase(ICommunication sock, int timeoutMillisec)`
|
||||
- **Overrides**:
|
||||
- `public override void Execute(...)` / `SyncExecute()` — Validates `FirstSample ≤ LastSample`.
|
||||
- `protected override CommandReceiveAction WholePackage()` — Parses raw `ushort[]` data.
|
||||
- `protected override CommandReceiveAction WholePackagePost()` — Converts `ushort[]` to `short[][]` (signed ADC), populates `QueryEventDataReport.Data`.
|
||||
- `public virtual void GetChannelData(int channel, out short[] signedADC)` — Extracts signed ADC data for a channel, applying `ADC_OFFSET` subtraction and channel ordering logic.
|
||||
- `public virtual void GetRawIndexedData(int index, out ushort[] data)` — Extracts raw (unsigned) data for a channel index.
|
||||
- `public override void CommandToString(...)` / `ResponseToString(...)` — Logs key parameters.
|
||||
|
||||
#### `GetNextDownloadStreamDataSamples`
|
||||
- **Inherits**: `EventDataCommands`
|
||||
- **Purpose**: Retrieves next packet of streaming event data. Does *not* send a command; reads buffered data.
|
||||
- **Properties**:
|
||||
- `DownloadByteConverter DlData { get; private set; }` — Parsed packet data.
|
||||
- **Constructors**:
|
||||
- `GetNextDownloadStreamDataSamples(ICommunication sock)`
|
||||
- `GetNextDownloadStreamDataSamples(ICommunication sock, int msTimeout)`
|
||||
- **Overrides**:
|
||||
- `public override void SyncExecute()` — Custom implementation to avoid sending command; reads response directly.
|
||||
- `public void ProcessData()` — Parses `baseResponse.ToBytes()` into `DlData`, validates CRC and sequence numbers.
|
||||
- **Behavior**:
|
||||
- `LogCommands = false` and `baseCommand.ShouldLog = false` (in constructors).
|
||||
- Sequence validation: throws `Exception("sequence number overflow")` if `|Δseq| > MAX_SEQUENCE_DIFF` (1000) and not initial packet.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Command Type**: All `EventDataCommands` subclasses set `command.Type = CommandPacket.CommandType.EventData`.
|
||||
- **Parameter Initialization**: All subclasses initialize `command.Parameter` to a fixed size (e.g., `new byte[18]` for `StartDownloadStreamData`, `new byte[14]` for `QueryEthernetEventData`/`QueryUARTEventData`).
|
||||
- **Parameter Offsets**: Command parameters are written at specific byte offsets (e.g., `EventNumber` at offset 0, `FirstSample` at offset 2, `LastSample` at offset 10, `Channel` at offset 18). Offsets are hardcoded in `SetParameter` calls.
|
||||
- **Response Parsing**: `WholePackage()` methods parse response parameters using `response.GetParameter(offset, out T value)`, where offsets are fixed per command specification.
|
||||
- **ADC Data Format**: Raw ADC data is stored as `ushort[]` in `QueryEventDataBase`. Conversion to signed `short[]` applies `ADC_OFFSET = 0x8000` subtraction.
|
||||
- **Channel Ordering**: `GetChannelData` implements a non-trivial channel ordering scheme (e.g., for 9-channel stacks: `7 8 9 4 5 6 1 2 3` repeated).
|
||||
- **Callback Report**: All event data download commands (`QueryEventDataBase`, `QueryUARTEventData`, `QueryUARTEventInfo`) produce a `QueryEventDataReport` in `WholePackagePost()`, with `Status` set to `Success` or `Failure` based on `response.Status`.
|
||||
- **Streaming Sequence Validation**: `GetNextDownloadStreamDataSamples.ProcessData()` enforces sequence number ordering: `SeqNumberPrev == SeqNumber - 1` (or initial packet `SeqNumber == 0`), logging out-of-order sequences.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Internal Dependencies
|
||||
- **`DTS.Common.ICommunication`**: Provides `ICommunication` interface for socket communication.
|
||||
- **`DTS.Common.Enums.DASFactory`**: Defines `CommandStatus`, `Commands` enum (in `EventDataCommands`), and `DFConstantsAndEnums`.
|
||||
- **`DTS.Common.Interface.DASFactory`**: Contains `ICommunication` type alias.
|
||||
- **`DTS.Common.DASResource`**: Provides `Strings` class (used in `QueryEventDataBase` for exception messages).
|
||||
- **`DTS.Common.Utilities.Logging`**: Provides `APILogger` (used in `QueryUARTEventData`, `QueryUARTEventInfo`).
|
||||
- **`DTS.Common.Strings`**: Used in `QueryUARTEventInfo` for logging.
|
||||
|
||||
### External Dependencies
|
||||
- **`System.Collections.Generic`**, **`System`**, **`System.Linq`**, **`System.Threading.Tasks`**, **`System.Diagnostics`**, **`System.Text`**: Standard .NET libraries.
|
||||
- **Firmware**: Requires SLICE2 firmware ≥ A1N4 for `StartDownloadStreamData` to function.
|
||||
|
||||
### Inheritance/Usage
|
||||
- **Inherits from**: `CommandBase` (via `EventDataCommands`).
|
||||
- **Used by**: Higher-level code that orchestrates event data retrieval (not visible in source).
|
||||
- **Implements**: `ICommandReport` (via `QueryEventDataReport`).
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`DownloadByteConverter.DlAdcStartOffset` Assignment Bug**: In constructor, `DlAdcStartOffset = GetUInt(...)` is overwritten by `DlAdcStartOffset = GetULong(...)`. The second assignment overwrites the first, but the `GetUInt` call is redundant and likely a typo. The correct field is `DlAdcEndOffset`, which uses `GetULong`.
|
||||
- **`DownloadByteConverter.DlStreamSampleNumber` Unused**: Declared but never assigned; appears to be incomplete.
|
||||
- **`DownloadByteConverter.DlChannels` Unused**: Declared but never assigned; likely a placeholder.
|
||||
- **`QueryEventDataReport.Data` Not Populated**: The `Data` property is declared but never assigned in any `WholePackagePost()` method (e.g., `QueryEventDataBase` computes `short[][]` but does not assign it to `cbReport.Data`).
|
||||
- **`QueryEventDataBase.Channel` Side Effect**: Setting `Channel` to `0xFF` sets `ChannelsDownloaded = 3`; otherwise `ChannelsDownloaded = 1`. This is implicit and not obvious from property definition.
|
||||
- **`GetNextDownloadStreamDataSamples.SyncExecute()` Avoids Sending Command**: This is intentional (per comment) but may be surprising. It reads buffered data without sending a new command.
|
||||
- **Sequence Number Overflow Handling**: `ProcessData()` throws `Exception("sequence number overflow")` if `|Δseq| > 1000`, but the comment notes this is unintentional (preserved from legacy code). This could crash the caller.
|
||||
- **Byte Order Inconsistency**: `DownloadByteConverter` distinguishes between parameter byte order (big-endian for offsets) and data byte order (little-end
|
||||
@@ -0,0 +1,398 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastIdentify.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastResetMcu.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MACTableEntry.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastSetIPAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastSetSubnetAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastSetGatewayAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastSetDhcp.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastSetDnsAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastGetIpAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastGetDnsAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastGetSubnetAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastGetDhcp.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastGetGatewayAddress.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastAutoDiscover.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastDiscoverSlice6.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastUDPQueryQATS.cs
|
||||
- DataPRO/SLICECommands/MulticastCommands/MulticastCommandBase.cs
|
||||
generated_at: "2026-04-16T03:55:01.601441+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "0d6bca66954e7e76"
|
||||
---
|
||||
|
||||
# Documentation: Multicast Command Module (`DTS.DASLib.Command.SLICE.MulticastCommands`)
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides a set of multicast-based communication commands for interacting with SLICE-series hardware devices (e.g., Slice6, S6DB) over UDP. It enables discovery, configuration (IP, subnet, gateway, DNS, DHCP), diagnostics (MAC table retrieval), and status querying (e.g., QATS sensor data) via multicast messaging. All commands inherit from `MulticastCommandBase`, which abstracts low-level UDP multicast send/receive logic, packet parsing, and MAC address handling. The module serves as the primary interface for networked device management in the DAS (Data Acquisition System) framework.
|
||||
|
||||
---
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Classes
|
||||
|
||||
#### `MulticastCommandBase`
|
||||
*Abstract base class for all multicast commands.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastCommandBase(ICommunication sock)`
|
||||
Initializes base with a communication socket.
|
||||
- `MulticastCommandBase(ICommunication sock, int timeoutMillisec)`
|
||||
Initializes with socket and custom receive timeout.
|
||||
|
||||
- **Properties**
|
||||
- `protected abstract Commands Command { get; }`
|
||||
Returns the command enum value (e.g., `Commands.Identify`).
|
||||
- `public string HostMac { get; set; }`
|
||||
MAC address of the sending host (used in command/response validation).
|
||||
- `public string ClientMac { set; }`
|
||||
MAC address of the target client device.
|
||||
- `public int ReceiveTimeoutMs { get; set; } = 3000`
|
||||
Timeout for receiving responses.
|
||||
- `public IPAddress BindToAdapterIPAddress { get; set; } = IPAddress.Any`
|
||||
Network adapter to bind to for sending/receiving.
|
||||
|
||||
- **Methods**
|
||||
- `public void BuildPacket()`
|
||||
Computes CRCs on the command packet.
|
||||
- `public void SendCommand()`
|
||||
Sends the multicast command packet without waiting for responses.
|
||||
- `public void StartListening()`
|
||||
Starts a background thread to listen for multicast responses.
|
||||
- `public void StopListening()`
|
||||
Signals the listening thread to terminate.
|
||||
- `public void MulticastExecute(CancellationToken ct, bool waitForResponse = true)`
|
||||
Sends command and optionally waits for responses (uses `StartListening` internally if `waitForResponse=true`).
|
||||
- `protected virtual bool StopAfterFirstMessage => true`
|
||||
Controls whether to stop after first response (overridden in `MulticastAutoDiscover`, `MulticastDiscoverSlice6`, `MulticastUdpQueryQATS`).
|
||||
- `protected virtual CommandReceiveAction WholePackage()`
|
||||
Parses incoming response packet (overridden in derived classes).
|
||||
- `public static string GetMacAddress()`
|
||||
Returns first multicast-capable, active network interface’s MAC address.
|
||||
|
||||
#### `MulticastIdentify`
|
||||
*Command to trigger device identification (e.g., LED blink).*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastIdentify(ICommunication sock)`
|
||||
- `MulticastIdentify(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.Identify`
|
||||
- `public override void CommandToString(ref List<List<string>> lines)`
|
||||
Appends `"MAC: {CommandClientMac}"` to output.
|
||||
|
||||
#### `MulticastResetMcu`
|
||||
*Command to reset the device MCU.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastResetMcu(ICommunication sock)`
|
||||
- `MulticastResetMcu(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.ResetMcu`
|
||||
- `public override void CommandToString(ref List<List<string>> lines)`
|
||||
Appends `"MAC: {CommandClientMac}"`.
|
||||
|
||||
#### `MulticastSetIpAddress`
|
||||
*Command to set static IP address.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastSetIpAddress(ICommunication sock)`
|
||||
- `MulticastSetIpAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Ip { set; }`
|
||||
Sets IP address string (e.g., `"192.168.1.100"`); writes to parameter buffer.
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.SetIpAddress`
|
||||
- `public override void CommandToString(ref List<List<string>> lines)`
|
||||
Appends `"MAC: {CommandClientMac} IP: {_ip}"`.
|
||||
|
||||
#### `MulticastSetSubnetAddress`
|
||||
*Command to set subnet mask.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastSetSubnetAddress(ICommunication sock)`
|
||||
- `MulticastSetSubnetAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Subnet { set; }`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.SetSubnetAddress`
|
||||
- `public override void CommandToString(ref List<List<string>> lines)`
|
||||
Appends `"MAC: {CommandClientMac} Subnet: {_subnet}"`.
|
||||
|
||||
#### `MulticastSetGatewayAddress`
|
||||
*Command to set gateway IP.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastSetGatewayAddress(ICommunication sock)`
|
||||
- `MulticastSetGatewayAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Gateway { set; }`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.SetGatewayAddress`
|
||||
- `public override void CommandToString(ref List<List<string>> lines)`
|
||||
Appends `"MAC: {CommandClientMac} Gateway: {_gateway}"`.
|
||||
|
||||
#### `MulticastSetDnsAddress`
|
||||
*Command to set DNS server IP.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastSetDnsAddress(ICommunication sock)`
|
||||
- `MulticastSetDnsAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Dns { set; }`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.SetDnsAddress`
|
||||
- `public override void CommandToString(ref List<List<string>> lines)`
|
||||
Appends `"MAC: {CommandClientMac} DNS: {_dns}"`.
|
||||
|
||||
#### `MulticastSetDhcp`
|
||||
*Command to enable/disable DHCP.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastSetDhcp(ICommunication sock)`
|
||||
- `MulticastSetDhcp(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public bool Dhcp { set; }`
|
||||
Converts `bool` to `byte` (0/1) and writes to parameter buffer.
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.SetDhcp`
|
||||
- `public override void CommandToString(ref List<List<string>> lines)`
|
||||
Appends `"MAC: {CommandClientMac} DHCP: {_dhcp} "`.
|
||||
|
||||
#### `MulticastGetIpAddress`
|
||||
*Command to retrieve device IP address.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastGetIpAddress(ICommunication sock)`
|
||||
- `MulticastGetIpAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Ip => _ip`
|
||||
Populated after `WholePackage()` processes response.
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.GetIpAddress`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
On success, extracts IP from response at offset `DOUBLE_MAC_ADDR_SIZE`.
|
||||
- `public override void CommandToString(...)` / `ResponseToString(...)`
|
||||
Appends MAC and (response) IP.
|
||||
|
||||
#### `MulticastGetSubnetAddress`
|
||||
*Command to retrieve subnet mask.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastGetSubnetAddress(ICommunication sock)`
|
||||
- `MulticastGetSubnetAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Subnet => _subnet`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.GetSubnetAddress`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
Extracts subnet at offset `FIRST_PARAMETER_OFFSET`.
|
||||
|
||||
#### `MulticastGetGatewayAddress`
|
||||
*Command to retrieve gateway IP.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastGetGatewayAddress(ICommunication sock)`
|
||||
- `MulticastGetGatewayAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Gateway => _gateway`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.GetGatewayAddress`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
Extracts gateway at offset `FIRST_PARAMETER_OFFSET`.
|
||||
|
||||
#### `MulticastGetDnsAddress`
|
||||
*Command to retrieve DNS IP.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastGetDnsAddress(ICommunication sock)`
|
||||
- `MulticastGetDnsAddress(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public string Dns => _dns`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.GetDnsAddress`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
Extracts DNS at offset `FIRST_PARAMETER_OFFSET`.
|
||||
|
||||
#### `MulticastGetDhcp`
|
||||
*Command to retrieve DHCP status.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastGetDhcp(ICommunication sock)`
|
||||
- `MulticastGetDhcp(ICommunication sock, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public bool Dhcp => Convert.ToBoolean(_dhcp)`
|
||||
`_dhcp` is a `byte` (0/1).
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.GetDhcp`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
Extracts DHCP byte at `FIRST_PARAMETER_OFFSET`; returns early on error.
|
||||
- `public override void CommandToString(...)` uses `ResponseClientMac` (unlike others using `CommandClientMac`).
|
||||
|
||||
#### `MulticastAutoDiscover`
|
||||
*Command to discover devices on network via multicast.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastAutoDiscover()`
|
||||
- `MulticastAutoDiscover(string macAddress)`
|
||||
- `MulticastAutoDiscover(int timeoutMillisec)`
|
||||
- `MulticastAutoDiscover(string macAddress, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public List<IDiscoveredDevice> DiscoveredDevices { get; }`
|
||||
Populated with discovered devices after execution.
|
||||
- `public TextLogger Logger { get; set; }`
|
||||
- `public DFConstantsAndEnums.MultiCastDeviceClasses DeviceClass { set; }`
|
||||
- `public ResponseOptions ResponseOption { set; }`
|
||||
- `public IPAddress Address { set; }`
|
||||
Sets multicast receive address/config.
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.AutoDiscover`
|
||||
- `protected override bool StopAfterFirstMessage => false`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
Parses response payload (278 bytes) into device fields (IP, MAC, serial, etc.); appends to `DiscoveredDevices`.
|
||||
- `public override void CommandToString(...)`
|
||||
Appends `"AutoDiscover: [{HostMac}] {_address} : {_port}"`.
|
||||
|
||||
#### `MulticastDiscoverSlice6`
|
||||
*Command to retrieve MAC table entries from Slice6/S6DB devices.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastDiscoverSlice6(DeviceClasses deviceClass, string hostMac)`
|
||||
- `MulticastDiscoverSlice6(string hostMac, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public DeviceClasses DeviceClass { set; }`
|
||||
- `public ResponseOptions ResponseOption { set; }`
|
||||
- `public uint DesiredPort { set; }`
|
||||
Bitmask for ports (e.g., `0x0F` for ports 1–4).
|
||||
- `public byte[] MACFilter { set; }`
|
||||
MAC address filter (e.g., `00:19:9B:*:*:*`).
|
||||
- `public TextLogger Logger { get; set; }`
|
||||
- `public Dictionary<string, IDiscoveredDevice> MACAddressToDevice { get; set; }`
|
||||
- `public DiscoveredConnectedSlice[] ConnectedDevices => _connectedDevices.ToArray()`
|
||||
Populated with MAC table entries per device.
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.GetMACTable`
|
||||
- `protected override bool StopAfterFirstMessage => false`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
Parses MAC table entries (12-byte records) into `MACTableEntry` objects; adds to `_connectedDevices`.
|
||||
- `public static string MACAddressToString(IEnumerable<byte> mac)`
|
||||
Converts MAC byte array to `"XX:XX:XX:XX:XX:XX"` string.
|
||||
|
||||
#### `MulticastUdpQueryQATS`
|
||||
*Command to query QATS (Quasi-Adaptive Time Series) sensor data from devices.*
|
||||
|
||||
- **Constructors**
|
||||
- `MulticastUdpQueryQATS(ICommunication sock)`
|
||||
- `MulticastUdpQueryQATS(string macAddress)`
|
||||
- `MulticastUdpQueryQATS(int timeoutMillisec)`
|
||||
- `MulticastUdpQueryQATS(string macAddress, int timeoutMillisec)`
|
||||
|
||||
- **Properties**
|
||||
- `public List<IUDPQATSEntry> QATSEntry { get; set; } = new List<IUDPQATSEntry>()`
|
||||
Accumulates QATS entries until `GetUDPQATs()` clears them.
|
||||
- `public DFConstantsAndEnums.MultiCastDeviceClasses DeviceClass { set; }`
|
||||
- `public ResponseOptions ResponseOption { set; }`
|
||||
- `public IPAddress Address { set; }`
|
||||
- `public int Port { set; }`
|
||||
|
||||
- **Overrides**
|
||||
- `protected override Commands Command => Commands.UdpQueryQTAS`
|
||||
- `protected override bool StopAfterFirstMessage => false`
|
||||
- `protected override CommandReceiveAction WholePackage()`
|
||||
Parses 215-byte response payload at offset 74 (`QATS_OFFSET`) into QATS fields (arm state, sample rate, tilt sensors, etc.); adds to `QATSEntry` (thread-safe via `lock`).
|
||||
- `public IUDPQATSEntry[] GetUDPQATs()`
|
||||
Returns and clears `QATSEntry` list.
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **MAC Address Format**: All MAC addresses are stored and transmitted as colon-separated hex strings (e.g., `"AA:BB:CC:DD:EE:FF"`). Internal parsing uses hyphen-separated strings (e.g., `"AA-BB-CC-DD-EE-FF"`) from the protocol, converted via `Replace('-', ':')`.
|
||||
- **Command/Response Validation**: `MulticastCommandBase.WholePackage()` validates that:
|
||||
- `ResponseClientMac == CommandClientMac`
|
||||
- `ResponseHostMac == HostMac`
|
||||
- Response status is `StatusNoError`.
|
||||
- **Payload Sizes**:
|
||||
- Command payload size is fixed per command (e.g., `DOUBLE_MAC_ADDR_SIZE + IP_ADDR_SIZE` for IP/subnet/gateway/DNS/DHCP commands).
|
||||
- Response payload size is fixed per command (e.g., 278 bytes for `AutoDiscover`, 215 for `UdpQueryQTAS`).
|
||||
- **Multicast Addresses**:
|
||||
- Command multicast group: `"239.1.2.3"` (configurable via `MulticastAddress`).
|
||||
- Response multicast group: `"239.4.5.6"` (configurable via `MulticastReceiveAddress`).
|
||||
- **Port Numbers**:
|
||||
- Command port: `8501` (`Ports.Command`).
|
||||
- Response port: `8503` (`Ports.Response`).
|
||||
- **Timeout Handling**: Default receive timeout is 3000 ms (`DEFAULT_RECEIVE_TIMEOUT_MS`). `MulticastUdpQueryQATS` overrides to 5000 ms.
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- `DTS.Common.Interface.DASFactory.ICommunication`
|
||||
Used for socket abstraction (though most commands instantiate `UdpClient` directly).
|
||||
- `DTS.Common.Enums.DASFactory`
|
||||
Defines enums: `Commands`, `MultiCastDeviceClasses`, `ResponseOptions`, `CommandStatus`.
|
||||
- `DTS.Common.Utilities.Logging`
|
||||
`TextLogger`, `APILogger`.
|
||||
- `DTS.DASLib.Command.Classes`
|
||||
Defines `IDiscoveredDevice`, `ConnectedEthernetDevice`, `UDPQATSEntry`, `IUDPQATSEntry`.
|
||||
- `System.Net`, `System.Net.NetworkInformation`
|
||||
For `UdpClient`, `IPAddress`, `NetworkInterface`, `MulticastOption`.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- High-level discovery/configuration workflows (e.g., device setup tools).
|
||||
- `MulticastAutoDiscover` and `MulticastDiscoverSlice6` are used for device enumeration.
|
||||
- `MulticastUdpQueryQATS` is used for real-time sensor data acquisition.
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **MAC Address Parsing Inconsistency**:
|
||||
`MulticastGetDhcp.CommandToString` uses `ResponseClientMac`, while other `CommandToString` overrides use `CommandClientMac`. This may cause mismatched MACs if `ClientMac` is set but `ResponseClientMac` is not yet populated.
|
||||
- **`MulticastCommandBase.WholePackage()` Default Behavior**:
|
||||
The base implementation strictly validates `CommandClientMac == ResponseClientMac`. Derived classes (`MulticastAutoDiscover`, `MulticastDiscoverSlice6`, `MulticastUdpQueryQATS`) override this to accept responses from *any* client MAC (or validate only `HostMac`), but this is not obvious from the base class.
|
||||
- **`MulticastDiscoverSlice6` Port Filtering**:
|
||||
`ParseSSIData` (not used in current `MulticastDiscoverSlice6`) filters ports based on device class (Slice6: port 2 only; S6DB: ports ≤4). This logic is unused in `WholePackage()`—MAC table parsing uses raw port values from the response.
|
||||
- **Thread Safety in `MulticastUdpQueryQATS`**:
|
||||
`QATSEntry` is accessed via `lock(MyLock)` in `WholePackage()` and `GetUDPQATs()`, but `MyLock` is `private static`, meaning *all instances share the same lock*. This may cause contention if multiple `MulticastUdpQueryQATS` instances run concurrently.
|
||||
- **`MulticastAutoDiscover` Payload Parsing**:
|
||||
Hardcoded offsets (e.g., `36`, `41`, `57`) assume fixed-layout binary protocol. Changes to firmware response structure will break parsing silently.
|
||||
- **`MulticastSetDhcp` Parameter Size**:
|
||||
`COMMAND_PAYLOAD_SIZE = DOUBLE_MAC_ADDR_SIZE + 1` implies a 1-byte DHCP flag, but `command.SetParameter(FIRST_PARAMETER_OFFSET, _dhcp)` writes a `byte`. Ensure `SetParameter` handles `byte` correctly (likely via implicit conversion to `int` or padding).
|
||||
- **`MulticastCommandBase.BindToAdapterIPAddress`**:
|
||||
Setting `BindToAdapterIPAddress` to `IPAddress.Any` may cause issues on multi-homed systems if the wrong interface is used for multicast traffic. No validation ensures the adapter is active/multicast-capable.
|
||||
- **`GetMacAddress()` Limitation**:
|
||||
Returns the *first* multicast-capable, active interface—may not be the desired interface for communication.
|
||||
@@ -0,0 +1,35 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/SLICECommands/Properties/AssemblyInfo.cs
|
||||
generated_at: "2026-04-16T03:55:22.017375+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "6cf6f8e540f4fe44"
|
||||
---
|
||||
|
||||
# Properties
|
||||
|
||||
## 1. Purpose
|
||||
This module is the `SLICECommands` .NET assembly, part of a proprietary codebase (likely related to SLICE—a domain-specific system, possibly for data processing, simulation, or industrial control). Its purpose is to encapsulate command-related functionality for the SLICE platform, though the provided `AssemblyInfo.cs` file itself contains only metadata and does not define executable logic. It serves as a foundational assembly unit, versioned and identified for deployment and interop purposes, with no visible business logic in the source provided.
|
||||
|
||||
## 2. Public Interface
|
||||
**No public types (classes, structs, interfaces, enums, or delegates) are defined in this file.**
|
||||
`AssemblyInfo.cs` is a metadata file used by the .NET build system to embed assembly-level attributes (e.g., title, version, COM visibility). It contains no executable code, and thus no public functions, classes, or methods.
|
||||
|
||||
## 3. Invariants
|
||||
- The assembly version is strictly `1.06.0081` (both `AssemblyVersion` and `AssemblyFileVersion` are identical).
|
||||
- The assembly is **not** COM-visible (`ComVisible(false)`), meaning its types are not exposed to COM clients by default.
|
||||
- The GUID `B97BAF22-3B93-4187-9438-848AC714A144` is permanently assigned as the typelib ID for COM interop *if* the assembly is later made COM-visible (e.g., via `ComVisible(true)` on specific types or reconfiguration).
|
||||
- Copyright notice is fixed to “Copyright © 2008”, indicating legacy status or intentional immutability of this metadata.
|
||||
|
||||
## 4. Dependencies
|
||||
- **Framework Dependencies**: Requires `System`, `System.Reflection`, `System.Runtime.CompilerServices`, and `System.Runtime.InteropServices` (standard .NET namespaces).
|
||||
- **No external project or library dependencies** are declared in this file.
|
||||
- **Dependents**: This assembly is likely referenced by other modules in the `DataPRO` suite (e.g., `SLICECommands` suggests it is part of a larger `DataPRO` product family), but no direct references are visible here.
|
||||
|
||||
## 5. Gotchas
|
||||
- **Misleading file name**: The file is named `AssemblyInfo.cs`, which is conventional for assembly metadata, but the module name `SLICECommands` implies command-handling logic—this file provides none. Developers may incorrectly expect command implementations here.
|
||||
- **Hardcoded year in copyright**: The copyright year is `2008`, which may be outdated or intentionally preserved for legal consistency; no versioning or update logic is evident.
|
||||
- **COM interop disabled by default**: Since `ComVisible(false)` is set at the assembly level, any types intended for COM exposure must explicitly opt in with `[ComVisible(true)]` at the type or method level.
|
||||
- **No semantic versioning**: The version `1.06.0081` uses a non-standard format (likely `major.minor.build`), but without documentation, the meaning of each component (e.g., whether `06` is minor or patch) is ambiguous.
|
||||
- **None identified from source alone.**
|
||||
@@ -0,0 +1,204 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/SLICECommands/RealtimeCommands/EndRealtimeMode.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/UDPStreamPacket.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/StartRealtimeMode.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/RealtimeCommandBase.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/IGetRealtimeSamples.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/GetRealtimeSamplesSLICE6.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/GetRealtimeSamplesSLICE2.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/RetrieveSingleSample.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/GetRealtimeSamplesTSRAIR.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/RetrieveSampleAverage.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/StartRealtimeStreamingMode.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/GetRealtimeSamples.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/RealtimeStreamDecoder.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/UDPRealtimeByteConverter.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/StreamReaderUDP.cs
|
||||
- DataPRO/SLICECommands/RealtimeCommands/StreamConfigUDP.cs
|
||||
generated_at: "2026-04-16T03:55:46.218507+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "775d71b774e90d26"
|
||||
---
|
||||
|
||||
# Realtime Command Module Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides command classes for controlling and retrieving real-time data from SLICE devices. It implements a family of command classes that inherit from `RealtimeCommandBase` to manage device modes (start/end real-time mode, streaming mode), retrieve sample data (single samples, averages, multi-sample batches), and configure UDP streaming. The module supports multiple device types (SLICE2, SLICE6, TSRAIR) with specialized implementations for data interpretation, and includes infrastructure for decoding raw UDP packets (`RealtimeStreamDecoder`, `UDPRealtimeByteConverter`) and streaming via `StreamReaderUDP`. Its role is to abstract low-level communication protocol details and provide a consistent interface for real-time data acquisition.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Command Classes
|
||||
|
||||
#### `EndRealtimeMode`
|
||||
- **Constructor**: `EndRealtimeMode(ICommunication sock)` / `EndRealtimeMode(ICommunication sock, int timeoutMillisec)`
|
||||
- **Purpose**: Sends command `0x02` (`Commands.EndRealtimeMode`) to terminate real-time mode on the device.
|
||||
|
||||
#### `StartRealtimeMode`
|
||||
- **Constructor**: `StartRealtimeMode(ICommunication sock)` / `StartRealtimeMode(ICommunication sock, int timeoutMillisec)`
|
||||
- **Properties**:
|
||||
- `SupportsMultipleSampleRealtime` (bool): Controls whether the command parameter is 1 byte (true) or 0 bytes (false). Default is `true`.
|
||||
- **Purpose**: Sends command `0x01` (`Commands.StartRealtimeMode`) to enable real-time mode. Presence of a 1-byte parameter signals firmware support for multi-sample real-time.
|
||||
|
||||
#### `RetrieveSingleSample`
|
||||
- **Constructor**: `RetrieveSingleSample(ICommunication sock)` / `RetrieveSingleSample(ICommunication sock, int timeoutMillisec)`
|
||||
- **Properties**:
|
||||
- `Channels` (ushort): Number of channels in `_data`.
|
||||
- `GetChannelData(int zeroBasedChannel)` (short): Returns the single sample for the specified channel.
|
||||
- **Purpose**: Sends command `0x04` (`Commands.RetrieveSingleSample`) and decodes response into signed `short` values. Converts unsigned values >32768 to negative by subtracting 65536.
|
||||
|
||||
#### `RetrieveSampleAverage`
|
||||
- **Constructor**: `RetrieveSampleAverage(ICommunication sock)` / `RetrieveSampleAverage(ICommunication sock, int timeoutMillisec)`
|
||||
- **Properties**:
|
||||
- `Samples` (ushort): Sets number of samples to average in command parameter; gets number of samples used in response.
|
||||
- `Channels` (ushort): Number of channels in `_data`.
|
||||
- `GetChannelData(int zeroBasedChannel)` (short): Returns the averaged sample for the specified channel.
|
||||
- **Purpose**: Sends command `0x05` (`Commands.RetrieveSampleAverage`) with configurable sample count. Decodes response to extract number of samples used and mean values per channel.
|
||||
|
||||
#### `StartRealtimeStreamingMode`
|
||||
- **Constructor**: `StartRealtimeStreamingMode(ICommunication sock, byte[] channelList)` / `StartRealtimeStreamingMode(ICommunication sock, int timeoutMillisec, byte[] channelList)`
|
||||
- **Properties**:
|
||||
- `ChannelList` (byte[]): List of channels to collect data on. Sets command parameter.
|
||||
- **Purpose**: Sends command `0x07` (`Commands.StartRealtimeStreamingMode`) to put firmware into continuous streaming mode.
|
||||
|
||||
#### `StartTimeStampStreamMode`
|
||||
- **Constructor**: `StartTimeStampStreamMode(ICommunication sock)` / `StartTimeStampStreamMode(ICommunication sock, int timeoutMillisec)`
|
||||
- **Properties**:
|
||||
- `SupportsMultipleSampleRealtime` (bool): Controls parameter presence (1 byte if true, 0 if false).
|
||||
- `ParamsToSend` (byte[]): Sets command parameter bytes.
|
||||
- **Purpose**: Sends command `0x09` (`Commands.StartTimeStampStreamMode`) to start IRIG timestamped streaming. Requires minimum protocol version `UDPRealtimeStream`.
|
||||
|
||||
#### `StreamConfigUDPGet`
|
||||
- **Constructor**: `StreamConfigUDPGet(ICommunication sock)` / `StreamConfigUDPGet(ICommunication sock, int timeoutMillisec)`
|
||||
- **Properties**: All get/set properties map to fixed offsets in a 65-byte command/response payload:
|
||||
- `Stream_Profile_Number`, `UdpIpPort`, `TimeChannelID`, `DataChannelID`, `TMNS_*`, `IENAUDP_PortNumber`, `TMNS5-7`.
|
||||
- **Purpose**: Sends command `0x0D` (`Commands.I106StreamConfigGet`) to retrieve UDP streaming configuration.
|
||||
|
||||
#### `StreamConfigUDPSet`
|
||||
- **Constructor**: `StreamConfigUDPSet(ICommunication sock)` / `StreamConfigUDPSet(ICommunication sock, int timeoutMillisec)`
|
||||
- **Properties**: All get/set properties map to fixed offsets in a 74-byte command payload:
|
||||
- `Stream_Profile_Number`, `UdpIpPort`, `Irig106Config0/1`, `TMNS_*`, `IENAUDP_PortNumber`, `TMNS5-7`.
|
||||
- **Purpose**: Sends command `0x0C` (`Commands.I106StreamConfigSet`) to configure UDP streaming.
|
||||
|
||||
### Data Retrieval Classes (Implement `IGetRealtimeSamples`)
|
||||
|
||||
#### `IGetRealtimeSamples` Interface
|
||||
- **Properties**:
|
||||
- `SampleNumber` (ulong): First sample number in the returned batch.
|
||||
- `TimeStamp` (ulong)
|
||||
- `SequenceNumber` (ulong)
|
||||
- `Channels` (ushort): Total channel count.
|
||||
- `SamplesReturned` (int): Number of samples per channel returned.
|
||||
- `LogCommands` (bool): Whether to log command execution (default `false`).
|
||||
- **Methods**:
|
||||
- `GetChannelData(int zeroBasedChannel)` (short[]): Returns all samples for the specified channel.
|
||||
- `SyncExecute()` (void): Executes the command and retrieves samples.
|
||||
|
||||
#### `GetRealtimeSamples` (Base Class)
|
||||
- **Constructor**: `GetRealtimeSamples(ICommunication sock)` / `GetRealtimeSamples(ICommunication sock, int timeoutMillisec, bool bPolling = false)`
|
||||
- **Properties**:
|
||||
- `SampleNumber`, `TimeStamp`, `SequenceNumber`, `Channels`, `SamplesReturned`, `LogCommands` (inherited from interface).
|
||||
- **Purpose**: Base implementation for polling-based sample retrieval. Sends command `0x03` (`Commands.GetRealtimeSamples`) with 1-byte parameter. Decodes response with channel interleaving and applies offset subtraction (`-0x8000`) to convert unsigned to signed.
|
||||
|
||||
#### `GetRealtimeSamplesSLICE6`
|
||||
- **Constructor**: `GetRealtimeSamplesSLICE6(ICommunication sock)` / `GetRealtimeSamplesSLICE6(ICommunication sock, int timeoutMillisec)`
|
||||
- **Purpose**: Specialized implementation for SLICE6 devices. Decodes response data as signed (no conversion needed beyond byte-swapping). No offset adjustment.
|
||||
|
||||
#### `GetRealtimeSamplesSLICE2`
|
||||
- **Constructor**: `GetRealtimeSamplesSLICE2(ICommunication sock)` / `GetRealtimeSamplesSLICE2(ICommunication sock, int timeoutMillisec)`
|
||||
- **Purpose**: Specialized implementation for SLICE2 devices. Converts unsigned data to signed by adding `0x8000` after byte-swapping.
|
||||
|
||||
#### `GetRealtimeSamplesTSRAIR`
|
||||
- **Constructor**: `GetRealtimeSamplesTSRAIR(ICommunication sock)` / `GetRealtimeSamplesTSRAIR(ICommunication sock, int timeoutMillisec)`
|
||||
- **Properties**:
|
||||
- `Timestamps` (List<ulong>): List of timestamps (currently unused in `WholePackage()`).
|
||||
- **Purpose**: Specialized implementation for TSRAIR devices. Decodes unsigned data with byte-swapping but no offset adjustment.
|
||||
|
||||
### UDP Streaming Infrastructure
|
||||
|
||||
#### `UDPStreamPacket`
|
||||
- **Properties**:
|
||||
- `ChannelData` (short[][]): First index = channel, second = sample.
|
||||
- `TimeStamp` (long)
|
||||
- `SampleNumber` (ulong)
|
||||
- `SequenceNumber` (ulong)
|
||||
- `PTPTimesec`, `PTPTimeNsec` (uint)
|
||||
- `PTPSyncStatusError`, `ADCOverflowStatus` (bool)
|
||||
- `PTPTimeString` (string): Concatenation of `PTPTimesec` and `PTPTimeNsec` (zero-padded to 9 digits).
|
||||
- **Purpose**: Data structure for parsed UDP streaming packets.
|
||||
|
||||
#### `RealtimeStreamDecoder`
|
||||
- **Constructor**: `RealtimeStreamDecoder(IReadOnlyList<byte> bytes)`
|
||||
- **Properties**:
|
||||
- `SequenceNumber` (ushort), `TimeStamp` (ulong), `SampleNumber` (ulong), `Channels` (int[]), `RtData` (ushort[])
|
||||
- **Purpose**: Decodes raw UDP packet bytes (SPS format) into structured data. Handles header parsing (byte order reversed), channel mask extraction, and data extraction (byte order preserved). Does not convert to signed values.
|
||||
|
||||
#### `UDPRealtimeByteConverter`
|
||||
- **Constructor**: `UDPRealtimeByteConverter(byte[] bytes)`
|
||||
- **Properties**:
|
||||
- `PacketPattern`, `DataChannelID`, `PacketLength`, `DataLength`, `DataTypeVersion`, `SequenceNumber`, `PacketFlags`, `DataType`, `RelativeTime32`, `RelativeTime16`, `HdrCrc16`, `PtpTimeStampSec`, `PtpTimeStampNsec`, `Hdr2Crc16`, `ChannelMask`, `UdpSampleCount`
|
||||
- `RtData` (ushort[]), `Channels` (uint[]), `SequenceNumberPrev` (byte)
|
||||
- **Purpose**: Parses UDP packet headers and data. Supports `ANALOG_DATA_FORMAT_1` (`0x21`) and `TIME_DATA_PTP` (`0x12`). Converts data by XOR with `0x8000` to produce signed values.
|
||||
|
||||
#### `StreamReaderUDP`
|
||||
- **Constructor**: `StreamReaderUDP(string streamAddress, string hostAddress, UDPStreamProfile uDPStreamType, byte[] channels)`
|
||||
- **Properties**:
|
||||
- `StreamAddress`, `cmdline`, `HostIPAddress`, `UDPStreamType`, `Channels`, `UDPEndpoint`, `UDPSampleNumber`
|
||||
- **Methods**:
|
||||
- `CloseSocket()` (void): Closes UDP socket.
|
||||
- `Read()` (UDPStreamPacket?): Receives one UDP packet and returns parsed `UDPStreamPacket`, or `null` on timeout/error.
|
||||
- **Purpose**: Manages UDP socket binding, multicast membership, and packet reception. Decodes incoming packets using `UDPRealtimeByteConverter` and maps data to configured channels.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Command Type**: All `RealtimeCommandBase` subclasses set `command.Type = CommandPacket.CommandType.Realtime`.
|
||||
- **Command Parameter Initialization**:
|
||||
- `StartRealtimeMode` and `GetRealtimeSamples` always initialize `command.Parameter` to a 1-byte array (even if unused).
|
||||
- `RetrieveSampleAverage` initializes `command.Parameter` to a 2-byte array.
|
||||
- `StreamConfigUDPSet` uses a 74-byte parameter array; `StreamConfigUDPGet` uses 65 bytes.
|
||||
- **Data Byte Order**:
|
||||
- Header fields (e.g., `TimeStamp`, `SampleNumber`, `SequenceNumber`) in `RealtimeStreamDecoder` are received in little-endian byte order and must be reversed for correct interpretation.
|
||||
- Data payload in `RealtimeStreamDecoder` is received in standard little-endian order (no reversal).
|
||||
- `UDPRealtimeByteConverter` reverses header bytes but not data bytes.
|
||||
- **Signed Conversion**:
|
||||
- `RetrieveSingleSample`: Converts unsigned >32768 to signed by subtracting 65536.
|
||||
- `UDPRealtimeByteConverter`: XORs data with `0x8000`.
|
||||
- `GetRealtimeSamplesSLICE2`: Adds `0x8000` after byte-swapping.
|
||||
- `GetRealtimeSamples`: Subtracts `0x8000` after byte-swapping.
|
||||
- `GetRealtimeSamplesSLICE6` and `GetRealtimeSamplesTSRAIR`: No offset adjustment (data is already signed or unsigned as appropriate).
|
||||
- **Channel Data Layout**:
|
||||
- `GetRealtimeSamples`: Interleaved data order per channel group (e.g., for 9 channels: 7,8,9,4,5,6,1,2,3).
|
||||
- `StreamReaderUDP`: Assumes 6 channels total (`numChannels = 6`) regardless of configured channel list; uses modulo arithmetic to map samples to channels.
|
||||
- **UDP Packet Format**:
|
||||
- `RealtimeStreamDecoder`: Header is 34 bytes (`ByteIndex.DataStart = 34`), with payload starting at byte 34.
|
||||
- `UDPRealtimeByteConverter`: Header is 40 bytes (`UDP_BYTE_INDEX.DATA_START = 40`), with payload starting at byte 40.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.ICommunication`**: Core communication interface (`ICommunication`, `CommandPacket`, `CommandReceiveAction`, `CommandStatus`).
|
||||
- **`DTS.Common.Enums.DASFactory`**: Enums and constants (`DFConstantsAndEnums.CommandStatus`, `ProtocolLimitedCommands`).
|
||||
- **`DTS.Common.Utilities`**: Helper utilities (`ArrayToString`).
|
||||
- **`System.Net`, `System.Net.Sockets`**: For `StreamReaderUDP` socket operations.
|
||||
- **`System.Collections.BitArray`**: Used in `RealtimeStreamDecoder` for channel mask parsing.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **`RealtimeCommandBase`** is inherited by all concrete command classes (`StartRealtimeMode`, `EndRealtimeMode`, `RetrieveSingleSample`, etc.).
|
||||
- **`IGetRealtimeSamples`** is implemented by `GetRealtimeSamples` and its subclasses (`GetRealtimeSamplesSLICE6`, `GetRealtimeSamplesSLICE2`, `GetRealtimeSamplesTSRAIR`).
|
||||
- **`StreamReaderUDP`** depends on `UDPRealtimeByteConverter` and `UDPStreamPacket`.
|
||||
- **`RealtimeStreamDecoder`** is a standalone decoder; its usage is inferred from context but not directly referenced in provided files.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **Channel Mask Interpretation in `StreamReaderUDP`**: The code assumes 6 channels (`numChannels = 6`) regardless of the `Channels` property, potentially misaligning data if fewer channels are configured.
|
||||
- **`StreamConfigUDPGet.ResponseToString` Bug**: The line `lines.Add(new List<string>() { $"Data Channel ID: {_timechannelid}" });` incorrectly logs `_timechannelid` instead of `_datachannelid`.
|
||||
- **`GetRealtimeSamples.ResponseToString` Bug**: The line `lines.Add(new List<string> { $"Sample number: {ResponseStatus}, Samples returned: {SampleNumber}, Time Stamp returned: {TimeStamp}, Sequence Number returned: {SequenceNumber}" });` uses `ResponseStatus` (undefined) instead of `SampleNumber` in the first placeholder.
|
||||
- **`UDPRealtimeByteConverter` Data Type Handling**: Only supports `ANALOG_DATA_FORMAT_1` (`0x21`); other types (e.g., `TIME_DATA_PTP`, `CGDP_TYPE`) result in `RtData = null`.
|
||||
- **`RealtimeStreamDecoder` Byte Order**: Header fields are reversed, but data payload is *not* reversed—this distinction is critical and explicitly documented in comments.
|
||||
- **`RetrieveSingleSample` Signed Conversion**: Uses `unsignedData[i] > 32768` to decide subtraction, which may misinterpret values exactly at 32768 (should be `>= 32768` for correct two’s complement).
|
||||
- **`StartRealtimeMode` Parameter Behavior**: Setting `SupportsMultipleSampleRealtime = false` clears the parameter array, but the constructor always initializes it to `new byte[1]`—only the setter can clear it after construction.
|
||||
- **`StreamReaderUDP` Timeout**: Socket timeout is hardcoded to 2000ms; no configurable option exists in the provided code.
|
||||
- **`UDPStreamPacket.TimeStamp`**: Always set to `0L` in `StreamReaderUDP.Read()`; the actual timestamp is stored in `PTPTimesec`/`PTPTimeNsec`.
|
||||
- **`UDPRealtimeByteConverter` Channel Mask**: Always assumes all 6 channels are present (`for (var i = 0; i < 6; i++)`), ignoring the `ChannelMask` field.
|
||||
Reference in New Issue
Block a user