248 lines
13 KiB
Markdown
248 lines
13 KiB
Markdown
|
|
---
|
||
|
|
source_files:
|
||
|
|
- Common/DTS.Common.ICommunication/IDASConnectedDevice.cs
|
||
|
|
- Common/DTS.Common.ICommunication/ICommunication.cs
|
||
|
|
- Common/DTS.Common.ICommunication/Communication.cs
|
||
|
|
generated_at: "2026-04-16T14:07:22.447976+00:00"
|
||
|
|
model: "zai-org/GLM-5-FP8"
|
||
|
|
schema_version: 1
|
||
|
|
sha256: "b573bb7d2f5d27d0"
|
||
|
|
---
|
||
|
|
|
||
|
|
# Documentation: DTS.Common.ICommunication
|
||
|
|
|
||
|
|
## 1. Purpose
|
||
|
|
|
||
|
|
This module provides the core communication infrastructure for interacting with DAS (Data Acquisition System) hardware devices. It defines the contract for connected devices via `IDASConnectedDevice`, encapsulates device metadata through `Communication_DASInfo`, and implements an asynchronous, callback-driven communication layer via the abstract `Communication<T>` class. The module handles connection lifecycle management, command execution with timeout handling, cancellation support, and protocol version negotiation for hardware commands.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 2. Public Interface
|
||
|
|
|
||
|
|
### IDASConnectedDevice (Interface)
|
||
|
|
**Namespace:** `DTS.DASLib.Communication`
|
||
|
|
|
||
|
|
Describes a device connected to a DAS (e.g., S6 connected to S6DB).
|
||
|
|
|
||
|
|
| Property | Type | Description |
|
||
|
|
|----------|------|-------------|
|
||
|
|
| `DeviceType` | `HardwareTypes` | The device type of the connected device |
|
||
|
|
| `Port` | `int` | The port on the DAS which the device is on (0-based) |
|
||
|
|
| `SpotOnPort` | `int` | The spot on the chain or port the device is on (0-based) |
|
||
|
|
| `PhysicalAddress` | `PhysicalAddress` | MAC Address or physical address |
|
||
|
|
| `IPAddress` | `string` | The IP address of the device |
|
||
|
|
| `SerialNumber` | `string` | The serial number of the device |
|
||
|
|
| `Location` | `string` | The location of the device |
|
||
|
|
| `Version` | `string` | The version of the device |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### CanceledException (Class)
|
||
|
|
**Namespace:** `DTS.Common.ICommunication`
|
||
|
|
|
||
|
|
A marker exception class extending `ApplicationException` to signal operation cancellation.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Communication_DASInfo (Class)
|
||
|
|
**Namespace:** `DTS.Common.ICommunication`
|
||
|
|
**Implements:** `ICommunication_DASInfo`
|
||
|
|
|
||
|
|
Encapsulates metadata about a DAS device.
|
||
|
|
|
||
|
|
**Properties:**
|
||
|
|
| Property | Type | Default | Description |
|
||
|
|
|----------|------|---------|-------------|
|
||
|
|
| `FirstUseDate` | `DateTime?` | `null` | Date of first use; `null` indicates hardware not used since calibration. Only valid when `IsFirstUseDateSupported` is `true` |
|
||
|
|
| `IsFirstUseDateSupported` | `bool` | `false` | Indicates hardware supports first use dates |
|
||
|
|
| `IsStreamingSupported` | `bool` | `false` | Indicates whether streaming is supported |
|
||
|
|
| `ConnectedDevices` | `IDASConnectedDevice[]` | empty array | Devices connected to the DAS (currently only used by SLICE6DB) |
|
||
|
|
| `SerialNumbers` | `string[]` | - | Array of serial numbers |
|
||
|
|
| `FirmwareVersions` | `string[]` | - | Array of firmware versions |
|
||
|
|
|
||
|
|
**Methods:**
|
||
|
|
- `void SetConnectedDevices(IDASConnectedDevice[] devices)` — Sets the `ConnectedDevices` array
|
||
|
|
- `string StackSerialNumber(int devid)` — Returns a stacked serial number string. Returns "N/A" if `SerialNumbers` is null/empty; returns `SerialNumbers[0]::SerialNumbers[devid]` if `devid` is non-zero and valid; otherwise returns `SerialNumbers[0]`
|
||
|
|
|
||
|
|
**Constructors:**
|
||
|
|
- `Communication_DASInfo()` — Default constructor
|
||
|
|
- `Communication_DASInfo(string[] serials, string[] fwnums)` — Constructs with cloned copies of serial and firmware arrays
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Communication\<T\> (Abstract Class)
|
||
|
|
**Namespace:** `DTS.Common.ICommunication`
|
||
|
|
**Implements:** `Interface.DASFactory.ICommunication`, `IDisposable`
|
||
|
|
**Constraint:** `where T : IConnection, new()`
|
||
|
|
|
||
|
|
Abstract base class for hardware communication, providing connection management, command execution, and cancellation support.
|
||
|
|
|
||
|
|
**Properties:**
|
||
|
|
| Property | Type | Description |
|
||
|
|
|----------|------|-------------|
|
||
|
|
| `ErrorInSetup` | `bool` | Indicates an error occurred during setup |
|
||
|
|
| `ConnectString` | `string` | Connection string from underlying socket |
|
||
|
|
| `Connected` | `bool` | Whether the socket is connected |
|
||
|
|
| `DASInfo` | `ICommunication_DASInfo` | DAS device information |
|
||
|
|
| `Transport` | `IConnection` | Underlying connection transport (setter throws `NotSupportedException`) |
|
||
|
|
| `ReceiveBufferSize` | `int` | Receive buffer size; default is 65536 (2^16) |
|
||
|
|
| `SerialNumber` | `string` | Device serial number |
|
||
|
|
| `FirmwareVersion` | `string` | Device firmware version; setter triggers `FirmwareVersionUpdated()` |
|
||
|
|
| `ProtocolVersion` | `byte` | Protocol version for command support checks |
|
||
|
|
| `MinimumProtocols` | `Dictionary<DFConstantsAndEnums.ProtocolLimitedCommands, byte>` | Maps commands to minimum required protocol versions |
|
||
|
|
| `FlushTimeoutMilliSec` | `int` | Timeout for flush operations; default is 5ms |
|
||
|
|
| `ExecuteIsBusy` | `bool` | Thread-safe flag indicating execution lock state |
|
||
|
|
| `CancelEvent` | `ManualResetEvent` | Event signaling cancellation has occurred |
|
||
|
|
|
||
|
|
**Events:**
|
||
|
|
- `EventHandler OnDisconnected` — Raised when the underlying socket disconnects
|
||
|
|
|
||
|
|
**Public Methods:**
|
||
|
|
- `int CompareTo(Interface.DASFactory.ICommunication dev)` — Compares connection strings (case-insensitive, ordinal)
|
||
|
|
- `int CompareTo(string conStr)` — Compares connection string to provided string
|
||
|
|
- `abstract void InitMinProto()` — Must be implemented to populate `MinimumProtocols`
|
||
|
|
- `bool IsCommandSupported(DFConstantsAndEnums.ProtocolLimitedCommands command)` — Returns `true` if `ProtocolVersion >= GetMinProto(command)`
|
||
|
|
- `byte GetMinProto(DFConstantsAndEnums.ProtocolLimitedCommands command)` — Returns minimum protocol version for command; returns `0xFF` if not found; throws `NotSupportedException` if `MinimumProtocols` is null
|
||
|
|
- `void Flush(int timeoutMs)` — Flushes the socket data buffer until empty or timeout
|
||
|
|
- `byte[] SyncExecute(byte[] byteData, int cbTimeout)` — **Throws `NotSupportedException`** (not implemented)
|
||
|
|
- `void Connect(string connectString, CommunicationCallback callback, object callbackObject, int callbackTimeout, string hostIPAddress)` — Initiates asynchronous connection
|
||
|
|
- `void Disconnect(bool reuseSocket, CommunicationCallback callback, object callbackObject, int callbackTimeout)` — Initiates asynchronous disconnect
|
||
|
|
- `void Cancel()` — Sets cancel state with 500ms sleep delay on clear
|
||
|
|
- `void ForceCancel()` — Sets cancel state with 250ms sleep delay on clear
|
||
|
|
- `bool IsCanceled()` — Returns current cancel state
|
||
|
|
- `void ClearCancel()` — Clears cancel state after sleeping
|
||
|
|
- `void Execute(byte[] byteData, CommunicationCallback cb, object cbObject, int cbTimeout)` — Sends data and processes responses asynchronously
|
||
|
|
- `void PseudoExecute(byte[] byteData, CommunicationCallback cb, object cbObject, int cbTimeout)` — For commands that only receive data (no send); does not clear buffer
|
||
|
|
- `void SetupReader()` — Initializes the asynchronous receive loop
|
||
|
|
- `void Close(int timeout)` — Empty implementation (no-op)
|
||
|
|
- `void Dispose()` — Implements `IDisposable`
|
||
|
|
|
||
|
|
**Protected Methods:**
|
||
|
|
- `void Lock()` — Empty implementation
|
||
|
|
- `void Release()` — Empty implementation
|
||
|
|
- `virtual void FirmwareVersionUpdated()` — Called when `FirmwareVersion` is set
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### CommunicationReport (Class)
|
||
|
|
**Namespace:** `DTS.Common.ICommunication`
|
||
|
|
**Implements:** `ICommunicationReport`
|
||
|
|
|
||
|
|
Carries the result of an asynchronous communication operation.
|
||
|
|
|
||
|
|
| Property | Type | Description |
|
||
|
|
|----------|------|-------------|
|
||
|
|
| `UserState` | `object` | User-provided state object |
|
||
|
|
| `Result` | `CommunicationResult` | Result enum value |
|
||
|
|
| `Data` | `byte[]` | Received data (for read operations) |
|
||
|
|
|
||
|
|
**Constructor:** `CommunicationReport(object state, CommunicationResult res)`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Communication\<T\>.ActionData (Abstract Nested Class)
|
||
|
|
Base class for tracking asynchronous operations with timeout handling.
|
||
|
|
|
||
|
|
| Property | Description |
|
||
|
|
|----------|-------------|
|
||
|
|
| `UserCallback` | `CommunicationCallback` delegate |
|
||
|
|
| `UserCallbackObject` | User-provided state object |
|
||
|
|
| `UserTimeout` | Timeout in milliseconds |
|
||
|
|
| `TimerExpired` | Whether the timeout timer fired |
|
||
|
|
|
||
|
|
**Methods:**
|
||
|
|
- `void StartTimer()` — Starts the timeout timer
|
||
|
|
- `void KillTimer()` — Stops and disposes the timer
|
||
|
|
- `bool ReportCanceled()` — Invokes callback with `CommunicationResult.Canceled`
|
||
|
|
- `abstract bool ReportFailure()` — Must implement failure reporting
|
||
|
|
- `abstract bool ReportSuccess()` — Must implement success reporting
|
||
|
|
- `abstract CommunicationResult GetTimeoutResult()` — Must return the timeout-specific result
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Communication\<T\>.ExecuteActionData (Nested Class)
|
||
|
|
Extends `ActionData` for execute operations.
|
||
|
|
|
||
|
|
**Additional Methods:**
|
||
|
|
- `bool ReportReadSuccess(byte[] data)` — Reports successful read with data
|
||
|
|
- `bool ReportReadTimeout()` — Reports read timeout
|
||
|
|
- `bool ReportReadDisconnected()` — Reports disconnection during read
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
### Communication\<T\>.PseudoAsyncResult (Nested Class)
|
||
|
|
Implements `IAsyncResult` for `PseudoExecute` operations.
|
||
|
|
|
||
|
|
| Property | Value |
|
||
|
|
|----------|-------|
|
||
|
|
| `IsCompleted` | Always `true` |
|
||
|
|
| `AsyncState` | The `ExecuteActionData` instance |
|
||
|
|
| `CompletedSynchronously` | Always `true` |
|
||
|
|
| `AsyncWaitHandle` | Throws `NotImplementedException` |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 3. Invariants
|
||
|
|
|
||
|
|
1. **Connection State Consistency**: `sock` is instantiated in the constructor and cannot be replaced via `Transport` setter (throws `NotSupportedException`).
|
||
|
|
|
||
|
|
2. **Execute Locking**: `ExecuteIsBusy` must be `false` before setting to `true`, and `true` before setting to `false`. Debug assertions enforce this—violations indicate re-entry or extra unlock bugs.
|
||
|
|
|
||
|
|
3. **Port/Spot Indexing**: `Port` and `SpotOnPort` on `IDASConnectedDevice` are 0-based indices.
|
||
|
|
|
||
|
|
4. **FirstUseDate Validity**: `FirstUseDate` is only meaningful when `IsFirstUseDateSupported` is `true`.
|
||
|
|
|
||
|
|
5. **MinimumProtocols Initialization**: `MinimumProtocols` must be populated by `InitMinProto()` before calling `GetMinProto()` or `IsCommandSupported()`, otherwise `NotSupportedException` is thrown.
|
||
|
|
|
||
|
|
6. **Callback Non-Null Assertion**: `ActionData` constructor asserts that the callback parameter is non-null.
|
||
|
|
|
||
|
|
7. **Thread ID Consistency**: In `ProcessReceivedData` and `SRRecvCallback`, if the thread ID changes during `WaitWithCondition.Wait`, the method exits early without processing.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 4. Dependencies
|
||
|
|
|
||
|
|
### This module depends on:
|
||
|
|
- `DTS.Common.Enums.Hardware` — `HardwareTypes` enum
|
||
|
|
- `DTS.Common.Enums.Communication` — `CommunicationResult`, `CommunicationConstantsAndEnums`
|
||
|
|
- `DTS.Common.Enums.DASFactory` — `DFConstantsAndEnums`
|
||
|
|
- `DTS.Common.Interface.Communication` — `ICommunication_DASInfo`, `CommunicationCallback` delegate
|
||
|
|
- `DTS.Common.Interface.Connection` — `IConnection`
|
||
|
|
- `DTS.Common.Classes.Connection` — (referenced but contents not in source)
|
||
|
|
- `DTS.Common.Utilities.Logging` — `APILogger`
|
||
|
|
- `DTS.Common.Utilities` — `SecureQueue<T>`
|
||
|
|
- `DTS.Common.Utils` — `WaitWithCondition`
|
||
|
|
- `System.Net.NetworkInformation` — `PhysicalAddress`
|
||
|
|
- `System.Net.Sockets` — `SocketException`
|
||
|
|
- `System.Threading` — `ManualResetEvent`, `Timer`, `Timeout`
|
||
|
|
- `System.Threading.Tasks` — `Task`
|
||
|
|
|
||
|
|
### What depends on this module:
|
||
|
|
- Implementations of `IConnection` (generic constraint `T`)
|
||
|
|
- Concrete DAS communication implementations that extend `Communication<T>`
|
||
|
|
- Consumers of `IDASConnectedDevice` for device enumeration
|
||
|
|
- Consumers of `ICommunication_DASInfo` for device metadata
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## 5. Gotchas
|
||
|
|
|
||
|
|
1. **SyncExecute Not Implemented**: Calling `SyncExecute()` throws `NotSupportedException`. Use `Execute()` with callbacks instead.
|
||
|
|
|
||
|
|
2. **Lock/Release Are No-ops**: `Lock()` and `Release()` methods have empty implementations. Any synchronization relying on these is not actually protected.
|
||
|
|
|
||
|
|
3. **Close() Does Nothing**: `Close(int timeout)` has an empty body and performs no cleanup.
|
||
|
|
|
||
|
|
4. **Cancel Sleep Delays**: `ClearCancel()` sleeps for either 500ms (after `Cancel()`) or 250ms (after `ForceCancel()`) before clearing the cancel state. This can introduce unexpected latency.
|
||
|
|
|
||
|
|
5. **Transport Setter Always Throws**: Setting `Transport` throws `NotSupportedException`—the socket cannot be replaced after construction.
|
||
|
|
|
||
|
|
6. **PseudoExecute Buffer Behavior**: Unlike `Execute()`, `PseudoExecute()` does not flush the buffer before operation and picks up from wherever the previous `PseudoExecute` left off.
|
||
|
|
|
||
|
|
7. **StackSerialNumber Edge Cases**: Returns "N/A" for empty/null `SerialNumbers`, but returns `SerialNumbers[0]` for `devid` values outside valid range (except 0). This may mask indexing errors.
|
||
|
|
|
||
|
|
8. **ActionData Timer Race**: The timer callback and `KillTimer()` both check `_timerFired` under a lock, but if the timer fires just before disposal, the callback will still execute.
|
||
|
|
|
||
|
|
9. **ReceiveCallback Disconnection Handling**: When `sock.EndReceive` returns 0 bytes, `_receiveCallbackRunning` is set to `false` and `OnDisconnected` is invoked, but the socket state is not explicitly cleaned up.
|
||
|
|
|
||
|
|
10. **Extra Communication Logging**: Conditional logging via `DFConstantsAndEnums.ExtraCommunicationLogging` may impact performance if enabled in production.
|