init
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/ChannelCodes/TextPastedArgs.cs
|
||||
- Common/DTS.Common/Classes/ChannelCodes/ChannelCode.cs
|
||||
generated_at: "2026-04-16T03:15:37.036883+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "936720bfac8d31e1"
|
||||
---
|
||||
|
||||
# ChannelCodes
|
||||
|
||||
## Documentation: ChannelCode Module
|
||||
|
||||
### 1. Purpose
|
||||
This module provides core data structures and command logic for handling channel codes in the DTS system. It defines the `ChannelCode` class (a concrete implementation of `IChannelCode`) that represents a channel with an identifier, code string, name, type (User/ISO), and status, and includes constructors for instantiation from database readers or other channel codes. It also defines `TextPastedArgs`, a data carrier for paste events, and `PasteCommandClass`, a `ICommand` implementation that intercepts text paste operations on UI text boxes, processes clipboard content, and publishes structured events (`TextPastedEvent`) when multi-field or structured paste occurs—while allowing simple single-field pastes to be handled by standard text change logic. The module supports UI binding, event-driven architecture (via Prism’s `IEventAggregator`), and ISO code coercion via a delegate.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `TextPastedArgs` class
|
||||
- **`TextPastedArgs(string text, IChannelCode channelCode, string id, object tag)`**
|
||||
Constructor. Initializes a new instance with the pasted `text`, the `channelCode` (used as `Sender`), a unique `id` (e.g., `"ChannelCode"`), and an arbitrary `tag` (typically from the UI element).
|
||||
- **`string Text { get; }`**
|
||||
The raw text content that was pasted (from clipboard).
|
||||
- **`object Sender { get; }`**
|
||||
The `IChannelCode` instance associated with the paste operation (set from the `channelCode` parameter).
|
||||
- **`string Id { get; }`**
|
||||
A string identifier for the paste operation (e.g., `"ChannelCode"`).
|
||||
- **`object Tag { get; }`**
|
||||
The `Tag` property of the UI element (e.g., `TextBox`) where the paste occurred.
|
||||
|
||||
#### `ChannelCode` class
|
||||
- **`ChannelCode(IDataReader reader, IReadOnlyDictionary<short, string> channelTypeLookup)`**
|
||||
Constructor. Populates the instance from an `IDataReader` by reading `"Id"`, `"Code"`, `"CodeTypeInt"`, and `"Name"` fields. Uses `channelTypeLookup` to map `CodeTypeInt` to `ChannelCodeType.User` or `.ISO`.
|
||||
- **`ChannelCode()`**
|
||||
Default constructor. Initializes `CodeType` to `ChannelCodeType.ISO`.
|
||||
- **`ChannelCode(IChannelCode channelCode)`**
|
||||
Copy constructor. Copies `Id`, `Code`, `Name`, and `CodeType` from another `IChannelCode`.
|
||||
- **`int Id { get; set; }`**
|
||||
The numeric identifier of the channel code. Initialized to `-1` by default.
|
||||
- **`UIItemStatus ItemStatus { get; set; }`**
|
||||
Status of the item (e.g., Added, Modified, Deleted). Initialized to `UIItemStatus.None`.
|
||||
- **`string Code { get; set; }`**
|
||||
The code string (e.g., `"A1"`). Protected backing field `_code`.
|
||||
- **`string Name { get; set; }`**
|
||||
The human-readable name. Protected backing field `_name`.
|
||||
- **`ChannelCodeType CodeType { get; set; }`**
|
||||
Enumerated type of the code (`User` or `ISO`).
|
||||
- **`const string PASTE_ID = "ChannelCode"`**
|
||||
A constant identifier used for paste operations (note: `PasteCommandClass` uses its own `Id` parameter, not this constant).
|
||||
- **`ICommand PasteCommand { get; set; } = null`**
|
||||
Command bound to paste operations (e.g., Ctrl+V). Defaults to `null` to avoid exceptions during UI construction.
|
||||
- **`override bool Equals(object obj)`**
|
||||
Compares two `ChannelCode` instances for equality based on `Code`, `Name`, and `CodeType` (case-sensitive string equality). Returns `false` if `obj` is not a `ChannelCode`.
|
||||
- **`~ChannelCode()`**
|
||||
Finalizer. Clears `_code` and `_name` to `null` to reduce memory footprint if the object is held longer than expected before cleanup.
|
||||
|
||||
#### `PasteCommandClass` class
|
||||
- **`PasteCommandClass(string id)`**
|
||||
Constructor. Stores the `id` in the `Id` property.
|
||||
- **`string Id { get; }`**
|
||||
Identifier for this paste command instance (e.g., `"ChannelCode"` or a unique control ID).
|
||||
- **`bool CanExecute(object parameter)`**
|
||||
Always returns `true`.
|
||||
- **`void Execute(object parameter)`**
|
||||
Executes the paste logic:
|
||||
- Validates `parameter` is a `TextBox`.
|
||||
- Resolves `IChannelCode` from `TextBox.DataContext`, supporting `ChannelCodeBuilder` and `ChannelNameBuilder` wrappers.
|
||||
- Reads clipboard text.
|
||||
- If clipboard text is a single line *without* delimiters (`,`, `;`, `\t`), publishes `PageModifiedEvent` and returns early (no structured paste).
|
||||
- Otherwise, clears `Code` and `Name` (via self-assignment to trigger property change), then publishes `TextPastedEvent` with a `TextPastedArgs` instance containing the clipboard text, channel code, `Id`, and `TextBox.Tag`.
|
||||
- Catches exceptions and publishes `PageErrorEvent` with the error message.
|
||||
- **`event EventHandler CanExecuteChanged`**
|
||||
Required by `ICommand`; not raised by this implementation.
|
||||
|
||||
#### `CoerceISOCodeDelegate` delegate
|
||||
- **`string CoerceISOCodeDelegate(string val, bool uniqueISOCodesRequired, bool useISOCodeFilterMapping)`**
|
||||
A delegate for custom logic to transform or validate an incoming ISO code string (`val`) before assignment, based on system constraints (`uniqueISOCodesRequired`, `useISOCodeFilterMapping`). Used to enforce ISO code uniqueness or apply filtering rules.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
- **`ChannelCode.Code` and `ChannelCode.Name` must be non-null strings** (though they may be empty). The `Code` and `Name` properties use `SetProperty`, implying change notifications are raised on assignment.
|
||||
- **`ChannelCode.Id` defaults to `-1`** and is only valid when set to a non-negative integer (typically from database).
|
||||
- **`ChannelCode.CodeType` defaults to `ChannelCodeType.ISO`** when constructed via the parameterless constructor.
|
||||
- **`TextPastedArgs.Text` is the raw clipboard content** at the time of paste, including any embedded delimiters.
|
||||
- **`TextPastedArgs.Sender` is always the resolved `IChannelCode` instance** (or `null` if resolution fails—though the `PasteCommandClass.Execute` method returns early if resolution fails, so `Sender` should never be `null` in published events).
|
||||
- **`PasteCommandClass.CanExecute` always returns `true`**, meaning paste is always enabled in the UI.
|
||||
- **Single-line, non-delimited paste bypasses `TextPastedEvent`** and only triggers `PageModifiedEvent`.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
- **Depends on:**
|
||||
- `DTS.Common.Events` (for `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent`, `PageModifiedArg`, `TextPastedArgs`, `PageErrorArg`).
|
||||
- `DTS.Common.Interface.Channels.ChannelCodes` (for `IChannelCode` interface).
|
||||
- `Prism.Events` (for `IEventAggregator`).
|
||||
- `Prism.Ioc` (for `ContainerLocator.Container`).
|
||||
- `DTS.Common.Base` (for `BasePropertyChanged`, enabling `INotifyPropertyChanged`).
|
||||
- `DTS.Common.Controls`, `DTS.Common.Enums`, `DTS.Common.Enums.Channels` (for `UIItemStatus`, `ChannelEnumsAndConstants`, `ChannelCodeType`).
|
||||
- `System.Data` (`IDataReader`), `System.Windows` (`TextBox`, `ICommand`), `System.Windows.Controls`.
|
||||
- `DTS.Common.Utility` (for `Utility.GetInt`, `Utility.GetString`, `Utility.GetShort`).
|
||||
|
||||
- **Depended on by:**
|
||||
- UI components (e.g., `TextBox` controls) that bind `PasteCommand` to `PasteCommandClass`.
|
||||
- Event handlers for `TextPastedEvent` (to process structured paste).
|
||||
- `ChannelCodeBuilder` and `ChannelNameBuilder` (implied by `PasteCommandClass.Execute` checking for their `DataContext`).
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
- **`PASTE_ID` constant is unused in `PasteCommandClass`**: The `PasteCommandClass` uses its own `Id` parameter (passed to its constructor) instead of the `ChannelCode.PASTE_ID` constant. This may cause confusion if expecting consistency.
|
||||
- **Self-assignment of `Code`/`Name` in `Execute`**: The lines `channelCode.Code = channelCode.Code;` are used to trigger property change notifications *without* modifying the value. This is a workaround to force UI updates before publishing `TextPastedEvent`.
|
||||
- **`PasteCommand` defaults to `null`**: To avoid exceptions during UI construction (per comment), `PasteCommand` is not initialized. UI must explicitly assign a `PasteCommandClass` instance.
|
||||
- **`Equals` ignores `Id`**: Two `ChannelCode` instances with different `Id` but identical `Code`, `Name`, and `CodeType` are considered equal. This may be intentional for business logic (e.g., comparing definitions) but could cause issues if `Id` is expected to be unique.
|
||||
- **`CanExecuteChanged` is never raised**: `PasteCommandClass` implements `ICommand` but does not raise `CanExecuteChanged`. UI frameworks relying on this event (e.g., WPF) may not update command availability dynamically.
|
||||
- **Clipboard access is synchronous**: `Clipboard.GetText()` is called directly in `Execute`, which may block the UI thread or throw if clipboard access is denied. Error handling only captures exceptions and publishes `PageErrorEvent`.
|
||||
- **`TextPastedArgs.Sender` is typed as `object`**: Though it is always an `IChannelCode`, the interface uses `object` instead of `IChannelCode`, requiring casting by consumers.
|
||||
116
enriched-qwen3-coder-next/Common/DTS.Common/Classes/ClockSync.md
Normal file
116
enriched-qwen3-coder-next/Common/DTS.Common/Classes/ClockSync.md
Normal file
@@ -0,0 +1,116 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/ClockSync/IClockSyncProfile.cs
|
||||
- Common/DTS.Common/Classes/ClockSync/ClockSyncProfile.cs
|
||||
- Common/DTS.Common/Classes/ClockSync/ClockSyncProfileConverter.cs
|
||||
- Common/DTS.Common/Classes/ClockSync/ClockSyncProfileCollection.cs
|
||||
generated_at: "2026-04-16T03:15:09.204079+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e412b56844d5af45"
|
||||
---
|
||||
|
||||
# ClockSync
|
||||
|
||||
## Documentation: Clock Sync Profile Module
|
||||
|
||||
### 1. Purpose
|
||||
This module defines and manages clock synchronization profiles for the DTS system, enabling configuration of different master clock input sources (e.g., PTP IEEE 1588, IRIG-B, GPS, 1PPS). It provides a singleton collection (`ClockSyncProfileCollection`) that loads profile definitions from an XML file (`ClockSyncProfiles.xml`), falling back to a default set if the file is missing. Profiles are represented by the `ClockSyncProfile` class, which implements the `IClockSyncProfile` interface and supports metadata-driven initialization from an enum (`ClockSyncProfileDefaults`). The module also includes a type converter (`ClockSyncProfileConverter`) for UI integration (e.g., property grids), ensuring only visible profiles are exposed and sorted by display order.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `IClockSyncProfile` (Interface)
|
||||
- **`int ProfileId { get; set; }`**
|
||||
Unique integer identifier for the profile.
|
||||
- **`string ProfileName { get; set; }`**
|
||||
Human-readable name of the profile (e.g., `"PTP IEEE 1588"`).
|
||||
- **`string ProfileDesc { get; set; }`**
|
||||
Description of the profile’s behavior or purpose.
|
||||
- **`int DisplayOrder { get; set; }`**
|
||||
Integer priority for ordering profiles in UI (lower values appear first).
|
||||
- **`bool Visible { get; set; }`**
|
||||
Flag indicating whether the profile should be shown in UI (e.g., property grids).
|
||||
- **`DASRestriction[] FilterRestrictions { get; set; }`**
|
||||
Array of restrictions (of type `DASRestriction`) applied to the profile; used to filter applicable DAS configurations.
|
||||
|
||||
#### `ClockSyncProfile` (Concrete Implementation)
|
||||
- **`ClockSyncProfile()`**
|
||||
Parameterless constructor for deserialization.
|
||||
- **`ClockSyncProfile(int profileId, string profileName, string profileDesc, int displayOrder, bool visible, DASRestriction[] filterRestrictions)`**
|
||||
Initializes a profile with explicit values via `Initialize()`.
|
||||
- **`ClockSyncProfile(ClockSyncProfileCollection.ClockSyncProfileDefaults defaults, DASRestriction[] restrictions)`**
|
||||
Initializes a profile by extracting metadata (name, description, order, visibility) from the `ClockSyncProfileDefaults` enum using reflection on `[Display]` and `[Browsable]` attributes, then calls `Initialize()`.
|
||||
- **`override string ToString()`**
|
||||
Returns `ProfileName`.
|
||||
|
||||
#### `ClockSyncProfileConverter` (Type Converter)
|
||||
- **`ClockSyncProfile[] Values { get; }`**
|
||||
Lazily-initialized array of *visible* profiles from the singleton collection, sorted by `DisplayOrder`. Thread-safe via `lock`.
|
||||
- **`override bool CanConvertFrom(...)`**
|
||||
Returns `true` if `sourceType == typeof(string)` (enables string-to-profile conversion by name).
|
||||
- **`override object ConvertFrom(...)`**
|
||||
Converts a string (profile name) to a `ClockSyncProfile` instance by matching `ProfileName` in `Values`. Returns `null` if no match.
|
||||
- **`override bool GetStandardValuesSupported(...)`**
|
||||
Returns `true` (indicates standard values are available).
|
||||
- **`override bool GetStandardValuesExclusive(...)`**
|
||||
Returns `true` (indicates only standard values are valid; no free-text input).
|
||||
- **`override StandardValuesCollection GetStandardValues(...)`**
|
||||
Returns a `StandardValuesCollection` containing *all* profiles from the singleton collection (including non-visible ones).
|
||||
|
||||
#### `ClockSyncProfileCollection` (Singleton Collection)
|
||||
- **`static ClockSyncProfileCollection GetCollection()`**
|
||||
Thread-safe singleton accessor. Loads profiles from `ClockSyncProfiles.xml` (creating it with defaults if missing).
|
||||
- **`ClockSyncProfile GetClockSyncProfile(string s)`**
|
||||
Returns the first profile matching `ProfileName == s`. If no match, returns the profile with `ProfileId == 0` (typically `"None"`). If neither exists, returns the first item in the collection.
|
||||
- **Constants**:
|
||||
- `NONE_NAME`, `PTPIEEE1588_NAME`, `IRIGB1PPS_NAME`, `GPS1PPS_NAME`, `IRIGB_NAME`, `_1PPS_NAME`
|
||||
Hardcoded string constants for profile names (e.g., `"PTP IEEE 1588"`).
|
||||
- **`ClockSyncProfileDefaults` Enum**:
|
||||
Defines default profile types with `[Display]` and `[Browsable]` attributes:
|
||||
- `None` (ID=0)
|
||||
- `PTPIEEE1588` (ID=1)
|
||||
- `IRIGB1PPS` (ID=2)
|
||||
- `GPS1PPS` (ID=4)
|
||||
- `IRIGB` (ID=8)
|
||||
- `_1PPS` (ID=16)
|
||||
Values use bit-shifted powers of two (e.g., `1 << 0`, `1 << 1`), but IDs are cast to `int` directly in `GetProfileInfo()`.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
- **Singleton Consistency**: `GetCollection()` always returns the same instance after first initialization.
|
||||
- **Profile Visibility Filtering**: `ClockSyncProfileConverter.Values` only includes profiles where `Visible == true`.
|
||||
- **Display Order Sorting**: `ClockSyncProfileConverter.Values` is sorted ascending by `DisplayOrder` (using `int.MaxValue` as fallback for missing order).
|
||||
- **Fallback Profile Selection**: `GetClockSyncProfile(string)` prioritizes exact name match, then `ProfileId == 0`, then first item.
|
||||
- **XML File Handling**: `ClockSyncProfiles.xml` is auto-generated with defaults if missing; existing file is never overwritten.
|
||||
- **Enum Metadata Dependency**: `ClockSyncProfile`’s enum-based constructor relies on `[Display]` and `[Browsable]` attributes being present on `ClockSyncProfileDefaults` members. Missing attributes cause runtime exceptions (e.g., `IndexOutOfRangeException` on `valueAttributes[0]`).
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
- **Internal Dependencies**:
|
||||
- `DTS.Common.Classes.DSP.DASRestriction` (used in `FilterRestrictions`).
|
||||
- `System.ComponentModel.DataAnnotations` (for `[Display]`, `[Browsable]`).
|
||||
- `System.Xml.Serialization` (for XML serialization/deserialization).
|
||||
- `System.Collections.ObjectModel.Collection<T>` (base class).
|
||||
- **External Dependencies**:
|
||||
- `ClockSyncProfileCollection` depends on `DASRestriction` type (defined elsewhere in `DTS.Common`).
|
||||
- `ClockSyncProfileConverter` depends on `ClockSyncProfileCollection` (singleton access).
|
||||
- **Depended Upon By**:
|
||||
- UI components (e.g., property grids) via `ClockSyncProfileConverter`.
|
||||
- Other modules requiring clock sync configuration (e.g., DSP configuration logic).
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
- **Enum ID Mismatch**: `ClockSyncProfileDefaults` uses bit-shifted values (e.g., `1 << 0 = 1`, `1 << 1 = 2`), but `GetProfileInfo()` casts the enum value directly to `int` for `profileId`. This means `IRIGB1PPS` has `ProfileId = 2`, not `1`. Ensure downstream logic does not assume sequential IDs.
|
||||
- **Attribute Dependency**: If `[Display]` or `[Browsable]` attributes are missing on a `ClockSyncProfileDefaults` member, `GetProfileInfo()` throws `IndexOutOfRangeException` (accessing `valueAttributes[0]` without null checks).
|
||||
- **Thread-Safe Lazy Initialization**: `ClockSyncProfileConverter.Values` uses double-checked locking but reinitializes `_values` only once per app domain. Subsequent modifications to the collection (e.g., via `GetCollection().Add(...)`) will *not* update `_values` until the converter is recreated.
|
||||
- **Non-Visible Profiles in StandardValues**: `GetStandardValues()` returns *all* profiles (including non-visible ones), while `Values` returns only visible ones. This inconsistency may confuse consumers expecting uniform filtering.
|
||||
- **Hardcoded XML Filename**: `CLOCKSYNC_PROFILE_XML_FILE = "ClockSyncProfiles.xml"` is hardcoded; no configuration override is provided.
|
||||
- **No Validation on `FilterRestrictions`**: `FilterRestrictions` is a `DASRestriction[]` with no null-checking or validation in constructors. Passing `null` may cause `NullReferenceException` downstream.
|
||||
- **No Profile Modification Support**: The collection is read-only after initialization (via `Collection<T>` base). Adding/removing profiles at runtime requires direct manipulation of `Items`, which bypasses validation.
|
||||
|
||||
None identified beyond these.
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Connection/NotConnectedException.cs
|
||||
generated_at: "2026-04-16T03:14:45.601567+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e5ae1dc6ac386b41"
|
||||
---
|
||||
|
||||
# Connection
|
||||
|
||||
1. **Purpose**
|
||||
This module defines a custom exception type, `NotConnectedException`, used to signal operations that are attempted on a connection object when no active connection exists. It serves as a domain-specific error mechanism within the `DTS.Common` library to distinguish connection-state errors from generic application failures, enabling callers to handle disconnection scenarios explicitly.
|
||||
|
||||
2. **Public Interface**
|
||||
- **`NotConnectedException(string message)`**
|
||||
Constructor that initializes a new instance of the exception with a specified error message. Inherits from `ApplicationException`. No additional properties or methods are defined beyond those inherited from `Exception`.
|
||||
|
||||
3. **Invariants**
|
||||
- The exception must always be instantiated with a non-null `message` parameter (enforced by the base `ApplicationException` constructor).
|
||||
- It is a *terminal* exception type—no subclasses or derived types are defined in the provided source.
|
||||
- No state beyond the exception message (inherited from `Exception.Message`) is stored or managed.
|
||||
|
||||
4. **Dependencies**
|
||||
- **Depends on**: `System` namespace (specifically `System.ApplicationException`).
|
||||
- **Used by**: Other modules in the `DTS.Common` namespace (and potentially downstream projects) that manage connection lifecycles and need to throw or catch connection-state errors.
|
||||
- No external project or library dependencies beyond the .NET Framework base class library.
|
||||
|
||||
5. **Gotchas**
|
||||
- The class inherits from `ApplicationException`, which is generally discouraged in modern .NET development in favor of `Exception` or more specific base types; this may reflect legacy design.
|
||||
- No inner exception overload is provided—callers cannot wrap another exception as the cause.
|
||||
- No additional context (e.g., connection ID, endpoint) is captured; callers must embed such details in the `message` string.
|
||||
- None identified from source alone.
|
||||
@@ -0,0 +1,166 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/DASFactory/DiagnosticMessageRow.cs
|
||||
- Common/DTS.Common/Classes/DASFactory/TCDiagnosticResult.cs
|
||||
- Common/DTS.Common/Classes/DASFactory/CanDiagnostics.cs
|
||||
- Common/DTS.Common/Classes/DASFactory/TemperatureConfig.cs
|
||||
- Common/DTS.Common/Classes/DASFactory/TMSNConfig.cs
|
||||
generated_at: "2026-04-16T03:17:33.495209+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "d29076d9515007bc"
|
||||
---
|
||||
|
||||
# Documentation: DASFactory Diagnostic & Configuration Classes
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides core data structures for representing and managing diagnostic results and configuration data within the DASFactory subsystem. It defines classes to encapsulate CAN bus diagnostics (`CanDiagnostics`), test channel diagnostics (`TCDiagnosticResult`), raw diagnostic message rows (`DiagnosticMessageRow`), and hardware-specific configuration objects for temperature logging (`TemperatureConfig`) and TMNS (Telemetry Network Subsystem) streaming (`TMNSConfig`). These classes serve as standardized data contracts between diagnostic test execution, result reporting, and configuration management layers—primarily supporting CAN BIST (Built-In Self-Test) and environmental monitoring, with extensibility for future hardware types.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `DiagnosticMessageRow`
|
||||
- **`DiagnosticMessageRow(string field, string value, string verdict)`**
|
||||
Constructor initializing all three properties. Used to hold a single diagnostic message row (e.g., from CAN BIST output).
|
||||
- **`Field` (string, get/set)**
|
||||
Name of the diagnostic field (e.g., "ErrorCounter", "StatusRegister").
|
||||
- **`Value` (string, get/set)**
|
||||
String representation of the diagnostic value.
|
||||
- **`Verdict` (string, get/set)**
|
||||
Pass/fail/other verdict for the field.
|
||||
- **`ToString()` (override)**
|
||||
Returns formatted string: `"Field: {Field}, Value: {Value}, Verdict: {Verdict}"`.
|
||||
|
||||
### `TCDiagnosticResult`
|
||||
- **`ChannelName` (string, get/set)**
|
||||
Human-readable name of the test channel.
|
||||
- **`ChannelIndex` (int, get/set)**
|
||||
Numeric index of the test channel.
|
||||
- **`CurrentReading` (double?, get/set)**
|
||||
Optional measured value (e.g., current in mA); `null` if not measured or unavailable.
|
||||
- **`Status` (DiagnosticStatus, get/set)**
|
||||
Overall diagnostic status (e.g., `Untested`, `Pass`, `Fail`).
|
||||
- **`ConnectionStatus` (ConnectionStatuses, get/set)**
|
||||
Connection state (e.g., `NotTested`, `Connected`, `Open`, `Short`).
|
||||
- **`Copy(ITCDiagnosticResult source)`**
|
||||
Copies all properties from `source` to this instance.
|
||||
|
||||
### `CanDiagnostics`
|
||||
- **`Active` (bool, get/set)**
|
||||
Whether this CAN channel is active.
|
||||
- **`ChannelIndex` (int, get/set)**
|
||||
CAN channel index (e.g., 0, 1).
|
||||
- **`Data` (int, get/set)**
|
||||
Raw data value from CAN diagnostics.
|
||||
- **`ErrorFrame` (int, get/set)**
|
||||
Count of error frames detected.
|
||||
- **`Load` (double, get/set)**
|
||||
Bus load percentage (0.0–100.0).
|
||||
- **`Overruns` (int, get/set)**
|
||||
Count of overrun errors.
|
||||
- **`LastUpdate` (DateTime, get/set)**
|
||||
Timestamp of last diagnostic update.
|
||||
- **`Errors` (int, read-only)**
|
||||
Computed error count: `Overruns` if `ErrorFrame == 0`, otherwise `1 + Overruns`.
|
||||
- **`ChannelName` (string, get/set)**
|
||||
Human-readable CAN channel name.
|
||||
- **`Copy(ICanDiagnosticResult source)`**
|
||||
Copies all properties from `source` to this instance.
|
||||
|
||||
### `TemperatureConfig`
|
||||
- **`LogEnable` (ushort, get/set)**
|
||||
Enable flag for logging (typically 0 or 1).
|
||||
- **`LogIntervalSec` (ushort, get/set)**
|
||||
Logging interval in seconds.
|
||||
- **`Channels` (ushort, get/set)**
|
||||
Bitfield representing enabled temperature/humidity channels (maps to `_channels` BitArray).
|
||||
- **`MCUTemp` (bool, get/set)**
|
||||
Enables/disables MCU temperature logging.
|
||||
- **`OnBoardHumidity` (bool, get/set)**
|
||||
Enables/disables on-board humidity logging.
|
||||
- **`EnvironmentalCh1`–`EnvironmentalCh4` (bool, get/set)**
|
||||
Enables/disables individual environmental channels (Ch1–Ch4).
|
||||
- **`ToUShortArray()` (ushort[])**
|
||||
Returns `[LogEnable, LogIntervalSec, Channels, Reserved]`.
|
||||
- **`TemperatureConfig(ushort[])`**
|
||||
Constructor initializing from a `ushort[]` (indices 0–2 used; index 3 ignored).
|
||||
- **`GetChannelsArray()` (int[])**
|
||||
Returns array of enabled channel indices (0–15) based on `_channels` BitArray.
|
||||
- **`GetMeasurementChannels()` (S6DBDiagnosticChannelList[])**
|
||||
Returns list of `S6DBDiagnosticChannelList` enum values corresponding to enabled channels.
|
||||
- **`GetChannelBitForDiagChannel(S6DBDiagnosticChannelList ch)` (TempLogChannelBits)**
|
||||
Maps a diagnostic channel enum to its corresponding `TempLogChannelBits` enum value; throws `NullReferenceException` if not found.
|
||||
|
||||
### `TMNSConfig`
|
||||
- **`TMNS_PCMSubFrameId` (uint, get/set)**
|
||||
PCM sub-frame ID.
|
||||
- **`TMNS_MsgId` (uint, get/set)**
|
||||
TMNS message ID.
|
||||
- **`TMNS_PCMMinorPerMajor` (uint, get/set)**
|
||||
PCM minor-per-major setting.
|
||||
- **`TMNS_TMATSPortNumber` (uint, get/set)**
|
||||
TMATs port number.
|
||||
- **`IENAUDP_PortNumber` (uint, get/set)**
|
||||
IENA UDP source port number.
|
||||
- **`TMNS5`, `TMNS6`, `TMNS7` (uint, get/set)**
|
||||
Reserved fields.
|
||||
- **`Fields` enum**
|
||||
Defines field indices: `TMNS_PCMSubFrameID`, `TMNS_MsgId`, `TMNS_PCMMinorPerMajor`, `TMNS_TMATSPortNumber`, `IENAUDP_PortNumber`, `TMNS5`, `TMNS6`, `TMNS7`.
|
||||
- **`TMNSConfig(uint[])`**
|
||||
Constructor from `uint[]` (length truncated to 8 if longer; shorter arrays padded with zeros).
|
||||
- **`TMNSConfig(string)`**
|
||||
Constructor from comma-separated string (e.g., `"(1,2,3)"`); parses to `uint[]`.
|
||||
- **`SetValue(Fields, uint)` / `GetValue(Fields)`**
|
||||
Set/get field value by enum.
|
||||
- **`ToUintArray()` (uint[])**
|
||||
Returns a copy of the internal `uint[]`.
|
||||
- **`ToCSVString()` (string)**
|
||||
Returns config as `(x,y,z,...)` string.
|
||||
- **`IsCh10(UDPStreamProfile)` (static bool)**
|
||||
Returns `true` if profile is a CH10 variant.
|
||||
- **`IsIENA(UDPStreamProfile)` (static bool)**
|
||||
Returns `true` if profile is `IENA_PTYPE_STREAM`.
|
||||
- **`IsTMNS(UDPStreamProfile)` (static bool)**
|
||||
Returns `true` if profile is `TMNS_PCM_STANDARD` or `TMNS_PCM_SUPERCOM`.
|
||||
- **`IsUART(UDPStreamProfile)` (static bool)**
|
||||
Returns `true` if profile is `UART_STREAM`.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`DiagnosticMessageRow`**: All three properties (`Field`, `Value`, `Verdict`) are non-null after construction (constructor assigns directly; no validation beyond constructor initialization).
|
||||
- **`TCDiagnosticResult`**: `ChannelIndex` defaults to `0`; `Status` defaults to `DiagnosticStatus.Untested`; `ConnectionStatus` defaults to `ConnectionStatuses.NotTested`; `CurrentReading` defaults to `null`.
|
||||
- **`CanDiagnostics`**: `ChannelIndex` defaults to `-1`; `Active` defaults to `false`; `Errors` is computed as `Overruns` if `ErrorFrame == 0`, else `1 + Overruns` (no negative values possible).
|
||||
- **`TemperatureConfig`**:
|
||||
- `_channels` BitArray is always 16 bits (initialized as `new BitArray(new[] { 0x00, 0x00 })`).
|
||||
- `Reserved` is a compile-time constant `0` and not stored in the config array.
|
||||
- `ToUShortArray()` always returns 4 elements: `[LogEnable, LogIntervalSec, Channels, 0]`.
|
||||
- `GetChannelBitForDiagChannel()` throws `NullReferenceException` for unmapped channels (no fallback).
|
||||
- **`TMNSConfig`**:
|
||||
- Internal `_values` array is always exactly 8 elements (size derived from `Fields` enum).
|
||||
- `ToUintArray()` returns a copy (not a reference).
|
||||
- `ToCSVString()` always includes parentheses and exactly 8 comma-separated values.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### This module depends on:
|
||||
- **`DTS.Common.Interface.DASFactory.Diagnostics`** (interfaces: `ITCDiagnosticResult`, `ICanDiagnosticResult`)
|
||||
- **`DTS.Common.Interface.Sensors.AnalogDiagnostics`** (used in `TCDiagnosticResult`)
|
||||
- **`DTS.Common.Enums.DASFactory`** (for `TempLogChannelBits`, `S6DBDiagnosticChannelList`, `DFConstantsAndEnums`)
|
||||
- **`DTS.Common.Enums`** (for `UDPStreamProfile` in `TMNSConfig`)
|
||||
- **`DTS.Common.Base`** (`BasePropertyChanged` base class for `TCDiagnosticResult` and `CanDiagnostics`)
|
||||
|
||||
### This module is depended upon by:
|
||||
- **Diagnostic test runners** (e.g., CAN BIST, temperature logging, TMNS configuration tools) that instantiate and populate these classes.
|
||||
- **UI/view layers** that bind to `TCDiagnosticResult`/`CanDiagnostics` via `INotifyPropertyChanged` (via `BasePropertyChanged`).
|
||||
- **Configuration serialization/deserialization** (e.g., saving/loading `TemperatureConfig` or `TMNSConfig` to/from storage).
|
||||
- **Diagnostic result aggregation** (e.g., combining `DiagnosticMessageRow` entries into test reports).
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`TemperatureConfig.GetChannelBitForDiagChannel()` throws `NullReferenceException`** for unmapped channels—despite the method name suggesting a safe lookup, it does not use `TryGetValue`. Callers must ensure the channel is supported.
|
||||
- **`TMNSConfig` string constructor is permissive**: Truncates or pads input to 8 fields; silently ignores non-parseable tokens (defaults to `0`).
|
||||
- **`TemperatureConfig.Channels` setter uses `BitConverter.ToUInt16`**: Assumes little-endian byte order (standard on .NET Core/.NET 5+ but platform-dependent in older frameworks).
|
||||
- **`CanDiagnostics.Errors` is computed, not stored**: Changes to `ErrorFrame` or `Overruns` trigger `OnPropertyChanged("Errors")`, but consumers must subscribe to `PropertyChanged` to react to this derived value.
|
||||
- **`DiagnosticMessageRow` stores everything as `string`**: No type safety or parsing; callers must handle numeric/string interpretation.
|
||||
- **`TMNSConfig` static methods (`IsCh10`, `IsIENA`, etc.) operate on `UDPStreamProfile` enum**: Behavior depends on complete enum coverage; missing cases in `switch` statements could cause incorrect results if new profiles are added.
|
||||
- **`TCDiagnosticResult` and `CanDiagnostics` implement `INotifyPropertyChanged` via `BasePropertyChanged`**: Property changes are observable, but `Copy()` does *not* raise `PropertyChanged` events for the copied values—consumers may need to manually trigger updates.
|
||||
181
enriched-qwen3-coder-next/Common/DTS.Common/Classes/DSP.md
Normal file
181
enriched-qwen3-coder-next/Common/DTS.Common/Classes/DSP.md
Normal file
@@ -0,0 +1,181 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/DSP/ScalerAttribute.cs
|
||||
- Common/DTS.Common/Classes/DSP/DASRestriction.cs
|
||||
- Common/DTS.Common/Classes/DSP/DSPFilterRestriction.cs
|
||||
- Common/DTS.Common/Classes/DSP/IStreamingFilterProfile.cs
|
||||
- Common/DTS.Common/Classes/DSP/StreamingFilterConverter.cs
|
||||
- Common/DTS.Common/Classes/DSP/DSPFilterConverter.cs
|
||||
- Common/DTS.Common/Classes/DSP/StreamingFilterProfile.cs
|
||||
- Common/DTS.Common/Classes/DSP/DSPFilterCollection.cs
|
||||
- Common/DTS.Common/Classes/DSP/StreamingFilterProfileCollection.cs
|
||||
- Common/DTS.Common/Classes/DSP/DSPFilterType.cs
|
||||
generated_at: "2026-04-16T03:17:48.073484+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "5b580a9c32ce9826"
|
||||
---
|
||||
|
||||
# DSP Module Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides data structures and utilities for configuring and managing digital signal processing (DSP) filters in the DTS system. It defines filter profiles (`StreamingFilterProfile`, `DSPFilterType`), their restrictions based on hardware type and protocol version (`DASRestriction`, `DSPFilterRestriction`), and collections (`StreamingFilterProfileCollection`, `DSPFilterCollection`) that load filter configurations from XML files. It also includes type converters (`StreamingFilterConverter`, `DSPFilterConverter`) for UI integration (e.g., property grids) and supports both legacy and ratio-based filter rate calculations. The module centralizes DSP filter metadata and logic, enabling consistent filter selection and configuration across the application.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Classes
|
||||
|
||||
- **`ScalerAttribute`**
|
||||
```csharp
|
||||
[AttributeUsage(AttributeTargets.Enum | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Field, AllowMultiple = false)]
|
||||
public class ScalerAttribute : Attribute
|
||||
```
|
||||
- **`Scaler`** (`double`): Stores a scaling factor (e.g., for computing filter cutoff frequencies from sample rates).
|
||||
- **Constructor `ScalerAttribute(double d)`**: Initializes the `Scaler` property with the provided value.
|
||||
|
||||
- **`DASRestriction`**
|
||||
```csharp
|
||||
public class DASRestriction
|
||||
```
|
||||
- **`DASType`** (`string`): Hardware type string (e.g., `"SLICE6_AIR"`). An empty string means *all* DAS types match.
|
||||
- **`ProtocolVersion`** (`int`): Minimum required protocol version. Values ≤ 0 mean *all* protocol versions match.
|
||||
- **Constructors**:
|
||||
- `DASRestriction()`: Sets `DASType = ""`, `ProtocolVersion = -1`.
|
||||
- `DASRestriction(string dasType, int protocolVersion)`: Initializes with specified values.
|
||||
|
||||
- **`DSPFilterRestriction`**
|
||||
```csharp
|
||||
public class DSPFilterRestriction
|
||||
```
|
||||
Identical structure and behavior to `DASRestriction` (same properties and constructors). *Note: No functional difference is evident in the source; likely a duplicate or legacy artifact.*
|
||||
|
||||
- **`StreamingFilterProfile`**
|
||||
```csharp
|
||||
public class StreamingFilterProfile : IStreamingFilterProfile
|
||||
```
|
||||
- **`Ratio`** (`double`): Scaling factor for computing filter cutoff frequency from sample rate (`fc = sps / Ratio`). `double.NaN` indicates no ratio-based calculation.
|
||||
- **`DisplayString`** (`string`), **`DescriptionString`** (`string`), **`EnumValue`** (`int`): Metadata for UI and firmware communication.
|
||||
- **`Restrictions`** (`DASRestriction[]`): Array of hardware/protocol restrictions.
|
||||
- **Constructors**:
|
||||
- `StreamingFilterProfile()`: Default.
|
||||
- `StreamingFilterProfile(StreamingFilterProfileCollection.DefaultProfiles profile, DASRestriction[] restrictions)`: Initializes from a `DefaultProfiles` enum value and restrictions.
|
||||
- `StreamingFilterProfile(string display, string description, int enumValue, double ratio, DASRestriction[] restrictions)`: Direct initialization.
|
||||
- **`GetDSPFilterRate(double sps, string hwType)`** (`double`): Returns the filter cutoff frequency (fc) for given sample rate (`sps`) and hardware type (`hwType`). Returns `double.NaN` if filtering is unsupported or restrictions not met.
|
||||
- For `SLICE6_AIR` with `sps ≥ 20480`, returns `double.NaN`.
|
||||
- For other cases, uses `DSPFilterType.Get6PButterWorthLegacyTable()` and `Ratio` to compute `fc = sps / Ratio` if `Ratio` is valid.
|
||||
- **`ToString()`**: Returns `DisplayString`.
|
||||
|
||||
- **`DSPFilterType`**
|
||||
```csharp
|
||||
public class DSPFilterType : IStreamingFilterProfile
|
||||
```
|
||||
- **`Ratio`**, **`EnumValue`**, **`DisplayString`**, **`DescriptionString`**, **`Restrictions`**: Same semantics as `StreamingFilterProfile`.
|
||||
- **Constructors**:
|
||||
- `DSPFilterType()`: Default.
|
||||
- `DSPFilterType(DSPFilterCollection.DSPFilterDefaults filter, DASRestriction[] restrictions)`: Initializes from `DSPFilterDefaults` enum value.
|
||||
- `DSPFilterType(int enumValue, string displayString, string descriptionString, double ratio, DASRestriction[] restrictions)`: Direct initialization.
|
||||
- **`GetDSPFilterRate(double sps, string hwType)`** (`double`): Returns `fc` for the legacy 6-pole Butterworth filter (`EnumValue == 13`). Returns `double.NaN` if `EnumValue ≠ 13`, restrictions not met, or hardware unsupported.
|
||||
- **Static Methods**:
|
||||
- **`Get6PButterWorthLegacyTable()`** (`Tuple<int, int>[]`): Returns the breakpoint table: `[(8000,1280), (5000,610), (2000,366), (1000,120), (500,120), (200,50), (80,15)]`.
|
||||
- **`GetLegacytDSPFilterRate(double sps, string hwType)`** (`double`): Returns `fc` for legacy Butterworth filter using the breakpoint table. Returns `double.NaN` for `SLICE6_AIR` with `sps ≥ 20480`.
|
||||
- **Constants**:
|
||||
- **`S6A_CAP`** (`int = 20480`): Sample rate threshold above which `SLICE6_AIR` falls back to analog filtering.
|
||||
|
||||
- **`StreamingFilterProfileCollection`**
|
||||
```csharp
|
||||
public class StreamingFilterProfileCollection : Collection<StreamingFilterProfile>
|
||||
```
|
||||
- **`GetCollection()`** (`static`): Singleton accessor. Loads from `"StreamingFilterProfiles.xml"` (creates default file if missing).
|
||||
- **`GetStreamingFilterProfile(string s)`** (`StreamingFilterProfile`): Returns the profile with matching `DisplayString`, or the default (`EnumValue == 13`), or the first item.
|
||||
- **`DefaultProfiles`** enum: Defines profiles with `ScalerAttribute` for `Ratio`:
|
||||
- `Default` (`13`): `Ratio = NaN` (legacy).
|
||||
- `Profile7` (`7`): `Ratio = 4`.
|
||||
- `Profile8` (`8`): `Ratio = 6.4`.
|
||||
- `Profile9` (`9`): `Ratio = 8`.
|
||||
- `Profile10` (`10`): `Ratio = 10`.
|
||||
- **`DEFAULT_VALUE`** (`int = 13`): Enum value for the default profile.
|
||||
|
||||
- **`DSPFilterCollection`**
|
||||
```csharp
|
||||
public class DSPFilterCollection : Collection<DSPFilterType>
|
||||
```
|
||||
- **`GetDSPFilterCollection()`** (`static`): Singleton accessor. Loads from `"DSPFilters.xml"` (creates default file if missing).
|
||||
- **`GetFilter(string s)`** (`DSPFilterType`): Returns filter with matching `DisplayString`, or `EnumValue == 0` (None), or first item.
|
||||
- **`DSPFilterDefaults`** enum: Defines filter types with `ScalerAttribute` (`Ratio = NaN` for all):
|
||||
- `None` (`0`).
|
||||
- `Butterworth` (`13`).
|
||||
- `FIR` (`14`).
|
||||
- **Constants**:
|
||||
- **`BUTTERWORTH`** (`int = 13`), **`FIR45TAP`** (`int = 14`), **`NONE`** (`int = 0`).
|
||||
|
||||
### Converters
|
||||
|
||||
- **`StreamingFilterConverter`**
|
||||
```csharp
|
||||
public class StreamingFilterConverter : ArrayConverter
|
||||
```
|
||||
- **`Values`** (`StreamingFilterProfile[]`): Cached array of profiles from `StreamingFilterProfileCollection`.
|
||||
- **`CanConvertFrom`**, **`ConvertFrom`**: Supports conversion from `string` (matches `DisplayString`).
|
||||
- **`GetStandardValuesSupported`**, **`GetStandardValuesExclusive`**, **`GetStandardValues`**: Provides standard values (entire collection) for property grids.
|
||||
|
||||
- **`DSPFilterConverter`**
|
||||
```csharp
|
||||
public class DSPFilterConverter : ArrayConverter
|
||||
```
|
||||
- **`Values`** (`DSPFilterType[]`): Cached array of filters from `DSPFilterCollection`.
|
||||
- **`CanConvertFrom`**, **`ConvertFrom`**: Supports conversion from `string` (matches `DisplayString`).
|
||||
- **`GetStandardValuesSupported`**, **`GetStandardValuesExclusive`**, **`GetStandardValues`**: Provides standard values (entire collection) for property grids.
|
||||
|
||||
### Interfaces
|
||||
|
||||
- **`IStreamingFilterProfile`**
|
||||
```csharp
|
||||
public interface IStreamingFilterProfile
|
||||
```
|
||||
Defines contract for filter profiles:
|
||||
- **`EnumValue`** (`int`), **`DisplayString`** (`string`), **`DescriptionString`** (`string`), **`Restrictions`** (`DASRestriction[]`), **`Ratio`** (`double`).
|
||||
- **`GetDSPFilterRate(double sps, string hwType)`** (`double`): Compute filter cutoff frequency.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Singleton Collections**: `StreamingFilterProfileCollection.GetCollection()` and `DSPFilterCollection.GetDSPFilterCollection()` are thread-safe singletons (using `lock` and lazy initialization). The XML files (`StreamingFilterProfiles.xml`, `DSPFilters.xml`) are created with defaults if missing.
|
||||
- **Restriction Matching**: A restriction matches if `DASType` is empty (any hardware) or equals `hwType`, and `ProtocolVersion ≤ 0` (any version) or `ProtocolVersion` matches the DAS’s version (exact match implied, though version comparison logic is not in this module).
|
||||
- **Filter Rate Calculation**:
|
||||
- `StreamingFilterProfile.GetDSPFilterRate` uses `Ratio` for ratio-based filters (`Ratio > 0`) and falls back to legacy table lookup (`DSPFilterType.GetLegacytDSPFilterRate`) only if `EnumValue == DEFAULT_VALUE` (13) and `Ratio = NaN`.
|
||||
- `DSPFilterType.GetDSPFilterRate` only supports the Butterworth filter (`EnumValue == 13`).
|
||||
- `SLICE6_AIR` with `sps ≥ 20480` is unsupported for digital filtering (returns `double.NaN`).
|
||||
- **Enum Values**: `DEFAULT_VALUE = 13` (for `StreamingFilterProfileCollection.DefaultProfiles.Default`) and `BUTTERWORTH = 13` (for `DSPFilterCollection.DSPFilterDefaults.Butterworth`) are hardcoded constants.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Internal Dependencies
|
||||
- **`DTS.Common.Enums.Hardware`**: Used for `HardwareTypes` (e.g., `SLICE6_AIR`, `SLICE6_AIR_BR`, `SLICE6_AIR_TC`).
|
||||
- **`System.ComponentModel.DataAnnotations`**: Used for `DisplayAttribute` (to extract `Name`/`Description` from enum fields).
|
||||
- **`System.Xml.Serialization`**: Used for XML serialization/deserialization of collections.
|
||||
- **`System.Collections.ObjectModel`**: Base for `Collection<T>`.
|
||||
|
||||
### External Dependencies
|
||||
- **XML Files**:
|
||||
- `StreamingFilterProfiles.xml`: Default location for streaming filter profiles.
|
||||
- `DSPFilters.xml`: Default location for DSP filter types.
|
||||
*(Both are created on first access if missing.)*
|
||||
- **UI Frameworks**: `StreamingFilterConverter` and `DSPFilterConverter` depend on `System.ComponentModel` (e.g., `ITypeDescriptorContext`, `StandardValuesCollection`) for property grid integration.
|
||||
|
||||
### Inferred Usage
|
||||
- `StreamingFilterProfileCollection` and `DSPFilterCollection` are used by converters and likely by UI components (e.g., dropdowns for filter selection).
|
||||
- `ScalerAttribute` is applied to enums in `StreamingFilterProfileCollection.DefaultProfiles` and `DSPFilterCollection.DSPFilterDefaults` to store scaling factors.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **Duplicate Classes**: `DASRestriction` and `DSPFilterRestriction` are identical in structure and behavior. The codebase does not clarify if they serve distinct purposes or are redundant.
|
||||
- **`Ratio = NaN` Semantics**: In `StreamingFilterProfile`, `Ratio = NaN` triggers legacy filter rate calculation (via `DSPFilterType.GetLegacytDSPFilterRate`), but only if `EnumValue == DEFAULT_VALUE` (13). This is not obvious from the method name or documentation.
|
||||
- **`GetDSPFilterRate` Inconsistency**:
|
||||
- `StreamingFilterProfile.GetDSPFilterRate` uses `Ratio` for ratio-based filters.
|
||||
- `DSPFilterType.GetDSPFilterRate` *only* supports Butterworth (`EnumValue == 13`) and ignores `Ratio`.
|
||||
This implies `StreamingFilterProfile` is for flexible profiles, while `DSPFilterType` is for legacy filter types.
|
||||
- **Hardware-Specific Logic**: `SLICE6_AIR` has a special case (`sps ≥ 20480` → `double.NaN`) in both `StreamingFilterProfile` and `DSPFilterType`. This is hardcoded and not configurable via XML.
|
||||
- **Protocol Version Matching**: `ProtocolVersion` is stored but never compared against a DAS’s actual version in the provided code. Matching logic is assumed but not implemented here.
|
||||
- **Case Sensitivity**: `GetFilter`/`GetStreamingFilterProfile` use `DisplayString == s` (case-sensitive). UI components may need to handle case normalization.
|
||||
- **Thread Safety**: Singletons use `lock` for initialization, but cached arrays (`Values` in converters) are not reloaded if XML files change at runtime.
|
||||
- **Typo**: Method `GetLegacytDSPFilterRate` (missing 'h' in "Legacy") and `S6A_CAP` (capitalization inconsistency with `SLICE6_AIR` enum values).
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/Commands/RelayCommand.cs
|
||||
generated_at: "2026-04-16T03:19:06.518329+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "33db5b96b73a6f00"
|
||||
---
|
||||
|
||||
# Commands
|
||||
|
||||
### 1. **Purpose**
|
||||
This module implements a concrete, reusable `ICommand`-based command class (`RelayCommand`) for WPF applications, enabling decoupling of UI actions (e.g., button clicks) from their execution logic. It supports optional conditional execution via a `CanExecute` predicate and integrates with WPF’s `CommandManager` to automatically re-evaluate command availability when UI state changes (e.g., focus or selection changes). Its role is to serve as a lightweight, standard command implementation for MVVM pattern adoption, avoiding boilerplate command classes per action.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
- **`RelayCommand(Action<object> execute)`**
|
||||
Constructor. Initializes the command with an execution delegate and no `CanExecute` predicate (i.e., always executable).
|
||||
- Throws `ArgumentNullException` if `execute` is `null`.
|
||||
|
||||
- **`RelayCommand(Action<object> execute, Predicate<object> canExecute)`**
|
||||
Constructor. Initializes the command with both execution and availability predicates.
|
||||
- Throws `ArgumentNullException` if `execute` is `null`.
|
||||
- `canExecute` may be `null`, in which case the command is always executable.
|
||||
|
||||
- **`bool CanExecute(object parameter)`**
|
||||
Implements `ICommand.CanExecute`. Returns `true` if `_canExecute` is `null` or if `_canExecute(parameter)` returns `true`; otherwise `false`.
|
||||
|
||||
- **`event EventHandler CanExecuteChanged`**
|
||||
Implements `ICommand.CanExecuteChanged`. Subscribes/unsubscribes to `CommandManager.RequerySuggested`, triggering WPF to re-query `CanExecute` when system events (e.g., keyboard/mouse input, focus changes) occur.
|
||||
|
||||
- **`void Execute(object parameter)`**
|
||||
Implements `ICommand.Execute`. Invokes `_execute(parameter)`. No validation or exception handling is performed; exceptions propagate to the caller.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
- `_execute` is **never `null`** after construction (enforced via `ArgumentNullException` in both constructors).
|
||||
- `_canExecute` may be `null`; in this case, `CanExecute` always returns `true`.
|
||||
- `CanExecuteChanged` events are **always** routed to `CommandManager.RequerySuggested`; no custom event storage is used.
|
||||
- `Execute` and `CanExecute` are called with the same `parameter` value provided by the command source (e.g., `Button.CommandParameter`).
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
- **Dependencies on external modules**:
|
||||
- `System` (for `Action<T>`, `Predicate<T>`, `ArgumentNullException`)
|
||||
- `System.Windows.Input` (for `ICommand`, `CommandManager`)
|
||||
- **Dependencies on other modules in the codebase**: None (no internal `using` statements beyond standard libraries).
|
||||
- **Depended upon by**: Presumably UI components (e.g., `Button`, `MenuItem`) in WPF views that bind commands via MVVM. Not visible in this file, but inferred from `ICommand` usage.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
- **No manual `CanExecuteChanged` raising**: Since `CanExecuteChanged` is wired to `CommandManager.RequerySuggested`, the command’s executability is only re-evaluated on `CommandManager`-triggered events (e.g., user input). If the command’s availability depends on non-UI state (e.g., background task completion), `CommandManager.InvalidateRequerySuggested()` must be called externally to force re-evaluation.
|
||||
- **No parameter validation**: `Execute` passes the `parameter` directly to `_execute` without null-checking or type validation. If `_execute` expects a specific type (e.g., `string`), passing an incompatible type will cause a runtime exception.
|
||||
- **Thread affinity**: `Execute` runs on the calling thread (typically the UI thread), but no thread-safety guarantees are provided. If invoked from a background thread, UI updates inside `_execute` will fail.
|
||||
- **Memory leak risk**: If subscribers to `CanExecuteChanged` are not properly disposed, the `CommandManager` may hold references indefinitely (though this is a general WPF pattern risk, not unique to this class).
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,65 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/Reports/ChannelGRMSSummary.cs
|
||||
generated_at: "2026-04-16T03:19:18.243942+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "8f994977a8bca5be"
|
||||
---
|
||||
|
||||
# Reports
|
||||
|
||||
### **1. Purpose**
|
||||
The `ChannelGRMSSummary` class serves as a data model for representing summary statistics of a single channel in a GRMS (G-RMS, or root-mean-square acceleration) analysis report. It encapsulates the channel’s name, its sampling rate, and the computed GRMS value, while implementing `INotifyPropertyChanged` to support data binding in UI frameworks (e.g., WPF). This class enables consistent, observable reporting of GRMS metrics across the DTS Viewer application.
|
||||
|
||||
---
|
||||
|
||||
### **2. Public Interface**
|
||||
|
||||
- **`ChannelName`** (`string`, read-write property)
|
||||
Gets or sets the human-readable name of the channel (e.g., `"Ch1-Accel"`). Used for identification in reports.
|
||||
|
||||
- **`SampleRate`** (`int`, read-write property)
|
||||
Gets or sets the sample rate (in Hz) used to acquire or process the channel data. Must be a non-negative integer (enforced by caller; not validated internally).
|
||||
|
||||
- **`GRMS`** (`double`, read-write property)
|
||||
Gets or sets the computed root-mean-square acceleration value (typically in *g* units) for the channel over a specified time interval.
|
||||
|
||||
- **`PropertyChanged`** (`event PropertyChangedEventHandler`)
|
||||
Event fired when a property value changes. Raised by `OnPropertyChanged`.
|
||||
|
||||
- **`OnPropertyChanged(string propertyName)`** (`void` method)
|
||||
Invokes the `PropertyChanged` event for the specified property name. Used to notify bound UI elements of updates.
|
||||
**Note:** Does *not* validate that `propertyName` corresponds to an actual property; caller must ensure correctness.
|
||||
|
||||
---
|
||||
|
||||
### **3. Invariants**
|
||||
- **No internal validation**: The class does not enforce constraints on `SampleRate` (e.g., positivity) or `GRMS` (e.g., non-negativity). Invalid values may be assigned silently.
|
||||
- **Property names must match exactly**: `OnPropertyChanged` relies on the caller passing the *exact* property name (e.g., `"GRMS"`, not `"grms"` or `"G rms"`); mismatches will cause silent UI update failures.
|
||||
- **Thread-safety**: The class provides no explicit thread-safety guarantees. `PropertyChanged` invocation is not atomic and may throw if subscribers are removed mid-invocation (though `?.` mitigates null reference exceptions).
|
||||
|
||||
---
|
||||
|
||||
### **4. Dependencies**
|
||||
|
||||
- **Depends on**:
|
||||
- `System.ComponentModel` (for `INotifyPropertyChanged` via `PropertyChangedEventHandler` and `PropertyChangedEventArgs`)
|
||||
- `DTS.Common.Interface` (for the `IChannelGRMSSummary` interface—implementation of which this class satisfies)
|
||||
|
||||
- **Implements**:
|
||||
- `IChannelGRMSSummary` (interface defined in `DTS.Common.Interface`; exact contract not visible in this file but assumed to declare `ChannelName`, `SampleRate`, `GRMS`, and `PropertyChanged`/`OnPropertyChanged` members)
|
||||
|
||||
- **Used by**:
|
||||
- Presumably UI components (e.g., WPF `DataGrid`, `ListView`) bound to GRMS summary reports.
|
||||
- Report generation or data aggregation logic that populates/updates channel summaries (e.g., a class computing GRMS from time-series data).
|
||||
|
||||
---
|
||||
|
||||
### **5. Gotchas**
|
||||
- **No null-check on `propertyName` in `OnPropertyChanged`**: Passing `null` will cause `PropertyChanged?.Invoke(...)` to throw a `NullReferenceException` (since `new PropertyChangedEventArgs(null)` is valid, but the event handler may not expect it).
|
||||
- **No validation on numeric properties**: `SampleRate` could be negative or zero; `GRMS` could be negative or `NaN`. Callers must ensure values are physically meaningful.
|
||||
- **Interface implementation is implicit**: The class does not explicitly declare `IChannelGRMSSummary` in its definition (e.g., `: IChannelGRMSSummary`), but the source comment implies it implements the interface. Verify the interface definition in `DTS.Common.Interface` for exact contract requirements (e.g., read-only vs. read-write properties).
|
||||
- **No documentation of units**: While `GRMS` is assumed to be in *g*, and `SampleRate` in Hz, the source provides no explicit unit annotations—rely on external documentation or conventions.
|
||||
|
||||
*None identified beyond the above.*
|
||||
@@ -0,0 +1,316 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestMetadata.cs
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestGraphs.cs
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestSetupMetadata.cs
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestRunMetadata.cs
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestSummary.cs
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestModule.cs
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestChannel.cs
|
||||
- Common/DTS.Common/Classes/DTS.Viewer/TestMetadata/TestMetadataList.cs
|
||||
generated_at: "2026-04-16T03:19:21.354792+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "2276bf4d72ccc406"
|
||||
---
|
||||
|
||||
# TestMetadata Module Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides data structures and parsing logic for loading, representing, and managing test metadata from XML-based `.dts` files in the DTS Viewer system. It defines core domain models (`TestMetadata`, `TestRunMetadata`, `TestSetupMetadata`, `TestModule`, `TestChannel`, `TestGraphs`, `TestSummary`) that encapsulate test configuration, hardware setup, channel definitions, and summary information. The `TestMetadataList` class is responsible for deserializing `.dts` XML files into these strongly-typed objects and constructing `TestSummary` instances for UI binding. This module serves as the foundational data layer for test data browsing, selection, and visualization components.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `TestMetadataList`
|
||||
|
||||
- **`Task<ObservableCollection<ITestSummary>> GetTestSummaryListAsync(IBaseViewModel parent, string path, string file, string pattern = "")`**
|
||||
Async wrapper for `GetTestSummaryList`. Returns a list of `ITestSummary` objects built from `.dts` files in the specified directory.
|
||||
|
||||
- **`ObservableCollection<ITestSummary> GetTestSummaryList(IBaseViewModel parent, string path, string file = "", string pattern = "")`**
|
||||
Loads `.dts` files (matching `pattern`, default `.dts`) from `path`, parses them into `ITestMetadata`, and returns a collection of `ITestSummary` objects. `parent` is used for command wiring in `TestSummary`.
|
||||
|
||||
- **`ObservableCollection<ITestSummary> GetTestSummaryList(string path, string file = "", string pattern = "")`**
|
||||
Overload of `GetTestSummaryList` without a `parent` parameter (used when `Parent` property in `TestSummary` is not required).
|
||||
|
||||
- **`List<ITestMetadata> GetTestMetadataList(XDocument xDoc, string path, string file)`**
|
||||
Parses an `XDocument` (representing a `.dts` XML file) into a list of `ITestMetadata` instances. Includes error handling, filtering for `TSRAIR_GO_TEST` when `RunTestVariables.IsTSRAIRGo` is true, and channel array pre-allocation.
|
||||
|
||||
### `TestMetadata` (implements `ITestMetadata`)
|
||||
|
||||
- **`ITestRunMetadata TestRun { get; set; }`**
|
||||
Contains test run-level metadata (e.g., test ID, description, modules, channels).
|
||||
|
||||
- **`ITestSetupMetadata TestSetup { get; set; }`**
|
||||
Contains test setup-level metadata (e.g., setup name, timestamp, graphs, calibration behavior).
|
||||
|
||||
### `TestRunMetadata` (implements `ITestRunMetadata`, `INotifyPropertyChanged`)
|
||||
|
||||
- **`string Name { get; set; }`**
|
||||
Logical test name (from XML `Id` attribute).
|
||||
|
||||
- **`string Id { get; set; }`**
|
||||
File name without extension (from XML `FilePath` attribute).
|
||||
|
||||
- **`string Description { get; set; }`**
|
||||
Test description.
|
||||
|
||||
- **`bool InlineSerializedData { get; set; }`**
|
||||
Indicates if raw data is embedded in the XML.
|
||||
|
||||
- **`string TestGuid { get; set; }`**
|
||||
Unique test identifier.
|
||||
|
||||
- **`int FaultFlags { get; set; }`**
|
||||
Bitmask of test fault conditions.
|
||||
|
||||
- **`string Software { get; set; }`**, **`string SoftwareVersion { get; set; }`**
|
||||
Software name and version used for acquisition.
|
||||
|
||||
- **`string DataType { get; set; }`**
|
||||
Type of data (e.g., "Acceleration", "Force").
|
||||
|
||||
- **`DateTime FileDate { get; set; }`**
|
||||
File system modification date.
|
||||
|
||||
- **`string FilePath { get; set; }`**
|
||||
Full path to the test data file.
|
||||
|
||||
- **`List<ITestModule> Modules { get; set; }`**
|
||||
List of acquisition modules used.
|
||||
|
||||
- **`List<ITestChannel> Channels { get; set; }`**
|
||||
List of physical channels.
|
||||
|
||||
- **`List<ITestChannel> CalculatedChannels { get; set; }`**
|
||||
List of derived channels.
|
||||
|
||||
- **`bool IsSelected { get; set; }`**
|
||||
UI selection state (raises `PropertyChanged`).
|
||||
|
||||
- **`event PropertyChangedEventHandler PropertyChanged`**
|
||||
Implements `INotifyPropertyChanged`.
|
||||
|
||||
### `TestSetupMetadata` (implements `ITestSetupMetadata`)
|
||||
|
||||
- **`string SetupName { get; set; }`**
|
||||
Name of the test setup configuration.
|
||||
|
||||
- **`DateTime TimeStamp { get; set; }`**
|
||||
Setup timestamp (fallback if module timestamps are invalid/zero).
|
||||
|
||||
- **`List<ITestGraphs> TestGraphs { get; set; }`**
|
||||
List of graph definitions.
|
||||
|
||||
- **`CalibrationBehaviors CalibrationBehavior { get; set; }`**
|
||||
Calibration strategy (e.g., `NonLinearIfAvailable`).
|
||||
|
||||
### `TestGraphs` (implements `ITestGraphs`)
|
||||
|
||||
- **`string Name { get; set; }`**
|
||||
Graph display name.
|
||||
|
||||
- **`string HardwareChannelName { get; set; }`**
|
||||
Hardware channel name associated with the graph.
|
||||
|
||||
- **`List<string> ChannelIds { get; set; }`**
|
||||
List of channel IDs included in the graph.
|
||||
|
||||
- **`List<ITestChannel> Channels { get; set; }`**
|
||||
*Note: Not populated during XML parsing; likely for runtime use.*
|
||||
|
||||
### `TestModule` (implements `ITestModule`, `INotifyPropertyChanged`)
|
||||
|
||||
- **`string SerialNumber { get; set; }`**, **`string BaseSerialNumber { get; set; }`**
|
||||
Module serial and base serial numbers.
|
||||
|
||||
- **`int Number { get; set; }`**, **`int NumberOfChannels { get; set; }`**
|
||||
Module number and channel count.
|
||||
|
||||
- **`int SampleRateHz { get; set; }`**, **`int UnsubsampledSampleRateHz { get; set; }`**
|
||||
Sample rates (post- and pre-subsampling).
|
||||
|
||||
- **`double RequestedPreTriggerSeconds { get; set; }`**, **`double PreTriggerSeconds { get; set; }`**, **`double RequestedPostTriggerSeconds { get; set; }`**, **`double PostTriggerSeconds { get; set; }`**
|
||||
Trigger timing parameters.
|
||||
|
||||
- **`int StartRecordTimestampSec { get; set; }`**, **`int StartRecordTimestampNanoSec { get; set; }`**, **`int TriggerTimestampSec { get; set; }`**, **`int TriggerTimestampNanoSec { get; set; }`**
|
||||
High-precision timestamps (PTP1588).
|
||||
|
||||
- **`List<ulong> TriggerSampleNumbers { get; set; }`**
|
||||
*Note: Always initialized as empty list; parsing logic returns empty list.*
|
||||
|
||||
- **`bool PTPMasterSync { get; set; }`**
|
||||
Indicates PTP synchronization status.
|
||||
|
||||
- **Tilt Sensor Angles (Pre/Post)**:
|
||||
`TiltSensorAxis{X,Y,Z}Degrees{Pre,Post}` — tilt sensor readings before/after test.
|
||||
|
||||
- **Temperature Readings (Pre/Post)**:
|
||||
`TemperatureLocation{1-4}{Pre,Post}` — temperature sensor readings.
|
||||
|
||||
- **`List<ITestChannel> Channels { get; set; }`**, **`List<ITestChannel> CalculatedChannels { get; set; }`**
|
||||
Channels associated with this module.
|
||||
|
||||
- **`bool IsSelected { get; set; }`**
|
||||
Selection state (raises `PropertyChanged`).
|
||||
|
||||
- **`event PropertyChangedEventHandler PropertyChanged`**
|
||||
Implements `INotifyPropertyChanged`.
|
||||
|
||||
### `TestChannel` (implements `ITestChannel`, `IBasePropertyChanged`, `ISerializable`)
|
||||
|
||||
- **`string Group { get; set; }`**, **`string SubGroup { get; set; }`**
|
||||
Logical grouping.
|
||||
|
||||
- **`bool IsGraphChannel { get; set; }`**, **`string GraphName { get; set; }`**
|
||||
Indicates if channel is used in a graph.
|
||||
|
||||
- **`string TestId { get; set; }`**, **`string TestSetupName { get; set; }`**, **`string ModuleSerialNumber { get; set; }`**
|
||||
Contextual identifiers.
|
||||
|
||||
- **`string SerialNumber { get; set; }`**, **`string ChannelId { get; set; }`**
|
||||
Channel serial and ID.
|
||||
|
||||
- **`string ChannelDisplayName { get; set; }`**, **`string ChannelDescriptionString { get; set; }`**
|
||||
Display name and description string.
|
||||
|
||||
- **`string ChannelName2 { get; set; }`**, **`string HardwareChannelName { get; set; }`**
|
||||
Alternative channel names.
|
||||
|
||||
- **`string ChannelType { get; set; }`**
|
||||
Channel type (e.g., "AnalogInput").
|
||||
|
||||
- **`bool IsCalculatedChannel { get; set; }`**
|
||||
Indicates if channel is derived.
|
||||
|
||||
- **`int Number { get; set; }`**, **`int ChannelNumber { get; set; }`**
|
||||
Channel numbers.
|
||||
|
||||
- **`double Sensitivity { get; set; }`**, **`string SensitivityUnits { get; set; }`**, **`double DesiredRange { get; set; }`**, **`double ActualMaxRangeEu { get; set; }`**, **`double ActualMinRangeEu { get; set; }`**, **`double ActualMaxRangeMv { get; set; }`**, **`double ActualMinRangeMv { get; set; }`**
|
||||
Calibration and range parameters.
|
||||
|
||||
- **`string Bridge { get; set; }`**, **`double BridgeResistanceOhms { get; set; }`**, **`double ZeroPoint { get; set; }`**
|
||||
Bridge configuration.
|
||||
|
||||
- **`DateTime Start { get; set; }`**
|
||||
Channel start time.
|
||||
|
||||
- **`string SoftwareFilter { get; set; }`**, **`bool ProportionalToExcitation { get; set; }`**, **`bool IsInverted { get; set; }`**, **`string LinearizationFormula { get; set; }`**, **`bool IsSubsampled { get; set; }`**
|
||||
Processing flags.
|
||||
|
||||
- **`int AbsoluteDisplayOrder { get; set; }`**
|
||||
Display order index.
|
||||
|
||||
- **`DateTime LastCalibrationDate { get; set; }`**
|
||||
Calibration date.
|
||||
|
||||
- **`string SensorId { get; set; }`**
|
||||
Sensor identifier.
|
||||
|
||||
- **`int OffsetToleranceLowMv { get; set; }`**, **`int OffsetToleranceHighMv { get; set; }`**, **`int DataFlag { get; set; }`**
|
||||
Tolerance and data quality flags.
|
||||
|
||||
- **`string ExcitationVoltage { get; set; }`**, **`string Eu { get; set; }`**, **`bool CalSignalEnabled { get; set; }`**, **`bool ShuntEnabled { get; set; }`**, **`bool VoltageInsertionCheckEnabled { get; set; }`**, **`bool RemoveOffset { get; set; }`**, **`string ZeroMethod { get; set; }`**, **`double ZeroAverageWindowBegin { get; set; }`**, **`double ZeroAverageWindowEnd { get; set; }`**
|
||||
Excitation, units, and zeroing configuration.
|
||||
|
||||
- **`int InitialEu { get; set; }`**, **`string InitialOffset { get; set; }`**
|
||||
Initial calibration values.
|
||||
|
||||
- **`double MeasuredShuntDeflectionMv { get; set; }`**, **`double TargetShuntDeflectionMv { get; set; }`**, **`double MeasuredExcitationVoltage { get; set; }`**, **`double FactoryExcitationVoltage { get; set; }`**
|
||||
Shunt calibration parameters.
|
||||
|
||||
- **`double TimeOfFirstSample { get; set; }`**, **`double Multiplier { get; set; }`**, **`double UserOffsetEu { get; set; }`**, **`int UnitConversion { get; set; }`**
|
||||
Timing, scaling, and unit conversion.
|
||||
|
||||
- **`bool AtCapacity { get; set; }`**, **`int CapacityOutputIsBasedOn { get; set; }`**
|
||||
Capacity-related flags.
|
||||
|
||||
- **`string SourceChannelNumber { get; set; }`**, **`string SourceModuleNumber { get; set; }`**, **`string SourceModuleSerialNumber { get; set; }`**, **`string Calculation { get; set; }`**
|
||||
For calculated channels: source and formula.
|
||||
|
||||
- **`string BinaryFileName { get; set; }`**, **`string BinaryFilePath { get; set; }`**
|
||||
Binary data file info.
|
||||
|
||||
- **`double Xmax { get; set; }`**, **`double Xmin { get; set; }`**
|
||||
X-axis range.
|
||||
|
||||
- **`int SequentialNumbers { get; set; }`**
|
||||
Sequential index.
|
||||
|
||||
- **`ITestSetupMetadata ParentTestSetup { get; set; }`**, **`ITestModule ParentModule { get; set; }`**, **`IBaseViewModel Parent { get; set; }`**
|
||||
Parent references.
|
||||
|
||||
- **`Color ChannelColor { get; set; }`**, **`string ErrorMessage { get; set; }`**, **`bool IsError { get; set; }`**, **`Color? ErrorColor { get; set; }`**
|
||||
UI state properties.
|
||||
|
||||
- **`bool IsLocked { get; set; }`**, **`bool CanLock { get; set; }`**, **`bool CanSelectChannel { get; set; }`**, **`bool IsExpanded { get; set; }`**, **`bool IsSelected { get; set; }`**
|
||||
Selection/locking state with side effects (e.g., updating graph view models).
|
||||
|
||||
- **`double MinADC { get; set; }`**, **`double MaxADC { get; set; }`**, **`double AveADC { get; set; }`**, **`double StdDevADC { get; set; }`**, **`double T0ADC { get; set; }`**
|
||||
ADC statistics.
|
||||
|
||||
- **`double MinMV { get; set; }`**, **`double MaxMV { get; set; }`**, **`double AveMV { get; set; }`**, **`double StdDevMV { get; set; }`**, **`double T0MV { get; set; }`**
|
||||
mV statistics.
|
||||
|
||||
- **`double MinEU { get; set; }`**, **`double MaxEU { get; set; }`**, **`double AveEU { get; set; }`**, **`double StdDevEU { get; set; }`**, **`double T0EU { get; set; }`**
|
||||
Engineering Unit statistics.
|
||||
|
||||
- **`double MinY { get; set; }`**, **`double MaxY { get; set; }`**, **`double AveY { get; set; }`**, **`double StdDevY { get; set; }`**, **`double T0Value { get; set; }`**
|
||||
Current unit statistics.
|
||||
|
||||
- **`string SetupEID { get; set; }`**, **`string DataCollectionEID { get; set; }`**
|
||||
EID (likely Event ID) at setup and collection time.
|
||||
|
||||
- **`void SetChannelDescriptionAndDisplayName(string channelDescription)`**
|
||||
Sets `ChannelDescriptionString` and `ChannelDisplayName`.
|
||||
|
||||
- **`ITestChannel Copy()`**
|
||||
Shallow copy via `MemberwiseClone()`.
|
||||
|
||||
- **`override string ToString()`**
|
||||
Returns `ChannelName2` if embedded test-specific; otherwise `ChannelDescriptionString`.
|
||||
|
||||
### `TestSummary` (implements `ITestSummary`, `INotifyPropertyChanged`)
|
||||
|
||||
- **`const string ROI_SUFFIX = @"_ROI Period"`**
|
||||
Suffix indicating ROI period data.
|
||||
|
||||
- **`string Id { get; set; }`**
|
||||
Unique ID: `TestRun.Id + ParseEventNumber(TestRun.FilePath)`.
|
||||
|
||||
- **`string SetupName { get; set; }`**, **`string Description { get; set; }`**, **`int ChannelCount { get; set; }`**, **`DateTime FileDate { get; set; }`**, **`DateTime TimeStamp { get; set; }`**, **`string DataType { get; set; }`**
|
||||
Summary metadata.
|
||||
|
||||
- **`bool IsSelected { get; set; }`**
|
||||
Selection state with side effects via `SelectionChanged()`.
|
||||
|
||||
- **`List<ITestGraphs> Graphs { get; set; }`**, **`List<ITestChannel> Channels { get; set; }`**, **`List<ITestChannel> CalculatedChannels { get; set; }`**
|
||||
References to metadata.
|
||||
|
||||
- **`IBaseViewModel Parent { get; set; }`**
|
||||
Parent view model (for command binding).
|
||||
|
||||
- **`CalibrationBehaviors CalibrationBehavior { get; set; } = CalibrationBehaviors.NonLinearIfAvailable`**
|
||||
Default calibration behavior.
|
||||
|
||||
- **`ITestMetadata TestMetadata { get; set; }`**
|
||||
Full metadata object.
|
||||
|
||||
- **`DelegateCommand IsSelectedCommand { get; }`**
|
||||
Command bound to `IsSelected` property.
|
||||
|
||||
- **`void SelectionChanged()`**
|
||||
Updates `Parent.SelectedTestSummaryList` and publishes via `IEventAggregator`.
|
||||
|
||||
- **`event PropertyChangedEventHandler PropertyChanged`**
|
||||
Implements `INotifyPropertyChanged`.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`TestMetadata`** must always have non-null `TestRun` and `TestSetup` properties after construction (defaults are created on parse failure).
|
||||
- **`TestSummary.Id`** is constructed as `TestRun.Id + ParseEventNumber(TestRun.FilePath)`. `ParseEventNumber` extracts the segment starting with `DTS.Common.Constants.EventNumber` from the file path.
|
||||
- **`TestSummary.TimeStamp`** is determined by `TestMetadataList.GetTimestamp()`:
|
||||
- Uses minimum PTP1588 timestamp from modules (trigger or start record).
|
||||
- Falls back to `TestSetup.TimeStamp` if module timestamps are invalid (e.g., zero, before 1990).
|
||||
- **`TestChannel.ChannelId`** defaults to `GetHashCode().ToString()` if the XML attribute is missing or `-1`.
|
||||
- **`TestChannel.HardwareChannelName`** is set to `Strings.Strings.Table_NA` for calculated channels (per comment `//
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/GroupTemplates/Constants.cs
|
||||
generated_at: "2026-04-16T03:15:43.815320+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "1a584874abe7fb97"
|
||||
---
|
||||
|
||||
# GroupTemplates
|
||||
|
||||
## 1. Purpose
|
||||
This module defines a集中 set of string constants used to identify non-ISO test object types and related metadata within the DTS (likely *Device Test System*) codebase. It exists to provide a single source of truth for hardcoded string literals associated with proprietary or non-standard test object channels, ensuring consistency and reducing the risk of typos or mismatches when referencing these special identifiers elsewhere in the system.
|
||||
|
||||
## 2. Public Interface
|
||||
The module exposes only a `static class` named `Constants` (no instance members). All members are `public const string` fields:
|
||||
|
||||
- `public const string NON_ISO_TESTOBJECT_CHANNEL_TYPE = "x_NonISOTestObjectType_x";`
|
||||
A constant string used as a channel type identifier for non-ISO test objects.
|
||||
|
||||
- `public const string NON_ISO_TESTOBJECT_NAME = "x_NonISOTestObjectName_x";`
|
||||
A constant string used as a name identifier for non-ISO test objects.
|
||||
|
||||
- `public const string NON_ISO_TESTOBJECT_CHANNEL_TYPE2 = "NONISO_x_";`
|
||||
A second, distinct constant string used as a channel type identifier—likely for a different variant or legacy path for non-ISO test objects.
|
||||
|
||||
## 3. Invariants
|
||||
- All constant values are compile-time literals and cannot be modified at runtime.
|
||||
- The values `"x_NonISOTestObjectType_x"`, `"x_NonISOTestObjectName_x"`, and `"NONISO_x_"` are *exact* and case-sensitive; any usage must match them precisely.
|
||||
- No validation or runtime checks are performed by this module itself—conformance is the responsibility of consumers.
|
||||
|
||||
## 4. Dependencies
|
||||
- **No external dependencies**: This file contains no `using` directives and references no other types or assemblies.
|
||||
- **Consumers**: Based on naming and structure, this module is intended to be referenced by other modules in the `DTS.Common` assembly (or potentially other assemblies referencing it), particularly those handling test object creation, routing, or serialization logic where non-ISO types must be distinguished from standard ISO-compliant ones.
|
||||
|
||||
## 5. Gotchas
|
||||
- The suffix `_x` in the first two constants (`NON_ISO_TESTOBJECT_CHANNEL_TYPE`, `NON_ISO_TESTOBJECT_NAME`) appears intentional but unusual—likely a marker for "extended" or "custom" (non-standard) types. Developers should not assume `_x` is a generic placeholder; it is part of the literal value.
|
||||
- `NON_ISO_TESTOBJECT_CHANNEL_TYPE2` has no trailing underscore in its value (`"NONISO_x_"`), unlike the others. This suggests it may be used in a different context (e.g., as a prefix rather than a full identifier), and mixing usage could lead to mismatches.
|
||||
- No documentation comments (XML doc) are present in the source, so the semantic distinction between `NON_ISO_TESTOBJECT_CHANNEL_TYPE` and `NON_ISO_TESTOBJECT_CHANNEL_TYPE2` is not self-evident from this file alone.
|
||||
- None identified from source alone.
|
||||
199
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Groups.md
Normal file
199
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Groups.md
Normal file
@@ -0,0 +1,199 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Groups/GroupGRPImportError.cs
|
||||
- Common/DTS.Common/Classes/Groups/GroupGRPImportGroup.cs
|
||||
- Common/DTS.Common/Classes/Groups/GroupHardwareDbRecord.cs
|
||||
- Common/DTS.Common/Classes/Groups/TestSetupGroupRecord.cs
|
||||
- Common/DTS.Common/Classes/Groups/GroupDbRecord.cs
|
||||
- Common/DTS.Common/Classes/Groups/GroupGRPImportChannel.cs
|
||||
- Common/DTS.Common/Classes/Groups/ChannelDbRecord.cs
|
||||
- Common/DTS.Common/Classes/Groups/GroupHelper.cs
|
||||
generated_at: "2026-04-16T03:16:28.845582+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "b79a1cdde998f5b5"
|
||||
---
|
||||
|
||||
# Documentation: Groups Module
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides data structures and helper utilities for representing, importing, and managing group-based test configurations—specifically those sourced from `.GRP` files (TDC format)—and their persistence in the database. It defines import-time models (`GroupGRPImportGroup`, `GroupGRPImportChannel`, `GroupGRPImportError`) for parsing and validating `.GRP` files, database record models (`GroupDbRecord`, `GroupHardwareDbRecord`, `TestSetupGroupRecord`, `ChannelDbRecord`) for ORM-style data access, and a static `GroupHelper` class to cache and manage cross-referenced metadata (e.g., static group names, DAS IDs, channel-group mappings) during runtime. The module serves as the canonical data model layer for group-centric test setups in the DTS system.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `GroupGRPImportError`
|
||||
|
||||
- **`Errors` enum**: Defines all possible error codes during `.GRP` file import:
|
||||
- `FileEmpty`, `InvalidISOCodeInput`, `InvalidFullScaleInput`, `InvalidSensorInput`, `InvalidInvertInput`, `SensorNotFound`, `InvalidInputMode`, `InvalidDefaultValue`, `InvalidActiveValue`, `InvalidFireMode`, `InvalidDelay`, `InvalidLimitDuration`, `InvalidDuration`, `InvalidCurrent`
|
||||
- **Properties**:
|
||||
- `Errors ErrorCode { get; set; }`: The specific error encountered.
|
||||
- `string File { get; set; }`: Path or name of the `.GRP` file where the error occurred.
|
||||
- `int Line { get; set; }`: Line number in the file where the error occurred.
|
||||
- `string ExtraInfo { get; set; }`: Human-readable error details.
|
||||
- **`override string ToString()`**: Returns `ExtraInfo`.
|
||||
|
||||
### `GroupGRPImportGroup`
|
||||
|
||||
- **Properties**:
|
||||
- `bool Included { get; set; } = true`: Whether the group is included in the current import operation.
|
||||
- `bool Overwrite { get; set; } = true`: Whether existing group data should be overwritten.
|
||||
- `string GroupName { get; set; }`: Name of the group.
|
||||
- `string GroupTags { get; set; }`: Tags associated with the group.
|
||||
- `string ImportingUserTags { get; set; }`: User-provided tags during import.
|
||||
- `string SourceFile { get; set; }`: Path to the source `.GRP` file.
|
||||
- `GroupGRPImportChannel[] Channels { get; set; } = { }`: Array of imported channels.
|
||||
- `GroupGRPImportError[] GroupErrors { get; set; } = null`: Array of errors encountered during import of the entire group.
|
||||
- `bool GroupNameHasError { get; set; }`: UI hint indicating if the group name field has an error (used for visual feedback).
|
||||
|
||||
### `GroupHardwareDbRecord`
|
||||
|
||||
- **Implements**: `IGroupHardwareDbRecord`
|
||||
- **Properties**:
|
||||
- `int Id { get; set; }`: Primary key (database ID).
|
||||
- `int GroupId { get; set; }`: Foreign key to `Group` table.
|
||||
- `int DASId { get; set; }`: Foreign key to DAS (Data Acquisition System) record.
|
||||
- `string SerialNumber { get; set; }`: Serial number of hardware associated with the group.
|
||||
- **Constructors**:
|
||||
- `GroupHardwareDbRecord()`: Default constructor.
|
||||
- `GroupHardwareDbRecord(IGroupHardwareDbRecord copy)`: Copy constructor.
|
||||
- `GroupHardwareDbRecord(IDataReader reader)`: Populates from database reader.
|
||||
|
||||
### `TestSetupGroupRecord`
|
||||
|
||||
- **Implements**: `ITestSetupGroupRecord`
|
||||
- **Properties**:
|
||||
- `int GroupId { get; set; }`: Foreign key to group.
|
||||
- `int DisplayOrder { get; set; }`: Order in which the group appears in a test setup UI.
|
||||
- `string Position { get; set; }`: ISO 13499 position field.
|
||||
- `string TestObjectType { get; set; }`: ISO 13499 test object field.
|
||||
- `int TestSetupId { get; set; }`: Foreign key to test setup.
|
||||
- **Constructors**:
|
||||
- `TestSetupGroupRecord()`: Default constructor.
|
||||
- `TestSetupGroupRecord(IDataReader reader)`: Populates from database reader.
|
||||
- `TestSetupGroupRecord(ITestSetupGroupRecord copy)`: Copy constructor.
|
||||
|
||||
### `GroupDbRecord`
|
||||
|
||||
- **Implements**: `IGroupDbRecord`
|
||||
- **Properties**:
|
||||
- `int Id { get; set; }`: Primary key (database ID).
|
||||
- `string SerialNumber { get; set; }`: Serial number (used as group identifier).
|
||||
- `string Picture { get; set; }`: Path or identifier for group image.
|
||||
- `string DisplayName { get; set; }`: Human-readable name.
|
||||
- `string Description { get; set; }`: Group description.
|
||||
- `bool Embedded { get; set; }`: Whether the group is embedded (system-managed).
|
||||
- `DateTime LastModified { get; set; }`: Timestamp of last modification.
|
||||
- `string LastModifiedBy { get; set; }`: User who last modified the group.
|
||||
- `int? StaticGroupId { get; set; }`: Reference to static group ID if applicable.
|
||||
- `string ExtraProperties { get; set; }`: Serialized JSON of additional properties.
|
||||
- **Constructors**:
|
||||
- `GroupDbRecord()`: Default constructor.
|
||||
- `GroupDbRecord(IGroupDbRecord copy)`: Copy constructor.
|
||||
- `GroupDbRecord(IGroup copy, List<KeyValuePair<string, string>> extraProperties)`: Converts from domain `IGroup` model.
|
||||
- `GroupDbRecord(IDataReader reader)`: Populates from database reader.
|
||||
|
||||
### `GroupGRPImportChannel`
|
||||
|
||||
- **Constants**:
|
||||
- `SerialNumberField = 0`, `DisplayNameField = 1`, `ISOCodeField = 2`, `InvertField = 3`, `CapacityField = 4`, `InputModeField = 5`, `DefaultValueField = 6`, `ActiveValueField = 7`, `FireModeField = 8`, `DelayField = 9`, `LimitDurationField = 10`, `DurationField = 11`, `CurrentField = 12`: Field indices for parsing `.GRP` files.
|
||||
- **Properties**:
|
||||
- `string SensorSerialNumber { get; set; }`: Serial number of the sensor.
|
||||
- `string DisplayName { get; set; }`: Channel display name.
|
||||
- `string ISOCode { get; set; }`: ISO-compliant channel code.
|
||||
- `bool Invert { get; set; }`: Whether the channel signal is inverted.
|
||||
- `double FullScale { get; set; }`: Full-scale value (e.g., for analog channels).
|
||||
- `InputModes? InputMode { get; set; } = null`: Input mode (see enum below).
|
||||
- `FireModes? FireMode { get; set; } = null`: Fire mode (see enum below).
|
||||
- `double? DefaultValue { get; set; } = null`: Default value (e.g., for analog channels).
|
||||
- `double? ActiveValue { get; set; } = null`: Active value (e.g., trigger threshold).
|
||||
- `double? Delay { get; set; } = null`: Delay before firing (seconds).
|
||||
- `bool? LimitDuration { get; set; } = null`: Whether duration is limited.
|
||||
- `double? Duration { get; set; } = null`: Duration of fire pulse (seconds).
|
||||
- `double? Current { get; set; } = null`: Current limit for squib firing.
|
||||
- `GroupGRPImportError Error { get; set; } = null`: Channel-specific import error.
|
||||
- `GroupGRPImportGroup ParentGroup { get; set; }`: Parent group reference.
|
||||
- `string GroupName { get; }`: Derived from `ParentGroup.GroupName`; returns `"---"` if no parent.
|
||||
- **Nested Enums**:
|
||||
- `InputModes`: `na`, `TLH`, `THL`, `CCNO`, `CCNC`
|
||||
- `FireModes`: `na`, `CD`, `CC`
|
||||
- **Constants**:
|
||||
- `DefaultInputMode = InputModes.CCNO`
|
||||
- `DefaultFireMode = FireModes.CD`
|
||||
- `DefaultDefaultValue = 0.0`, `DefaultActiveValue = 1.0`, `DefaultDelay = 0.00`, `DefaultLimitDuration = true`, `DefaultDuration = 10.0`, `DefaultCurrent = 1.5`
|
||||
- **Methods**:
|
||||
- `void GroupNameInvalidate()`: Forces UI refresh for `GroupName` binding.
|
||||
|
||||
### `ChannelDbRecord`
|
||||
|
||||
- **Implements**: `IChannelDbRecord`
|
||||
- **Properties**:
|
||||
- `long Id { get; set; }`: Primary key (database ID).
|
||||
- `int GroupId { get; set; }`: Foreign key to group.
|
||||
- `string IsoCode { get; set; }`: ISO channel code.
|
||||
- `string IsoChannelName { get; set; }`: ISO-compliant channel name.
|
||||
- `string UserCode { get; set; }`: User-defined channel code.
|
||||
- `string UserChannelName { get; set; }`: User-defined channel name.
|
||||
- `int DASId { get; set; }`: Foreign key to DAS.
|
||||
- `int DASChannelIndex { get; set; }`: Channel index on the DAS.
|
||||
- `int GroupChannelOrder { get; set; }`: Order within the group.
|
||||
- `int TestSetupOrder { get; set; }`: Order within a test setup.
|
||||
- `int SensorId { get; set; }`: Foreign key to sensor.
|
||||
- `bool Disabled { get; set; }`: Whether channel is disabled.
|
||||
- `bool IsDisabled { get; set; }`: Backward-compatible alias for `Disabled`.
|
||||
- `DateTime LastModified { get; set; }`: Timestamp of last modification.
|
||||
- `string LastModifiedBy { get; set; }`: User who last modified the channel.
|
||||
- **Constructors**:
|
||||
- `ChannelDbRecord()`: Default constructor.
|
||||
- `ChannelDbRecord(IChannelDbRecord copy)`: Copy constructor.
|
||||
- `ChannelDbRecord(IDataReader reader)`: Populates from database reader.
|
||||
|
||||
### `GroupHelper`
|
||||
|
||||
- **Static utility class** (abstract, non-instantiable).
|
||||
- **Methods**:
|
||||
- `ClearStaticGroupNames()`, `SetStaticGroupName(int id, string name)`, `GetStaticGroupName(int id)`: Manage mapping of static group IDs to names.
|
||||
- `ClearEmbeddedGroupIdList()`, `SetEmbeddedGroupId(int id)`, `IsGroupEmbedded(int id)`: Manage list of embedded group IDs.
|
||||
- `ClearTestSetupGroupIds()`, `SetTestSetupGroupId(int groupId, int testSetupId)`, `GetTestSetupGroupId(int groupId)`: Map group IDs to test setup IDs.
|
||||
- `ClearGroupChannelIds()`, `AddGroupChannelId(int sensorId, int groupId)`, `GetGroupIdsFromChannels(int sensorId)`: Map sensor IDs to associated group IDs.
|
||||
- `ClearDASIds()`, `SetDASId(string serialNumber, int dasId)`, `GetDASId(string serialNumber)`: Map DAS serial numbers to database IDs.
|
||||
- `ClearBaseModuleChannelIndexList()`, `SetBaseModuleChannelIndexList(...)`, `GetChannelIndexes(...)`: Manage channel index mappings for base/module serial number pairs.
|
||||
- `ClearDASIdChannelIndexGroupIdList()`, `SetDASIdChannelIndexGroupIdList(...)`, `GetGroupIds(...)`: Map DAS ID + channel index → group ID.
|
||||
- `ClearTestSetupHardwareIds()`, `AddTestSetupHardwareId(int dasId, int testSetupId)`, `GetTestSetupHardwareIds(int DASId)`: Map DAS IDs to associated test setup IDs.
|
||||
- `ClearGroupHardwareIds()`, `AddGroupHardwareId(int dasId, int groupId)`, `GetGroupHardwareIds(int DASId)`: Map DAS IDs to associated group IDs.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`GroupGRPImportGroup.Channels`**: Always initialized to an empty array (`{ }`), never `null`.
|
||||
- **`GroupGRPImportGroup.GroupErrors`**: Initialized to `null` by default; non-null only if errors occurred during import.
|
||||
- **`GroupGRPImportChannel.*` nullable properties** (e.g., `InputMode`, `DefaultValue`, `FireMode`, etc.): May be `null` if not specified in the `.GRP` file; default values are defined as constants (e.g., `DefaultInputMode`, `DefaultFireMode`, etc.).
|
||||
- **`GroupDbRecord.ExtraProperties`**: Serialized as JSON using `JavaScriptSerializer`; deserialization responsibility lies with consumers.
|
||||
- **`ChannelDbRecord.IsDisabled`**: Redirects to `Disabled`; both properties must be kept in sync when set via `IsDisabled`.
|
||||
- **`GroupHelper` static caches**: Must be cleared between operations (e.g., import sessions) to avoid stale data; no automatic cleanup is provided.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.Base`**: Base classes (`BasePropertyChanged`) used by `GroupGRPImportGroup`, `GroupGRPImportChannel`, `GroupHardwareDbRecord`, `TestSetupGroupRecord`, `GroupDbRecord`, `ChannelDbRecord`.
|
||||
- **`DTS.Common.Interface.Groups`**: Interfaces `IGroupHardwareDbRecord`, `ITestSetupGroupRecord`, `IGroupDbRecord`.
|
||||
- **`DTS.Common.Interface.Channels`**: Interface `IChannelDbRecord`.
|
||||
- **`System.Data`**: `IDataReader` used in record constructors.
|
||||
- **`System.ComponentModel.DataAnnotations`**: `[Key]` attribute on `Id` fields.
|
||||
- **`System.Web.Script.Serialization.JavaScriptSerializer`**: Used in `GroupDbRecord` constructor to serialize `ExtraProperties`.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **Import/Export logic**: `.GRP` file parsing and validation (not included here, but inferred from `GroupGRPImport*` classes).
|
||||
- **Database layer**: `GroupDbRecord`, `ChannelDbRecord`, `GroupHardwareDbRecord`, `TestSetupGroupRecord` are used by data access layers.
|
||||
- **UI layer**: `GroupGRPImportGroup.GroupNameHasError` and `GroupGRPImportChannel.GroupName` suggest binding to UI controls (e.g., textboxes, error indicators).
|
||||
- **Runtime metadata management**: `GroupHelper` is used by other modules to resolve IDs, serial numbers, and mappings without repeated DB queries.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`GroupGRPImportChannel.GroupName` is a computed property**: It returns `ParentGroup.GroupName` or `"---"` if `ParentGroup` is `null`. UI bindings must be manually invalidated via `GroupNameInvalidate()` if `ParentGroup` changes after construction.
|
||||
- **`IsDisabled` alias in `ChannelDbRecord`**: While `IsDisabled` redirects to `Disabled`, setting `IsDisabled` only raises `OnPropertyChanged("IsDisabled")`, not `"Disabled"`. This may cause UI binding inconsistencies if consumers bind to `"Disabled"` directly.
|
||||
- **`GroupDbRecord.ExtraProperties` serialization**: Uses legacy `JavaScriptSerializer`; not compatible with modern `System.Text.Json`. Consumers must use the same serializer for round-tripping.
|
||||
- **`GroupHelper` static state**: Caches are global and mutable; failure to call `Clear*()` methods between operations (e.g., import sessions) can lead to incorrect ID lookups or stale mappings.
|
||||
- **`GroupHardwareDbRecord.Id` vs `GroupDbRecord.Id`**: Both use `int Id`, but `ChannelDbRecord.Id` uses `long Id`. Ensure correct type usage in queries.
|
||||
- **`GroupGRPImportGroup.GroupErrors` is nullable**: Consumers must explicitly check for `null` before iterating (e.g., `?.Length` or `GroupErrors?.Any()`).
|
||||
- **`GroupHelper.GetChannelIndexes` and `GetGroupIds`**: Use exact string/ID matching on nested dictionaries; performance may degrade with large datasets due to nested loops.
|
||||
- **`GroupDbRecord.SerialNumber` vs `GroupName`**: In `GroupDbRecord(IGroup copy, ...)`, `SerialNumber` is set to `copy.Name`, but `DisplayName` is set separately. Ensure `Name` and `DisplayName` are distinct in the `IGroup` interface.
|
||||
@@ -0,0 +1,158 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Groups/ChannelSettings/ChannelSettingRecord.cs
|
||||
- Common/DTS.Common/Classes/Groups/ChannelSettings/GroupChannelSettingRecord.cs
|
||||
- Common/DTS.Common/Classes/Groups/ChannelSettings/ChannelSettingBase.cs
|
||||
generated_at: "2026-04-16T03:18:55.361650+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "48681046c7a61e91"
|
||||
---
|
||||
|
||||
# ChannelSettingRecord, GroupChannelSettingRecord, and ChannelSettingBase Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module defines core data structures for representing channel configuration settings within the DTS system. It provides three interrelated classes: `ChannelSettingRecord` (a lightweight record of a *type* of channel setting, including its ID, name, and default value), `GroupChannelSettingRecord` (a *specific instance* of a setting applied to a particular channel), and `ChannelSettingBase` (a richer, type-aware implementation of `IChannelSetting` that supports parsing and type conversion of setting values). Together, they enable storage, retrieval, and manipulation of channel-specific configuration parameters across different channel types (analog, digital, squib, UART, CAN, etc.), forming the data layer for channel configuration management.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `ChannelSettingRecord`
|
||||
- **`ChannelSettingRecord()`**
|
||||
Default constructor; initializes an empty record.
|
||||
- **`ChannelSettingRecord(IDataReader reader)`**
|
||||
Populates the record from an `IDataReader` by reading columns `"Id"`, `"SettingName"`, and `"DefaultValue"` using `Utility.GetInt` and `Utility.GetString`.
|
||||
|
||||
- **`int Id { get; set; }`**
|
||||
Unique identifier for this setting *type* (e.g., `"Range"` or `"SquibCurrent"`).
|
||||
- **`string SettingName { get; set; }`**
|
||||
Human-readable name of the setting (e.g., `"Range"`).
|
||||
- **`string DefaultValue { get; set; }`**
|
||||
Default value string for this setting type (e.g., `"10"` for a range setting).
|
||||
|
||||
> *Note:* Inherits from `Common.Base.BasePropertyChanged`, implying `INotifyPropertyChanged` support for UI binding.
|
||||
|
||||
---
|
||||
|
||||
### `GroupChannelSettingRecord`
|
||||
- **`GroupChannelSettingRecord()`**
|
||||
Default constructor; initializes an empty record.
|
||||
- **`GroupChannelSettingRecord(IDataReader reader, int storedProcedureVersionUsed)`**
|
||||
Populates the record from an `IDataReader`. If `storedProcedureVersionUsed >= Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`, it reads `"ChannelId"` using `Utility.GetLong`; otherwise, `ChannelId` is left uninitialized (default `0`). Always reads `"SettingId"` (`Utility.GetInt`) and `"SettingValue"` (`Utility.GetString`).
|
||||
- **`GroupChannelSettingRecord(long channelId, int settingId, string settingValue)`**
|
||||
Constructor for direct initialization with explicit values.
|
||||
|
||||
- **`long ChannelId { get; set; }`**
|
||||
Identifier of the channel to which this setting instance applies.
|
||||
- **`int SettingId { get; set; }`**
|
||||
Identifier of the setting *type* (corresponds to `ChannelSettingRecord.Id`).
|
||||
- **`string SettingValue { get; set; }`**
|
||||
Actual value string assigned to this setting for the channel.
|
||||
|
||||
> *Note:* Inherits from `BasePropertyChanged`, implying `INotifyPropertyChanged` support.
|
||||
|
||||
---
|
||||
|
||||
### `ChannelSettingBase`
|
||||
- **`ChannelSettingBase(int settingType, string name, string defaultValue)`**
|
||||
Constructor initializing `SettingTypeId`, `SettingName`, and `DefaultValue`. `Value` is initialized to `null`.
|
||||
- **`ChannelSettingBase(IChannelSetting setting)`**
|
||||
Copy constructor; initializes all properties from another `IChannelSetting` instance.
|
||||
- **`IChannelSetting Clone()`**
|
||||
Returns a new `ChannelSettingBase` instance with all properties copied from the current instance.
|
||||
|
||||
- **`long ChannelId { get; set; }`**
|
||||
Channel identifier associated with this setting instance.
|
||||
- **`int SettingTypeId { get; protected set; }`**
|
||||
Type ID of the setting (e.g., used to group settings by channel type).
|
||||
- **`string SettingName { get; protected set; }`**
|
||||
Name of the setting (e.g., `"Range"`, `"SquibCurrent"`).
|
||||
- **`string DefaultValue { get; protected set; }`**
|
||||
Default value string for this setting type.
|
||||
- **`string Value { get; set; }`**
|
||||
Current value string for this setting instance.
|
||||
|
||||
- **`double DoubleValue { get; set; }`**
|
||||
Parses `Value` as a `double` (using `InvariantCulture`); if parsing fails, returns `DoubleDefaultValue`. Setting updates `Value`.
|
||||
- **`double DoubleDefaultValue { get; }`**
|
||||
Parses `DefaultValue` as a `double` (using `InvariantCulture`).
|
||||
- **`int IntValue { get; set; }`**
|
||||
Parses `Value` as an `int`; if parsing fails, returns `IntDefaultValue`. Setting updates `Value`.
|
||||
- **`int IntDefaultValue { get; }`**
|
||||
Parses `DefaultValue` as an `int`.
|
||||
- **`bool BoolValue { get; set; }`**
|
||||
Parses `Value` as a `bool`; if parsing fails, returns `BoolDefaultValue`. Setting updates `Value`.
|
||||
- **`bool BoolDefaultValue { get; }`**
|
||||
Parses `DefaultValue` as a `bool`. If parsing fails and `DefaultValue` is null/empty, returns `false`; otherwise, returns `!DefaultValue.Equals(0)` (note: this is a string comparison, not numeric).
|
||||
|
||||
> *Note:* Implements `IChannelSetting`. Constants defined as `public const string` for known setting names (see *Gotchas* for caveats).
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`ChannelSettingRecord`**
|
||||
- `Id`, `SettingName`, and `DefaultValue` are populated from database columns and must be non-null (except `DefaultValue`, which may be empty or null per `Utility.GetString` behavior).
|
||||
- `Id` is expected to be unique per setting type.
|
||||
|
||||
- **`GroupChannelSettingRecord`**
|
||||
- `SettingId` must correspond to a valid `ChannelSettingRecord.Id` (enforced externally, not by this class).
|
||||
- `ChannelId` may be uninitialized (`0`) if constructed via `IDataReader` constructor with `storedProcedureVersionUsed < Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`.
|
||||
- `SettingValue` may be null or empty.
|
||||
|
||||
- **`ChannelSettingBase`**
|
||||
- `SettingName` and `DefaultValue` are set only via constructor and remain immutable after construction (due to `protected set`).
|
||||
- `Value` is mutable and may be null/empty.
|
||||
- `DoubleValue`, `IntValue`, and `BoolValue` fall back to their respective `*DefaultValue` properties if `Value` is unparsable.
|
||||
- `BoolDefaultValue` has non-intuitive behavior: if `DefaultValue` cannot be parsed as `bool`, and is non-empty, it returns `!DefaultValue.Equals("0")` (string comparison), *not* numeric evaluation.
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.Interface.Channels`**
|
||||
Defines interfaces `IChannelSettingRecord`, `IGroupChannelSettingRecord`, and `IChannelSetting` (consumed by these classes).
|
||||
- **`DTS.Common.Base`**
|
||||
Provides `BasePropertyChanged` (base class for `ChannelSettingRecord` and `GroupChannelSettingRecord`).
|
||||
- **`System.Data`**
|
||||
Used for `IDataReader` in constructors.
|
||||
- **`DTS.Common` (internal)**
|
||||
- `Utility` class (for `GetInt`, `GetString`, `GetLong`).
|
||||
- `Constants` (for `BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`).
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- Likely consumed by:
|
||||
- Data access layers (to populate records from `IDataReader`).
|
||||
- Channel configuration services (to manage per-channel settings).
|
||||
- UI layers (via `INotifyPropertyChanged` support).
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`BoolDefaultValue` logic is error-prone**:
|
||||
If `DefaultValue` is `"1"` or `"true"`, `bool.TryParse` succeeds. But if `DefaultValue` is `"0"`, `bool.TryParse` fails (since `"0"` is not a valid `bool` string), and `BoolDefaultValue` returns `!DefaultValue.Equals("0")` → `false`. This is inconsistent with typical `bool` parsing and may cause misinterpretation of `"0"` as `false` only when `bool.TryParse` fails. Prefer explicit `"true"`/`"false"` defaults.
|
||||
|
||||
- **`ChannelSettingBase` constants are *not* exhaustive**:
|
||||
The `public const string` fields list known setting names (e.g., `"Range"`, `"SquibCurrent"`), but are not validated against actual usage. New settings may be added without updating these constants, leading to string literals scattered elsewhere in the codebase.
|
||||
|
||||
- **`GroupChannelSettingRecord` constructor behavior depends on `storedProcedureVersionUsed`**:
|
||||
If `storedProcedureVersionUsed < Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`, `ChannelId` is *not* read from the `IDataReader`, leaving it at `0`. This introduces version-dependent data loading logic that may cause silent bugs if versioning is mismanaged.
|
||||
|
||||
- **`ChannelSettingBase` does not enforce `Value` format**:
|
||||
While `DoubleValue`, `IntValue`, and `BoolValue` provide type-safe access, `Value` itself is a raw `string`. No validation ensures `Value` matches the expected format for `SettingName`.
|
||||
|
||||
- **`Clone()` returns `IChannelSetting`, not `ChannelSettingBase`**:
|
||||
The copy constructor is `private`, and `Clone()` returns the interface type, limiting extensibility or deep-copy behavior in subclasses.
|
||||
|
||||
- **No null-safety for `DefaultValue` in numeric/bool conversions**:
|
||||
`DoubleDefaultValue`, `IntDefaultValue`, and `BoolDefaultValue` call `double.Parse`, `int.Parse`, or `bool.TryParse` on `DefaultValue` without null checks. If `DefaultValue` is `null`, this will throw `ArgumentNullException` or `FormatException`.
|
||||
|
||||
- **`SettingName` is `protected set`**:
|
||||
Cannot be modified after construction, but `ChannelSettingBase` is not sealed—subclasses could theoretically override behavior, though no subclasses are visible in the provided source.
|
||||
|
||||
- **`ChannelSettingRecord` and `GroupChannelSettingRecord` share naming but serve distinct roles**:
|
||||
`ChannelSettingRecord` defines a *type* of setting (e.g., `"Range"`), while `GroupChannelSettingRecord` defines an *instance* (e.g., channel 123’s `"Range"` = `"10"`). Confusing these roles is a common source of bugs.
|
||||
|
||||
None identified beyond the above.
|
||||
321
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Hardware.md
Normal file
321
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Hardware.md
Normal file
@@ -0,0 +1,321 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Hardware/ExternalTilt.cs
|
||||
- Common/DTS.Common/Classes/Hardware/DragAndDropPayload.cs
|
||||
- Common/DTS.Common/Classes/Hardware/SerializableAAF.cs
|
||||
- Common/DTS.Common/Classes/Hardware/DASDBRecord.cs
|
||||
- Common/DTS.Common/Classes/Hardware/DASChannelDBRecord.cs
|
||||
- Common/DTS.Common/Classes/Hardware/DASMonitorInfo.cs
|
||||
generated_at: "2026-04-16T03:14:40.842937+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "f2a89e74efee1556"
|
||||
---
|
||||
|
||||
# Hardware Data Models Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module defines core data models for representing hardware components in the DTS (Data Acquisition System) ecosystem. It provides structured classes for serializing, deserializing, and persisting hardware metadata—including DAS (Data Acquisition System) units, their channels, external tilt sensors, and monitoring configurations—to and from databases and files. These models serve as the canonical data structures for hardware inventory management, configuration synchronization, and system diagnostics across the application.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `ExternalTilt`
|
||||
A simple POCO representing metadata for an external tilt sensor.
|
||||
|
||||
- **`ExternalTilt()`**
|
||||
Parameterless constructor.
|
||||
|
||||
- **`string SerialNumber { get; set; }`**
|
||||
Serial number of the tilt sensor.
|
||||
|
||||
- **`byte TiltID { get; set; }`**
|
||||
Unique identifier for the tilt sensor within a system.
|
||||
|
||||
- **`string SystemID { get; set; }`**
|
||||
Identifier of the system the tilt sensor is associated with.
|
||||
|
||||
- **`string SystemLocation { get; set; }`**
|
||||
Physical or logical location of the tilt sensor within the system.
|
||||
|
||||
---
|
||||
|
||||
### `DragAndDropPayload`
|
||||
A static class defining string constants used as clipboard/data transfer formats for hardware table drag-and-drop operations.
|
||||
|
||||
- **`const string FORMAT = "RESOLVECHANNELS_HARDWARETABLE"`**
|
||||
Primary format identifier for hardware table data transfer.
|
||||
|
||||
- **`const string ALT_FORMAT = "ALT_RESOLVECHANNELS_HARDWARETABLE"`**
|
||||
Alternate format identifier (likely for legacy or variant workflows).
|
||||
|
||||
- **`const string CTRL_FORMAT = "CTRL_RESOLVECHANNELS_HARDWARETABLE"`**
|
||||
Control-key modifier variant format identifier.
|
||||
|
||||
---
|
||||
|
||||
### `SerializableAAF`
|
||||
A class for serializing/deserializing AAF (Anti-Aliasing Filter) configuration data. *Note: All core functionality is currently commented out.*
|
||||
|
||||
- **`enum DAS_TYPE { TDAS = 0, SLICE = 1 }`**
|
||||
Defines DAS hardware types.
|
||||
|
||||
- **`string GetSerializedKey()`** *(commented out)*
|
||||
Would return a key string of the form `"{DAS_TYPE}_{SampleRate}"`.
|
||||
|
||||
- **`string GetSerializedValue()`** *(commented out)*
|
||||
Would return the AAF value as a culture-invariant string.
|
||||
|
||||
- **`void FromSerializedStrings(string key, string value)`** *(commented out)*
|
||||
Would parse `key` and `value` strings to reconstruct internal state.
|
||||
|
||||
*No active public methods or properties are available in the current source.*
|
||||
|
||||
---
|
||||
|
||||
### `DASDBRecord`
|
||||
A database-mapped entity representing a DAS unit in the `DAS` table.
|
||||
|
||||
- **`static DateTime INVALID_DATE => new DateTime(1970, 1, 1)`**
|
||||
Sentinel value for unset date fields.
|
||||
|
||||
- **`DASDBRecord()`**
|
||||
Default constructor.
|
||||
|
||||
- **`DASDBRecord(IDASDBRecord copy)`**
|
||||
Copy constructor; initializes fields from another `IDASDBRecord` instance.
|
||||
|
||||
- **`DASDBRecord(IDataReader reader)`**
|
||||
Constructor that populates fields from a database `IDataReader`.
|
||||
|
||||
- **`int DASId { get; set; }`**
|
||||
Primary key (`[Key]`, `[Column("DASId")]`).
|
||||
|
||||
- **`string SerialNumber { get; set; }`**
|
||||
Required; max length 50 (`[Required]`, `[StringLength(50)]`).
|
||||
|
||||
- **`int DASType { get; set; }`**
|
||||
Numeric type identifier for the DAS.
|
||||
|
||||
- **`int MaxModules { get; set; }`**, **`long MaxMemory { get; set; }`**, **`double MaxSampleRate { get; set; }`**, **`double MinSampleRate { get; set; }`**
|
||||
Hardware specifications.
|
||||
|
||||
- **`string FirmwareVersion { get; set; }`**
|
||||
Firmware version string; defaults to `""`.
|
||||
|
||||
- **`DateTime CalDate { get; set; }`**
|
||||
Calibration date; defaults to `INVALID_DATE`.
|
||||
|
||||
- **`int ProtocolVersion { get; set; }`**
|
||||
Protocol version number.
|
||||
|
||||
- **`DateTime LastModified { get; set; }`**, **`string LastModifiedBy { get; set; }`**
|
||||
Timestamp and user who last modified the record.
|
||||
|
||||
- **`int Version { get; set; }`**
|
||||
Concurrency/version tracking.
|
||||
|
||||
- **`bool LocalOnly { get; set; }`**
|
||||
Flag indicating local-only storage (deprecated per `DASChannelDBRecord`).
|
||||
|
||||
- **`DateTime LastUsed { get; set; }`**, **`string LastUsedBy { get; set; }`**
|
||||
Last usage timestamp and user.
|
||||
|
||||
- **`string Connection { get; set; }`**, **`int Channels { get; set; }`**, **`string Position { get; set; }`**
|
||||
Connection type, channel count, and physical/logical position.
|
||||
|
||||
- **`int[] ChannelTypes { get; set; }`**
|
||||
Array of channel type identifiers; defaults to `new int[0]`.
|
||||
|
||||
- **`bool IsProgrammable { get; set; }`**, **`bool IsReconfigurable { get; set; }`**, **`bool IsModule { get; set; }`**
|
||||
Hardware capability flags.
|
||||
|
||||
- **`int PositionOnDistributor { get; set; }`**, **`int PositionOnChain { get; set; }`**, **`int Port { get; set; }`**
|
||||
Positioning metadata.
|
||||
|
||||
- **`string ParentDAS { get; set; }`**
|
||||
Serial number of parent DAS (for modular systems).
|
||||
|
||||
- **`DateTime? FirstUseDate { get; set; }`**, **`bool IsFirstUseValid { get; set; }`**
|
||||
Optional first-use date and validity flag.
|
||||
|
||||
- **`bool StandIn { get; set; }`**
|
||||
Flag indicating this is a stand-in (replacement) unit.
|
||||
|
||||
- **`int? TestId { get; set; }`**, **`int? GroupId { get; set; }`**
|
||||
Optional test and group identifiers.
|
||||
|
||||
- **`double MaxAAFRate { get; set; }`**
|
||||
Maximum AAF rate supported.
|
||||
|
||||
---
|
||||
|
||||
### `DASChannelDBRecord`
|
||||
A database-mapped entity representing a channel on a DAS unit.
|
||||
|
||||
- **`string HardwareId { get; set; }`**
|
||||
Composite hardware identifier: `serialnumber_dastype`.
|
||||
|
||||
- **`int DaschannelId { get; set; }`**
|
||||
Primary key (`[Key]`, `[Column("DASChannelId")]`).
|
||||
|
||||
- **`int? Dasid { get; set; }`**
|
||||
Foreign key to `DAS.DASId`.
|
||||
|
||||
- **`int ChannelIdx { get; set; }`**
|
||||
Physical channel index on the DAS.
|
||||
|
||||
- **`const int DEFAULT_SUPPORTED_BRIDGES = 12`**
|
||||
Default bridge support mask (half + full bridge).
|
||||
|
||||
- **`int SupportedBridges { get; set; }`**
|
||||
Bitmask of supported bridge types:
|
||||
- Bit 0: IEPE
|
||||
- Bit 1: Quarter bridge
|
||||
- Bit 2: Half bridge
|
||||
- Bit 3: Full bridge
|
||||
- Bit 4: Digital input
|
||||
- Bit 5: Squib fire
|
||||
- Bit 6: Digital output
|
||||
- Bit 7: Half bridge signal plus (G5)
|
||||
- Bit 8: Real-time clock
|
||||
- Bit 9: UART
|
||||
|
||||
- **`const int DEFAULT_SUPPORTED_EXCITATIONS = 16`**
|
||||
Default excitation mask (5V).
|
||||
|
||||
- **`int SupportedExcitations { get; set; }`**
|
||||
Bitmask of supported excitation voltages:
|
||||
- Bit 0: Invalid
|
||||
- Bit 1: 2V
|
||||
- Bit 2: 2.5V
|
||||
- Bit 3: 3V
|
||||
- Bit 4: 5V
|
||||
- Bit 5: 10V
|
||||
- Bit 6: 1V
|
||||
|
||||
- **`int DASDisplayOrder { get; set; }`**
|
||||
Logical display order (may differ from physical order).
|
||||
|
||||
- **`bool LocalOnly { get; set; }`**
|
||||
Deprecated; indicates local-only storage.
|
||||
|
||||
- **`const int DEFAULT_SUPPORTED_DI_MODES = 16`**, **`int SupportedDigitalInputModes { get; set; }`**
|
||||
Default and configurable digital input modes bitmask.
|
||||
|
||||
- **`const int DEFAULT_SQUIB_FIRE_MODES = 16`**, **`int SupportedSquibFireModes { get; set; }`**
|
||||
Default and configurable squib fire modes bitmask.
|
||||
|
||||
- **`const int DEFAULT_SUPPORTED_DO_MODES = 16`**, **`int SupportedDigitalOutputModes { get; set; }`**
|
||||
Default and configurable digital output modes bitmask.
|
||||
|
||||
- **`string ModuleSerialNumber { get; set; }`**
|
||||
Serial number of the module the channel belongs to.
|
||||
|
||||
- **`int SettingId { get; set; }`**
|
||||
Configuration setting ID.
|
||||
|
||||
- **`int ModuleArrayIndex { get; set; }`**
|
||||
Array index of the module on the DAS or rack.
|
||||
|
||||
- **`DASChannelDBRecord()`**, **`DASChannelDBRecord(IDataReader reader)`**, **`DASChannelDBRecord(IDASChannelDBRecord copy)`**
|
||||
Constructors for default, database, and copy initialization.
|
||||
|
||||
---
|
||||
|
||||
### `DASMonitorInfo`
|
||||
A class for reading/writing and constructing monitor configuration data for a DAS unit, primarily used for tilt sensor calibration and channel diagnostics.
|
||||
|
||||
- **`string SerialNumber { get; private set; }`**
|
||||
DAS serial number.
|
||||
|
||||
- **`double[] TiltSensorCals { get; private set; }`**
|
||||
Calibration coefficients for 18 tilt sensors.
|
||||
|
||||
- **`short[] TiltSensorDataPre { get; private set; }`**
|
||||
Pre-processed tilt sensor raw data (3 values).
|
||||
|
||||
- **`DFConstantsAndEnums.TiltAxes TiltAxes { get; private set; }`**
|
||||
Axis configuration (e.g., `IXIYIZ`).
|
||||
|
||||
- **`int AxisIgnored { get; private set; }`**
|
||||
Bitmask indicating ignored axes.
|
||||
|
||||
- **`double MountOffsetAxisOne { get; private set; }`**, **`double MountOffsetAxisTwo { get; private set; }`**
|
||||
Mounting offsets for two axes.
|
||||
|
||||
- **`string GetChannelName(int index)`**
|
||||
Returns channel name based on internal `_channelNames` array or a default `"Ch#XX"`.
|
||||
|
||||
- **`double GetOffsetTolerancemVHigh(int index)`**, **`double GetOffsetTolerancemVLow(int index)`**
|
||||
Returns high/low offset tolerance (mV) for a given channel index.
|
||||
|
||||
- **`void ReadFromFile(string path)`**
|
||||
Reads monitor info from a text file (10 lines, one per `Fields` enum value). Silently fails on file not found or parse errors.
|
||||
|
||||
- **`void WriteToFile(string path)`**
|
||||
Writes monitor info to a text file. Logs exceptions via `APILogger`.
|
||||
|
||||
- **`DASMonitorInfo(IDASCommunication das, IsoViewMode mode)`**
|
||||
Constructor that populates fields from an active DAS communication object (`das`) and view mode.
|
||||
|
||||
- **`DASMonitorInfo(string path)`**
|
||||
Constructor that calls `ReadFromFile(path)`.
|
||||
|
||||
*Note: Several private helper methods (`GetTiltSensorCals`, `GetTiltSensorData`, `GetChannelNames`, etc.) are used internally during construction.*
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`DASDBRecord`**
|
||||
- `SerialNumber` and `Position` are required (`[Required]` attribute) and must be ≤50 characters.
|
||||
- `CalDate` and `LastUsed` default to `INVALID_DATE` (1970-01-01) if unset.
|
||||
- `ChannelTypes` is always initialized to a non-null array (default `new int[0]`).
|
||||
- `IsFirstUseValid` is `false` by default; `FirstUseDate` is `null` if invalid or unset.
|
||||
|
||||
- **`DASChannelDBRecord`**
|
||||
- `SupportedBridges`, `SupportedExcitations`, `SupportedDigitalInputModes`, `SupportedDigitalOutputModes`, and `SupportedSquibFireModes` use specific bitmasks defined by constants.
|
||||
- `ChannelIdx` defaults to `-1` if not set.
|
||||
- `ModuleArrayIndex` is mutable only via direct assignment (no `SetProperty` call).
|
||||
|
||||
- **`DASMonitorInfo`**
|
||||
- `_channelNames`, `_offsetTolerancesHigh`, `_offsetTolerancesLow` arrays are initialized to empty arrays by default.
|
||||
- `ReadFromFile` silently ignores missing files or malformed lines.
|
||||
- `TiltSensorCals` is always 18 elements; `TiltSensorDataPre` is always 3 elements.
|
||||
|
||||
- **`SerializableAAF`**
|
||||
- No active invariants (all functionality is commented out).
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### This Module Depends On:
|
||||
- **`DTS.Common.Base`** (`BasePropertyChanged` base class for `DASDBRecord`, `DASChannelDBRecord`).
|
||||
- **`DTS.Common.Enums`**, **`DTS.Common.Enums.DASFactory`** (`DFConstantsAndEnums.TiltAxes`, `IsoViewMode`).
|
||||
- **`DTS.Common.Interface.DataRecorders`** (`IDASDBRecord`, `IDASChannelDBRecord`).
|
||||
- **`DTS.Common.Interface.DASFactory`** (`IDASCommunication`).
|
||||
- **`DTS.Common.Interface.Hardware`** (`ITiltSensorCalAware`).
|
||||
- **`DTS.Common.Utilities.Logging`** (`APILogger`).
|
||||
- **`System.ComponentModel.DataAnnotations`**, **`System.Data`** (EF Core attributes, `IDataReader`).
|
||||
- **`System`**, **`System.Linq`**, **`System.Text`**, **`System.Globalization`**, **`System.IO`**.
|
||||
|
||||
### This Module Is Used By:
|
||||
- Database persistence layers (via `DASDBRecord`, `DASChannelDBRecord`).
|
||||
- Hardware configuration UIs (via `DASMonitorInfo`, `ExternalTilt`).
|
||||
- Drag-and-drop handlers (via `DragAndDropPayload` constants).
|
||||
- Serialization/deserialization utilities (though `SerializableAAF` is currently unused).
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`SerializableAAF` is non-functional**: All public members are commented out. Do not rely on this class for serialization.
|
||||
- **`DASChannelDBRecord.LocalOnly` is deprecated**: Despite being present, it should not be used for new logic.
|
||||
- **`DASDBRecord.IsProgrammable` maps to `"Reprogramable"` column**: Note the typo in the column name (`Reprogramable` vs. `IsProgrammable`).
|
||||
- **`DASMonitorInfo` tolerances are per-channel but stored flat**: `_offsetTolerancesHigh`/`_offsetTolerancesLow` arrays are indexed per channel, but their length depends on the number of analog input channels in the DAS configuration.
|
||||
- **`DASMonitorInfo.GetChannelName` falls back to default naming**: If `_channelNames` is shorter than `index`, it returns `"Ch#XX"` instead of throwing.
|
||||
- **`DASMonitorInfo.ToShortArray` has a bug**: In `ToShortArray`, it parses `line` instead of `token` (`short.TryParse(line, ...)`)—likely a typo.
|
||||
- **`DASMonitorInfo` uses `float.NaN` for mount offsets**: Despite `MountOffsetAxisOne/Two` being `double`, `GetMountOffsetAxisOne/Two` return `float.NaN` when no modules exist. This may cause precision loss or unexpected behavior.
|
||||
- **`DASDBRecord` uses `INVALID_DATE` for unset dates**: Code must explicitly check for `DateTime(1970, 1, 1)` to detect unset values.
|
||||
101
enriched-qwen3-coder-next/Common/DTS.Common/Classes/ISO.md
Normal file
101
enriched-qwen3-coder-next/Common/DTS.Common/Classes/ISO.md
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/ISO/IsoCode.cs
|
||||
generated_at: "2026-04-16T03:15:00.433406+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "f4af52456432964e"
|
||||
---
|
||||
|
||||
# ISO
|
||||
|
||||
## Documentation: `IsoCode` Class
|
||||
|
||||
### 1. Purpose
|
||||
The `IsoCode` class encapsulates a fixed-length 16-character ISO-compliant location code, where each position or substring has a defined semantic meaning (e.g., test object, position, main/fine locations, physical dimension, direction, filter class). It provides a structured, type-safe interface to parse, manipulate, and reconstruct such codes while enforcing padding with `'?'` for missing characters and `'0'` for out-of-bounds or invalid inputs. This class exists to standardize handling of ISO 14134–2–compliant or similar legacy location identifiers in the system, likely used in medical device or calibration contexts.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### Constructor
|
||||
- **`IsoCode(string isoCode)`**
|
||||
Initializes a new instance by parsing a 16-character (or shorter/longer) input string. Truncates to 16 chars if longer; pads with `'?'` if shorter. Assigns each character directly to `_isoCodeFull[i]`.
|
||||
|
||||
#### Properties
|
||||
- **`string TestObject`**
|
||||
Gets/sets the first character (`_isoCodeFull[0]`). Setter replaces `null`/empty input with `'?'`.
|
||||
|
||||
- **`string Position`**
|
||||
Gets/sets the second character (`_isoCodeFull[1]`). Setter replaces `null`/empty input with `'?'`.
|
||||
|
||||
- **`string MainLocation`**
|
||||
Gets/sets characters at indices 2–5 (4 chars). Setter pads with `'?'` if < 4 chars, truncates to 4 if > 4.
|
||||
|
||||
- **`string FineLocation1`**
|
||||
Gets/sets characters at indices 6–7 (2 chars). Setter pads with `'?'` if < 2 chars.
|
||||
|
||||
- **`string FineLocation2`**
|
||||
Gets/sets characters at indices 8–9 (2 chars). Setter pads with `'?'` if < 2 chars.
|
||||
|
||||
- **`string FineLocation3`**
|
||||
Gets/sets characters at indices 10–11 (2 chars). Setter pads with `'?'` if < 2 chars.
|
||||
|
||||
- **`string PhysicalDimension`**
|
||||
Gets/sets characters at indices 12–13 (2 chars). Setter pads with `'?'` if < 2 chars, truncates to 2 if > 2.
|
||||
|
||||
- **`string Direction`**
|
||||
Gets/sets the 15th character (`_isoCodeFull[14]`). Setter replaces `null`/empty input with `'?'`.
|
||||
|
||||
- **`string FilterClass`**
|
||||
Gets/sets the 16th character (`_isoCodeFull[15]`). Setter replaces `null`/empty input with `'?'`.
|
||||
|
||||
- **`string StringRepresentation`**
|
||||
Gets/sets the full 16-character code as a string.
|
||||
- *Getter*: concatenates all `_isoCodeFull` characters.
|
||||
- *Setter*: assigns `value[i]` to `_isoCodeFull[i]` for `i < 16`; sets remaining positions to `'0'` if `value.Length < 16`.
|
||||
⚠️ **Note**: Unlike other setters, this one pads *short* inputs with `'0'`, not `'?'`.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
- `_isoCodeFull` is always exactly 16 characters long.
|
||||
- All public properties (`TestObject`, `Position`, etc.) map to fixed, non-overlapping substrings of `_isoCodeFull`:
|
||||
- `TestObject`: index 0
|
||||
- `Position`: index 1
|
||||
- `MainLocation`: indices 2–5
|
||||
- `FineLocation1`: indices 6–7
|
||||
- `FineLocation2`: indices 8–9
|
||||
- `FineLocation3`: indices 10–11
|
||||
- `PhysicalDimension`: indices 12–13
|
||||
- `Direction`: index 14
|
||||
- `FilterClass`: index 15
|
||||
- When setting any property via its public setter:
|
||||
- Short inputs are padded with `'?'` (except `StringRepresentation`, which uses `'0'`).
|
||||
- Long inputs are truncated to the property’s fixed length.
|
||||
- Invalid or missing characters (e.g., `null`, empty string) are normalized to `'?'` for most properties, but `'0'` may appear in `StringRepresentation` setter or internal `_mainLocation`/`_fineLocation*` setters if arrays are undersized (see *Gotchas*).
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
- **Internal**: Uses `System.Text.StringBuilder` (for `StringRepresentation` getter).
|
||||
- **External**:
|
||||
- `DTS.Common.ISO` namespace (no external NuGet or framework dependencies beyond `System`).
|
||||
- **Depended on**: Not visible in source; likely consumed by higher-level location/positioning or calibration modules (e.g., device state management, test sequencing).
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
- **Inconsistent padding in `StringRepresentation` setter**: Unlike all other property setters, `StringRepresentation` pads short inputs with `'0'`, not `'?'`. This breaks the expected `'?'`-padding convention and may cause silent data corruption if used carelessly.
|
||||
- **Undersized array handling in private setters**:
|
||||
- `_mainLocation`, `_fineLocation1`, `_fineLocation2`, `_fineLocation3`, `_physicalDimension` setters use `value.Length <= i` or `value.Length < i` to decide whether to write `'0'` or `value[i]`. This is inconsistent:
|
||||
- For `_mainLocation`, `value.Length <= i` (e.g., 3-char input → writes `'0'` for index 3).
|
||||
- For `_fineLocation1`, `value.Length < i` (e.g., 1-char input → writes `'0'` for index 1).
|
||||
→ Both produce `'0'` for missing chars, but the condition is off-by-one in `_fineLocation1`.
|
||||
- **No validation of semantic meaning**: The class accepts any characters (including non-alphanumeric) and does not enforce ISO-specific character sets (e.g., digits, uppercase letters only).
|
||||
- **`TestObject`, `Position`, etc. are misnamed**: `TestObject` is a property name but semantically appears to be a *test identifier* or *test type* (not an object). Likely legacy naming.
|
||||
- **No immutability or thread safety**: The class is mutable and not thread-safe.
|
||||
- **`StringRepresentation` setter mutates underlying array directly**: Does not validate or normalize input beyond length truncation/padding, potentially violating invariants if used after property setters (e.g., setting `StringRepresentation = "ABC"` yields `"ABC0000000000000"` instead of `"ABC???????????????"`).
|
||||
- **No `Equals`/`GetHashCode`/`IEquatable` implementation**: Value equality is not defined, risking reference equality bugs.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/ISO/ExtraProperties/TextPastedArgs.cs
|
||||
generated_at: "2026-04-16T03:18:29.951703+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "958951d2772f6a16"
|
||||
---
|
||||
|
||||
# ExtraProperties
|
||||
|
||||
## 1. Purpose
|
||||
`TextPastedArgs` is an immutable event argument class used to carry contextual data when a text-paste operation occurs on an extra property control within the ISO (likely *Intelligent System Operator* or similar domain) UI layer. It encapsulates the pasted text content, the originating extra property instance, a unique identifier for the operation, and an optional user-defined tag—enabling event subscribers to handle paste events with full context.
|
||||
|
||||
## 2. Public Interface
|
||||
- **`TextPastedArgs(string text, IExtraProperty extraProperty, string id, object tag)`**
|
||||
Constructor initializing all properties. Validates *none* of the parameters are null-checked in the constructor body (per source), but `text` and `id` are non-nullable reference types (C# 8+), implying callers must provide non-null values.
|
||||
- `text`: The string content being pasted.
|
||||
- `extraProperty`: The `IExtraProperty` instance that triggered the event (assigned to `Sender`).
|
||||
- `id`: A string identifier for the paste operation (e.g., correlation ID, control ID).
|
||||
- `tag`: An arbitrary object for caller-defined metadata.
|
||||
|
||||
- **`string Text { get; }`**
|
||||
Immutable property containing the pasted text.
|
||||
|
||||
- **`object Sender { get; }`**
|
||||
Immutable property referencing the `IExtraProperty` instance passed into the constructor (i.e., the source control).
|
||||
|
||||
- **`string Id { get; }`**
|
||||
Immutable property holding the operation identifier.
|
||||
|
||||
- **`object Tag { get; }`**
|
||||
Immutable property for user-defined contextual data.
|
||||
|
||||
## 3. Invariants
|
||||
- All properties are **read-only** (no setters); instances are fully immutable after construction.
|
||||
- `Text` and `Id` are expected to be non-null (as declared with non-nullable reference types), though the constructor does not enforce this at runtime.
|
||||
- `Sender` is *always* the exact `IExtraProperty` instance passed as the second constructor parameter.
|
||||
- `Tag` may be `null` (no constraints specified).
|
||||
|
||||
## 4. Dependencies
|
||||
- **Depends on**:
|
||||
- `System` (core types: `string`, `object`)
|
||||
- `DTS.Common.Events` (namespace, likely contains event-related infrastructure)
|
||||
- `DTS.Common.Interface.ISO.ExtraProperties` (specifically `IExtraProperty` interface)
|
||||
- **Used by**: Event handlers subscribed to paste events (e.g., `ITextPastedEventArgs` consumers), likely in UI components managing extra property controls.
|
||||
|
||||
## 5. Gotchas
|
||||
- **No null-safety in constructor**: While `Text` and `Id` are non-nullable reference types, the constructor does not validate inputs—passing `null` to `text` or `id` will compile (with warnings suppressed or ignored) but may cause runtime failures downstream.
|
||||
- **`Sender` is misnamed**: The property is named `Sender` but stores `extraProperty` (not a generic UI sender like a control). This may confuse developers expecting `sender` to be the UI element.
|
||||
- **No validation of `id` uniqueness**: The `Id` field’s purpose is unclear without context—consumers must assume it is unique per operation or handle collisions.
|
||||
- **`Tag` semantics undefined**: The meaning of `Tag` is entirely caller-defined; no standard usage pattern is evident from this class alone.
|
||||
|
||||
None identified beyond the above.
|
||||
136
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Locking.md
Normal file
136
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Locking.md
Normal file
@@ -0,0 +1,136 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Locking/LockRecord.cs
|
||||
- Common/DTS.Common/Classes/Locking/LockError.cs
|
||||
- Common/DTS.Common/Classes/Locking/SensorsLocking.cs
|
||||
generated_at: "2026-04-16T03:16:01.173429+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "4c9a49fc0d53b85f"
|
||||
---
|
||||
|
||||
# Locking
|
||||
|
||||
## Documentation: `DTS.Common.Classes.Locking` Module
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module provides infrastructure for managing application-level locks on sensor-related data items within a distributed system. It defines core data structures (`LockRecord`, `LockError`) to represent lock state and error conditions, and a high-level locking coordinator (`SensorsLocking`) responsible for maintaining and validating locks on behalf of UI components (e.g., sensor editing controls). The module supports lock renewal, theft detection, and loss handling, integrating with logging (`APILogger`), event aggregation (`Prism.Events`), and a lower-level `LockManager` (referenced but not included here) for persistence operations.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `LockRecord` Class
|
||||
Represents a single active lock on a data item.
|
||||
|
||||
- **Constructor**
|
||||
```csharp
|
||||
public LockRecord(string user, string machine, DateTime createTime, DateTime lastUpdate, string itemKey, int itemCategory, int itemId)
|
||||
```
|
||||
Initializes a new lock record with the specified metadata. All properties are read-only after construction.
|
||||
|
||||
- **Properties**
|
||||
- `string LockingUserName` – Name of the user who acquired the lock.
|
||||
- `string LockingMachineName` – Hostname of the machine holding the lock.
|
||||
- `DateTime CreationTime` – Timestamp when the lock was first acquired.
|
||||
- `DateTime LastUpdated` – Timestamp of the last lock renewal/maintenance.
|
||||
- `string ItemKey` – Human-readable key identifying the locked item (e.g., sensor name).
|
||||
- `int ItemCategory` – Numeric category of the item (e.g., `LockCategories` enum value in DB).
|
||||
- `int ItemId` – Numeric ID of the locked item (e.g., sensor ID).
|
||||
|
||||
#### `LockError` Class
|
||||
Encapsulates error information from lock operations.
|
||||
|
||||
- **Constructor**
|
||||
```csharp
|
||||
public LockError(int error, string message, string user = null, string machine = null)
|
||||
```
|
||||
Creates an error instance with code, message, and optional lock holder details.
|
||||
|
||||
- **Properties**
|
||||
- `int ErrorCode` – Numeric error code (see constants below).
|
||||
- `string Message` – Human-readable description.
|
||||
- `string LockingUser` – User associated with the lock at time of error (empty if unknown).
|
||||
- `string LockingMachine` – Machine associated with the lock at time of error (empty if unknown).
|
||||
- `bool LockStolen => ErrorCode == LOCKSTOLEN_ERROR` – Indicates the lock was forcibly released by another user.
|
||||
- `bool LockLost => ErrorCode == LOCKDOESNTEXIST_ERROR` – Indicates the lock no longer exists in the backing store.
|
||||
|
||||
- **Constants**
|
||||
- `BAD_NETPATH_ERROR = 994` – Network path error (e.g., lost remote DB connection).
|
||||
- `SEM_TIMEOUT_ERROR = 995` – Semaphore timeout (e.g., connection failure).
|
||||
- `ITEM_NOT_FOUND = 996` – Referenced item not found.
|
||||
- `LOCKDOESNTEXIST_ERROR = 997` – Lock record missing (lock lost).
|
||||
- `LOCKSTOLEN_ERROR = 998` – Lock stolen by another user.
|
||||
- `UNKNOWN_ERROR = 999` – Generic/unspecified error.
|
||||
|
||||
#### `SensorsLocking` Class
|
||||
Manages lock lifecycle for sensor UI controls.
|
||||
|
||||
- **`Unlock(bool bCheckLock, string userName, int userId)`**
|
||||
Stops background lock renewal and attempts to release all tracked locks via `FreeLocks()`. Logs exceptions but does not propagate them.
|
||||
*Note: Parameter `bCheckLock` is unused in the current implementation.*
|
||||
|
||||
- **`IsCurrentlyLocked(LockRecord lockRecord)`**
|
||||
```csharp
|
||||
public bool IsCurrentlyLocked(LockRecord lockRecord)
|
||||
```
|
||||
Returns `true` if the provided `lockRecord` matches an item currently tracked by this instance (i.e., `ItemId` and `ItemCategory` match any entry in `_existingLocks`). Thread-safe via `MyLock`.
|
||||
|
||||
- **Private Methods (Referenced)**
|
||||
- `StopUpdating()` – Cancels background renewal task and waits up to `MAX_WAIT_TIME_MS` (10s) for completion. Returns `true` only if stopped cleanly.
|
||||
- `FreeLocks()` – Iterates over `_existingLocks` and calls `LockManager.FreeLoc` for each (implementation truncated in source).
|
||||
- `CheckLocks(bool publishErrors, string userName, int userId)` – Validates all tracked locks; on failure, clears `_existingLocks`, calls `WipeOutChanges()`, and publishes `PageErrorEvent` if `publishErrors` is `true`.
|
||||
- `CheckLock(...)` – *Not implemented* (`NotImplementedException`).
|
||||
- `WipeOutChanges()` – *Not implemented* (`NotImplementedException`).
|
||||
- `GetErrorMessage(LockError[] errors, LockRecord[] lockRecords)` – Builds a localized error message string for display, handling `LockStolen` and `LockLost` cases.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- `_existingLocks` is always `null` or a non-null array (never partially initialized).
|
||||
- Lock records in `_existingLocks` are only modified or cleared under the `MyLock` synchronization object.
|
||||
- `LockRecord` instances are immutable after construction (all properties are `readonly` or get-only).
|
||||
- `LockError.ErrorCode` is set once at construction and never modified.
|
||||
- Lock renewal/maintenance is performed periodically via `_updateTask`; failure to renew triggers `CheckLocks()` failure.
|
||||
- On *any* lock failure during `CheckLocks()`, `_existingLocks` is atomically reset to an empty array, and `WipeOutChanges()` is called (though implementation is missing).
|
||||
- `LockManager.FreeLoc` is assumed to be the canonical method for releasing locks (external dependency).
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### **Internal Dependencies (from imports)**
|
||||
- `DTS.Common.Events` – For `PageErrorEvent` and `PageErrorArg`.
|
||||
- `DTS.Common.SharedResource.Strings` – For localized strings (`StringResources.FailedToUpdateLock`, `LockStolen_Sensors`, `LockLost_Sensors`).
|
||||
- `DTS.Common.Utilities.Logging` – For `APILogger`.
|
||||
- `Prism.Events` – For `IEventAggregator` and `ContainerLocator.Container`.
|
||||
- `System.Threading.Tasks` – For `Task`, `CancellationTokenSource`.
|
||||
|
||||
#### **External Dependencies (inferred)**
|
||||
- `LockManager` – Referenced in `FreeLocks()` but not defined in the provided source. Critical dependency for lock acquisition/release.
|
||||
- `PageErrorEvent` – A Prism event used to publish UI-level errors.
|
||||
- `ContainerLocator.Container` – Prism/IoC container for resolving services (e.g., `IEventAggregator`).
|
||||
|
||||
#### **Depended Upon By**
|
||||
- UI controls (e.g., sensor editing forms) that need to track and release locks on sensor items.
|
||||
- Likely used in conjunction with `LockManager` for end-to-end locking workflows.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`CheckLock` and `WipeOutChanges` are unimplemented** (`NotImplementedException`). This module is incomplete and non-functional as-is.
|
||||
- **`bCheckLock` parameter in `Unlock()` is ignored** – The method always proceeds to `FreeLocks()` regardless of its value.
|
||||
- **`FreeLocks()` calls `LockManager.FreeLoc` without arguments** – The source is truncated (`FreeLoc` call is cut off), so the exact signature and required parameters (e.g., `LockRecord`) are unknown.
|
||||
- **`GetErrorMessage` uses `Array.Exists` with `ItemId`/`ItemCategory` but `IsCurrentlyLocked` does the same** – Redundant logic suggests potential for refactoring or inconsistency if `LockRecord` equality semantics change.
|
||||
- **No validation of `LockRecord` constructor parameters** – No null checks on `user`, `machine`, or `itemKey`; invalid values (e.g., empty `ItemKey`) may propagate silently.
|
||||
- **`LockingUser`/`LockingMachine` in `LockError` default to `string.Empty`** – Not `null`, which simplifies UI display but may mask missing data.
|
||||
- **`MAX_WAIT_TIME_MS = 10000` is hardcoded** – No configuration or override mechanism for timeout duration.
|
||||
- **Thread-safety relies on `MyLock` but is inconsistent** – `IsCurrentlyLocked` uses `lock(MyLock)`, but `CheckLocks` and `FreeLocks` use `lock(MyLock)` only for reading `_existingLocks`; background task (`_updateTask`) state is managed separately.
|
||||
- **No explicit lock acquisition methods** – The module only handles *renewal* and *release* of *already-acquired* locks (via `LockManager`), implying lock acquisition happens elsewhere.
|
||||
|
||||
*None identified beyond the above.*
|
||||
281
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Sensors.md
Normal file
281
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Sensors.md
Normal file
@@ -0,0 +1,281 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Sensors/DisplayedCalibrationBehavior.cs
|
||||
- Common/DTS.Common/Classes/Sensors/ChannelSerialNumber.cs
|
||||
- Common/DTS.Common/Classes/Sensors/ChannelTypeUtility.cs
|
||||
- Common/DTS.Common/Classes/Sensors/SensorDbRecord.cs
|
||||
- Common/DTS.Common/Classes/Sensors/ZeroRef.cs
|
||||
- Common/DTS.Common/Classes/Sensors/CalMode.cs
|
||||
- Common/DTS.Common/Classes/Sensors/ThermocouplerRecord.cs
|
||||
- Common/DTS.Common/Classes/Sensors/StreamInputRecord.cs
|
||||
- Common/DTS.Common/Classes/Sensors/CANRecord.cs
|
||||
- Common/DTS.Common/Classes/Sensors/UARTRecord.cs
|
||||
- Common/DTS.Common/Classes/Sensors/ParseParameters.cs
|
||||
- Common/DTS.Common/Classes/Sensors/DigitalInputScaleMultiplier.cs
|
||||
- Common/DTS.Common/Classes/Sensors/DigitalOutDbRecord.cs
|
||||
- Common/DTS.Common/Classes/Sensors/SensorCalDbRecord.cs
|
||||
- Common/DTS.Common/Classes/Sensors/StreamOutputRecord.cs
|
||||
generated_at: "2026-04-16T03:14:41.949051+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "584219a9653a657a"
|
||||
---
|
||||
|
||||
# Sensor Data Model Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides core data structures and utility classes for representing sensor metadata, calibration, and configuration within the DTS system. It serves as the foundational data layer for sensor management, enabling serialization/deserialization of sensor records from databases, handling of various sensor types (thermocouple, stream input/output, CAN, UART, digital output), and supporting calibration workflows including zero-reference methods and calibration mode configurations. The module bridges raw database records and higher-level business logic by encapsulating sensor-specific properties, validation rules, and conversion utilities.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Classes
|
||||
|
||||
#### `DisplayedCalibrationBehavior`
|
||||
- **Properties**:
|
||||
- `CalibrationBehavior` (`DTS.Common.Enums.Sensors.CalibrationBehaviors`): The underlying calibration behavior enum value.
|
||||
- `DisplayString` (`string`): Human-readable string representation of the behavior.
|
||||
- **Methods**:
|
||||
- `ToString()`: Returns `DisplayString`.
|
||||
|
||||
#### `ChannelSerialNumber`
|
||||
- **Methods**:
|
||||
- `SerialNumberFromChannel(bool isTestSpecificEmbedded, string testSpecificEmbeddedSensor, string sensorDataSerialNumber)`: Returns `testSpecificEmbeddedSensor` if `isTestSpecificEmbedded` is true; otherwise returns `sensorDataSerialNumber`.
|
||||
|
||||
#### `ChannelTypeUtility`
|
||||
- **Nested Enum**:
|
||||
- `KnownChannelTypes`: Enum of known 2-character channel type codes (VS, VU, SB, TI, TC, CT, XP, P4, VF, NB, EX, X1, R1, VO, CO, CP).
|
||||
- **Methods**:
|
||||
- `ParseSensorKnownChannelType(string sensorName)`: Extracts the first two characters of `sensorName` (uppercased) and returns them if they match a `KnownChannelTypes` value; otherwise returns `string.Empty`. Returns `string.Empty` if `sensorName` is null/empty or shorter than 2 characters.
|
||||
|
||||
#### `ZeroRef`
|
||||
- **Nested Enum**:
|
||||
- `ZeroType`: Defines zeroing methods: `AverageOverTime` (0), `UsePreEventDiagnostics` (1), `UseZeroMv` (2).
|
||||
- **Properties**:
|
||||
- `ZeroMethod` (`ZeroType`): The selected zeroing method.
|
||||
- **Constructors**:
|
||||
- `ZeroRef(string zeroref)`: Parses `zeroref` ("0", "1", or "2") into `ZeroType`; throws `NotSupportedException` for invalid values.
|
||||
- `ZeroRef(ZeroType type)`: Initializes with specified `ZeroType`.
|
||||
- **Methods**:
|
||||
- `ToString()`: Returns "0", "1", or "2" based on `ZeroMethod`.
|
||||
|
||||
#### `CalMode`
|
||||
- **Properties**:
|
||||
- `ShuntCheck` (`bool`): True if first character is 'S', false if 'I'.
|
||||
- `FullBridge` (`bool`): True if second character is 'D', false if 'S'.
|
||||
- `Filter` (`bool`): True if third character is 'F', false if 'B'.
|
||||
- **Constructors**:
|
||||
- `CalMode(string value)`: Parses a 3-character string (`value[0]` = shunt, `value[1]` = bridge, `value[2]` = filter); throws `NotSupportedException` for invalid characters.
|
||||
- `CalMode()`: Parameterless constructor (properties default to `false`).
|
||||
- **Methods**:
|
||||
- `ToString()`: Returns a 3-character string in format `[S/I][D/S][F/B]`.
|
||||
|
||||
#### `SensorDbRecord`
|
||||
- **Properties**:
|
||||
- `id` (`int`): Database ID.
|
||||
- `SensorType` (`short`): Sensor type identifier.
|
||||
- `SerialNumber` (`string`): Sensor serial number.
|
||||
- **Constructors**:
|
||||
- `SensorDbRecord(IDataReader reader)`: Initializes properties from database reader using `Utility.GetInt`, `Utility.GetShort`, and `Utility.GetString`.
|
||||
- **Inherits**:
|
||||
- `TagAwareBase` with `TagType` overridden to `TagTypes.SensorModels`.
|
||||
|
||||
#### `ThermocouplerRecord`
|
||||
- **Properties**:
|
||||
- `Id` (`int`): Database ID.
|
||||
- `SerialNumber` (`string`): Serial number.
|
||||
- `LastModified` (`DateTime`): Last modification timestamp.
|
||||
- `LastUpdatedBy` (`string`): User who last modified.
|
||||
- `DoNotUse` (`bool`): Flag indicating sensor should not be used.
|
||||
- `Broken` (`bool`): Flag indicating sensor is broken.
|
||||
- **Constructors**:
|
||||
- `ThermocouplerRecord(ISensorData sd)`: Initializes from `ISensorData` interface.
|
||||
- `ThermocouplerRecord(IDataReader reader)`: Initializes from database reader using `Utility` methods.
|
||||
- **Inherits**:
|
||||
- `TagAwareBase` with `TagType` overridden to `TagTypes.Sensors`.
|
||||
- **Note**: All constructors include try/catch blocks logging failures via `APILogger`.
|
||||
|
||||
#### `StreamInputRecord`
|
||||
- **Properties**:
|
||||
- `Id` (`int`): Database ID.
|
||||
- `SerialNumber` (`string`): Serial number.
|
||||
- `LastModified` (`DateTime`): Last modification timestamp.
|
||||
- `LastUpdatedBy` (`string`): User who last modified.
|
||||
- `DoNotUse` (`bool`): Flag indicating sensor should not be used.
|
||||
- `Broken` (`bool`): Flag indicating sensor is broken.
|
||||
- `StreamInUDPAddress` (`string`): UDP address for streaming input; defaults to `"UDP://239.1.2.10:8400"`.
|
||||
- **Constructors**:
|
||||
- `StreamInputRecord(ISensorData sd)`: Initializes from `ISensorData`.
|
||||
- `StreamInputRecord(IDataReader reader)`: Initializes from database reader.
|
||||
- **Inherits**:
|
||||
- `TagAwareBase` with `TagType` overridden to `TagTypes.Sensors`.
|
||||
|
||||
#### `CANRecord`
|
||||
- **Properties**:
|
||||
- `Id` (`int`): Database ID.
|
||||
- `SerialNumber` (`string`): Serial number.
|
||||
- `LastModified` (`DateTime`): Last modification timestamp.
|
||||
- `LastUpdatedBy` (`string`): User who last modified.
|
||||
- `DoNotUse` (`bool`): Flag indicating sensor should not be used.
|
||||
- `Broken` (`bool`): Flag indicating sensor is broken.
|
||||
- `CanIsFD` (`bool`): Indicates if CAN FD is enabled; defaults to `EmbeddedSensors.CANISFD_DEFAULT`.
|
||||
- `CanArbBaseBitrate` (`int`): Arbitration base bitrate; defaults to `EmbeddedSensors.CANFD_ARB_BASE_BITRATE_DEFAULT`.
|
||||
- `CanArbBaseSJW` (`int`): Arbitration base SJW; defaults to `EmbeddedSensors.CANFD_1000000_ARB_BASE_SJW_MAX`.
|
||||
- `CanDataBitrate` (`int`): Data bitrate; defaults to `EmbeddedSensors.DATA_BITRATE_DEFAULT`.
|
||||
- `CanDataSJW` (`int`): Data SJW; defaults to `EmbeddedSensors.DATA_SJW_DEFAULT`.
|
||||
- `CanFileType` (`string`): File type; defaults to `EmbeddedSensors.FILETYPE_DEFAULT`.
|
||||
- **Constructors**:
|
||||
- `CANRecord(ISensorData sensor)`: Initializes from `ISensorData`.
|
||||
- `CANRecord(IDataReader reader)`: Initializes from database reader.
|
||||
- **Inherits**:
|
||||
- `TagAwareBase` with `TagType` overridden to `TagTypes.Sensors`.
|
||||
|
||||
#### `UARTRecord`
|
||||
- **Properties**:
|
||||
- `Id` (`int`): Database ID.
|
||||
- `SerialNumber` (`string`): Serial number.
|
||||
- `LastModified` (`DateTime`): Last modification timestamp.
|
||||
- `LastUpdatedBy` (`string`): User who last modified.
|
||||
- `DoNotUse` (`bool`): Flag indicating sensor should not be used.
|
||||
- `Broken` (`bool`): Flag indicating sensor is broken.
|
||||
- `UartBaudRate` (`uint`): Baud rate; defaults to `EmbeddedSensors.BAUD_RATE_DEFAULT`.
|
||||
- `UartDataBits` (`uint`): Data bits; defaults to `8`.
|
||||
- `UartStopBits` (`StopBits`): Stop bits; defaults to `StopBits.None`.
|
||||
- `UartParity` (`Parity`): Parity; defaults to `Parity.None`.
|
||||
- `UartFlowControl` (`Handshake`): Flow control; defaults to `Handshake.None`.
|
||||
- `UartDataFormat` (`UartDataFormat`): Data format; defaults to `UartDataFormat.Binary`.
|
||||
- **Constructors**:
|
||||
- `UARTRecord(ISensorData sensor)`: Initializes from `ISensorData`.
|
||||
- `UARTRecord(IDataReader reader)`: Initializes from database reader using `Enum.Parse` for enum properties.
|
||||
- **Inherits**:
|
||||
- `TagAwareBase` with `TagType` overridden to `TagTypes.Sensors`.
|
||||
|
||||
#### `DigitalOutDbRecord`
|
||||
- **Properties**:
|
||||
- `SerialNumber` (`string`): Serial number.
|
||||
- `DODelay` (`double`): Digital output delay in ms.
|
||||
- `DODuration` (`double`): Digital output duration in ms.
|
||||
- `ModifiedBy` (`string`): User who last modified.
|
||||
- `LastModified` (`DateTime`): Last modification timestamp.
|
||||
- `DatabaseId` (`int`): Database ID.
|
||||
- `ISOCode` (`string`): ISO code.
|
||||
- `ISOChannelName` (`string`): ISO channel name.
|
||||
- `UserCode` (`string`): User code.
|
||||
- `UserChannelName` (`string`): User channel name.
|
||||
- `Broken` (`bool`): Flag indicating sensor is broken.
|
||||
- `DoNotUse` (`bool`): Flag indicating sensor should not be used.
|
||||
- `DOMode` (`DigitalOutputModes`): Digital output mode; defaults to `DigitalOutputModes.CCNC`.
|
||||
- `LimitDuration` (`bool`): Flag limiting duration; defaults to `true`.
|
||||
- `Version` (`int`): Record version.
|
||||
- `TagsBlobBytes` (`byte[]`): Binary blob for user tags.
|
||||
- **Constructors**:
|
||||
- `DigitalOutDbRecord()`: Parameterless constructor.
|
||||
- `DigitalOutDbRecord(ISensorData copy, byte[] tagsBlobBytes)`: Initializes from `ISensorData`.
|
||||
- `DigitalOutDbRecord(IDigitalOutDbRecord copy)`: Copy constructor.
|
||||
- `DigitalOutDbRecord(IDataReader reader)`: Initializes from database reader.
|
||||
- **Inherits**:
|
||||
- `BasePropertyChanged`.
|
||||
|
||||
#### `SensorCalDbRecord`
|
||||
- **Properties**:
|
||||
- `CalibrationId` (`int?`): Database calibration ID; null if unknown.
|
||||
- `SerialNumber` (`string`): Sensor serial number.
|
||||
- `CalibrationDate` (`DateTime`): Calibration date.
|
||||
- `Username` (`string`): User who performed calibration.
|
||||
- `LocalOnly` (`bool`): Flag indicating local-only calibration.
|
||||
- `NonLinear` (`bool`): Flag indicating non-linear calibration.
|
||||
- `Records` (`ICalibrationRecords`): Calibration records.
|
||||
- `ModifyDate` (`DateTime`): Last modification date.
|
||||
- `IsProportional` (`bool`): Flag indicating proportional calibration.
|
||||
- `RemoveOffset` (`bool`): Flag indicating offset removal.
|
||||
- `SensitivityInspection` (`SensitivityInspectionType`): Sensitivity inspection type.
|
||||
- `CalibrationNote` (`string`): Calibration note (max 2048 chars).
|
||||
- `UsageCount` (`int`): Number of times calibration has been used.
|
||||
- `ZeroMethods` (`ZeroMethods`): Zeroing method definitions.
|
||||
- `CertificationDocuments` (`string[]`): Array of certification document paths.
|
||||
- `InitialOffsets` (`InitialOffsets`): Initial offset values.
|
||||
- `LinearAdded` (`bool`): Computed property indicating if linearization was added (based on `NonLinear`, `Records`, and `ZeroMethods` structure).
|
||||
- **Constructors**:
|
||||
- `SensorCalDbRecord()`: Parameterless constructor.
|
||||
- `SensorCalDbRecord(ISensorCalDbRecord copy)`: Copy constructor.
|
||||
- `SensorCalDbRecord(IDataReader reader, int actualDbVersion)`: Initializes from database reader; handles version-specific fields.
|
||||
- **Inherits**:
|
||||
- `BasePropertyChanged`.
|
||||
- **Note**: Constructors include try/catch blocks logging failures via `APILogger`. `NonLinear` setter has side effects: sets `Records.Records[0].Sensitivity = 1D`, `RemoveOffset = false`.
|
||||
|
||||
#### `StreamOutputRecord`
|
||||
- **Properties**:
|
||||
- `Id` (`int`): Database ID.
|
||||
- `SerialNumber` (`string`): Serial number.
|
||||
- `LastModified` (`DateTime`): Last modification timestamp.
|
||||
- `LastUpdatedBy` (`string`): User who last modified.
|
||||
- `DoNotUse` (`bool`): Flag indicating sensor should not be used.
|
||||
- `Broken` (`bool`): Flag indicating sensor is broken.
|
||||
- `StreamOutUDPProfile` (`UDPStreamProfile`): UDP streaming profile; defaults to `UDPStreamProfile.CH10_ANALOG_2HDR`.
|
||||
- `StreamOutUDPAddress` (`string`): UDP address; defaults to `"UDP://239.1.2.10:8400"`.
|
||||
- `StreamOutUDPTimeChannelId` (`ushort`): Time channel ID; defaults to `1`, range `[10, 100]`.
|
||||
- `StreamOutUDPDataChannelId` (`ushort`): Data channel ID; defaults to `3`, range `[10, 100]`.
|
||||
- `StreamOutUDPTmNSConfig` (`string`): TMNS config; defaults to `"(1,6,60,0,0,0,0,0)"`.
|
||||
- `StreamOutIRIGTimeDataPacketIntervalMs` (`ushort`): IRIG time data packet interval; defaults to `500`, range `[10, 1000]`.
|
||||
- `StreamOutTMATSIntervalMs` (`ushort`): TMATS interval; defaults to `1000`, range `[0, 65535]`.
|
||||
- **Constructors**:
|
||||
- `StreamOutputRecord(ISensorData sd)`: Initializes from `ISensorData`.
|
||||
- `StreamOutputRecord(IDataReader reader, int ClientDbVersion, int ConnectionDbVersion)`: Initializes from database reader; conditionally loads `TMATS_IntervalMS` based on version checks.
|
||||
- **Static Methods**:
|
||||
- `AvailableUDPStreamProfiles(int ConnectionDbVersion, bool UseAdvancedStreamingProfiles)`: Returns array of supported `UDPStreamProfile` values based on version and flag.
|
||||
- **Inherits**:
|
||||
- `TagAwareBase` with `TagType` overridden to `TagTypes.Sensors`.
|
||||
|
||||
#### `DigitalInputScaleMultiplier`
|
||||
- **Properties**:
|
||||
- `Form` (`Forms`): Scaling form; defaults to `Forms.ArbitraryLowAndHigh`.
|
||||
- `DefaultValue` (`double`): Value for digital 0 (OFF); defaults to `0`.
|
||||
- `ActiveValue` (`double`): Value for digital 1 (ON); defaults to `1`.
|
||||
- **Constructors**:
|
||||
- `DigitalInputScaleMultiplier()`: Initializes `DefaultValue = 0`.
|
||||
- `DigitalInputScaleMultiplier(DigitalInputScaleMultiplier copy)`: Copy constructor.
|
||||
- **Methods**:
|
||||
- `SimpleEquals(IDigitalInputScaleMultiplier rhs)`: Compares `Form`, `DefaultValue`, and `ActiveValue`.
|
||||
- `Equals(object obj)`: Overrides `Equals` for equality comparison.
|
||||
- `GetHashCode()`: Overrides `GetHashCode` using primes (31, 79, 127, 23).
|
||||
- `ToSerializeDbString()`: Serializes to string (only `ArbitraryLowAndHigh` supported).
|
||||
- `FromDbSerializeString(string s)`: Deserializes from string; throws `NotSupportedException` for invalid formats.
|
||||
- **Inherits**:
|
||||
- `IDigitalInputScaleMultiplier`.
|
||||
|
||||
#### `ParseParameters`
|
||||
- **Purpose**: Internal helper class to bundle parameters for CSV import operations (used in Wizard and DataPRO CSV import code).
|
||||
- **Properties**:
|
||||
- `ImportContainedSensorRanges` (`bool`): Default `false`.
|
||||
- `SensorData` (`ISensorData`): Sensor data source.
|
||||
- `ImportCulture` (`IFormatProvider`): Culture for parsing.
|
||||
- `Errors` (`List<string>`): Error list.
|
||||
- `IrtraccExponent` (`double`): IRTRACC exponent.
|
||||
- `SensorCal` (`ISensorCalibration`): Calibration data.
|
||||
- `Sensitivity` (`double`): Sensitivity value.
|
||||
- `SavedIsProportional` (`bool`): Saved proportional flag.
|
||||
- `SavedRemoveOffset` (`bool`): Saved remove offset flag.
|
||||
- `StripBackslash` (`bool`): Flag for backslash stripping.
|
||||
- `OriginalOffset` (`double`): Original offset value; defaults to `double.NaN`.
|
||||
- `ZeroType` (`ZeroMethodType`): Zero method type.
|
||||
- `ZeroEnd` (`double`): Zero method end value.
|
||||
- `ZeroStart` (`double`): Zero method start value.
|
||||
- `SquibDefaults` (`ISquibSettingDefaults`): Squib defaults.
|
||||
- `DigitalOutDefaults` (`IDigitalOutDefaults`): Digital output defaults.
|
||||
- `SensorGroupNameLookup` (`Dictionary<string, string>`): Sensor group name lookup.
|
||||
- `SensorGroupTypeLookup` (`Dictionary<string, string>`): Sensor group type lookup.
|
||||
- `GroupNameToTestObjectLookup` (`Dictionary<string, string>`): Group name to test object lookup.
|
||||
- `SensorTestObject` (`string`): Sensor test object.
|
||||
- `UseISOCodeFilterMapping` (`bool`): Flag for ISO code filter mapping.
|
||||
- `UseZeroForUnfiltered` (`bool`): Flag for zeroing unfiltered data.
|
||||
- `SensorISOCode` (`Dictionary<string, string>`): Sensor ISO code mapping.
|
||||
- `SensorISOChannelName` (`Dictionary<string, string>`): Sensor ISO channel name mapping.
|
||||
- `SensorUserCode` (`Dictionary<string, string>`): Sensor user code mapping.
|
||||
- `SensorUserChannelName` (`Dictionary<string, string>`): Sensor user channel name mapping.
|
||||
- `SensorDASSerialNumber` (`Dictionary<string, string>`): Sensor DAS serial number mapping.
|
||||
- `SensorDASChannelIndex` (`Dictionary<string, int>`): Sensor DAS channel index mapping.
|
||||
- **Note**: Documentation states this class is internal and may be refactored when DataPRO CSV import is removed.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`ChannelSerialNumber.SerialNumberFromChannel`**: Returns exactly one of the two input serial number strings based on `isTestSpecificEmbedded`; never returns `
|
||||
@@ -0,0 +1,167 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Sensors/AnalogDiagnostics/DiagnosticRun.cs
|
||||
- Common/DTS.Common/Classes/Sensors/AnalogDiagnostics/DiagnosticEntry.cs
|
||||
generated_at: "2026-04-16T03:18:16.331578+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "00d9f02148080370"
|
||||
---
|
||||
|
||||
# DiagnosticRun and DiagnosticEntry Documentation
|
||||
|
||||
## 1. Purpose
|
||||
This module defines core data transfer objects (`DiagnosticRun` and `DiagnosticEntry`) used to represent analog sensor diagnostic test sessions and individual channel measurements within the DTS (Data Transfer System) framework. `DiagnosticRun` models a single diagnostic test execution (e.g., a pre-test or post-test run), capturing metadata like user, test ID, and run type. `DiagnosticEntry` models a single sensor channel’s diagnostic results within a run, including measured values (excitation, offset, range, noise, shunt), status flags, and associated sensor/DAS (Data Acquisition System) identification. These classes are primarily used for deserializing data from SQL Server database queries (via `SqlDataReader`) and serve as the canonical in-memory representation of diagnostic test data for reporting, analysis, and persistence.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `DiagnosticRun`
|
||||
- **`DiagnosticRun()`**
|
||||
Parameterless constructor; initializes all properties to their default values (`null` for nullable types, `string.Empty` for strings, `true` for `PreTest`).
|
||||
|
||||
- **`DiagnosticRun(SqlDataReader reader)`**
|
||||
Constructor that populates the object from a `SqlDataReader` positioned on a valid row. Reads columns: `Id`, `DataPROUser`, `TestId`, `TestName`, `PreTest`. Skips assignment if the column value is `DBNull.Value`.
|
||||
|
||||
- **`long? Id { get; set; }`**
|
||||
Database primary key or unique identifier for the diagnostic run. Nullable; defaults to `null`.
|
||||
|
||||
- **`string DataPROUser { get; set; }`**
|
||||
Username of the operator who executed the diagnostic run. Defaults to `string.Empty`.
|
||||
|
||||
- **`int? TestId { get; set; }`**
|
||||
Foreign key or identifier linking to a specific test configuration. Nullable; defaults to `null`.
|
||||
|
||||
- **`string TestName { get; set; }`**
|
||||
Human-readable name of the test being run. Defaults to `string.Empty`.
|
||||
|
||||
- **`bool PreTest { get; set; }`**
|
||||
Indicates whether this run is a *pre-test* (`true`) or *post-test* (`false`). Defaults to `true`.
|
||||
|
||||
---
|
||||
|
||||
### `DiagnosticEntry`
|
||||
- **`DiagnosticEntry()`**
|
||||
Parameterless constructor; initializes all properties to their default values (`null` for nullable types, `0` for numeric primitives, `DateTime.MinValue` for `Timestamp`, `DiagnosticStatus.Untested` for status fields, `string.Empty` for strings).
|
||||
|
||||
- **`DiagnosticEntry(SqlDataReader reader)`**
|
||||
Constructor that populates the object from a `SqlDataReader` row. Reads columns: `Id`, `DiagnosticRunId`, `Excitation`, `ExcitationStatus`, `Offset`, `OffsetStatus`, `ActualRange`, `ActualRangeStatus`, `Noise`, `NoiseStatus`, `Shunt`, `ShuntStatus`, `SensorId`, `SensorSerialNumber`, `DASId`, `DASSerialNumber`, `DASChannelIdx`, `UserCode`, `UserChannelName`, `IsoCode`, `IsoChannelName`, `ScaleFactor`, `CalibrationRecordId`, `CalibrationRecordXML`, `Timestamp`. Skips assignment if the column value is `DBNull.Value`.
|
||||
|
||||
- **`long? Id { get; set; }`**
|
||||
Database primary key or unique identifier for the diagnostic entry. Nullable; defaults to `null`.
|
||||
|
||||
- **`long DiagnosticRunId { get; set; }`**
|
||||
Foreign key linking this entry to a `DiagnosticRun`. Non-nullable; defaults to `-1`.
|
||||
|
||||
- **`double? Excitation { get; set; }`**
|
||||
Measured excitation voltage (e.g., in mV/V). Nullable; defaults to `null`.
|
||||
|
||||
- **`DiagnosticStatus ExcitationStatus { get; set; }`**
|
||||
Status of the excitation measurement (e.g., Passed, Failed, Untested). Defaults to `DiagnosticStatus.Untested`.
|
||||
|
||||
- **`double? Offset { get; set; }`**
|
||||
Measured offset voltage. Nullable; defaults to `null`.
|
||||
|
||||
- **`DiagnosticStatus OffsetStatus { get; set; }`**
|
||||
Status of the offset measurement. Defaults to `DiagnosticStatus.Untested`.
|
||||
|
||||
- **`double? ActualRange { get; set; }`**
|
||||
Measured actual range (e.g., span). Nullable; defaults to `null`.
|
||||
|
||||
- **`DiagnosticStatus ActualRangeStatus { get; set; }`**
|
||||
Status of the range measurement. Defaults to `DiagnosticStatus.Untested`.
|
||||
|
||||
- **`double? Noise { get; set; }`**
|
||||
Measured noise level. Nullable; defaults to `null`.
|
||||
|
||||
- **`DiagnosticStatus NoiseStatus { get; set; }`**
|
||||
Status of the noise measurement. Defaults to `DiagnosticStatus.Untested`.
|
||||
|
||||
- **`double? Shunt { get; set; }`**
|
||||
Measured shunt calibration value. Nullable; defaults to `null`.
|
||||
|
||||
- **`DiagnosticStatus ShuntStatus { get; set; }`**
|
||||
Status of the shunt measurement. Defaults to `DiagnosticStatus.Untested`.
|
||||
|
||||
- **`int? SensorId { get; set; }`**
|
||||
Identifier for the sensor being tested. Nullable; defaults to `null`.
|
||||
|
||||
- **`string SensorSerialNumber { get; set; }`**
|
||||
Serial number of the sensor. Defaults to `string.Empty`.
|
||||
|
||||
- **`int? DASId { get; set; }`**
|
||||
Identifier for the Data Acquisition System used. Nullable; defaults to `null`.
|
||||
|
||||
- **`string DASSerialNumber { get; set; }`**
|
||||
Serial number of the DAS. Defaults to `string.Empty`.
|
||||
|
||||
- **`int DASChannelIdx { get; set; }`**
|
||||
Zero-based index of the channel on the DAS. Defaults to `0`.
|
||||
|
||||
- **`string UserCode { get; set; }`**
|
||||
User-defined code or label for the channel. Defaults to `string.Empty`.
|
||||
|
||||
- **`string UserChannelName { get; set; }`**
|
||||
User-friendly name for the channel. Defaults to `string.Empty`.
|
||||
|
||||
- **`string IsoCode { get; set; }`**
|
||||
ISO-standard code for the channel configuration. Defaults to `string.Empty`.
|
||||
|
||||
- **`string IsoChannelName { get; set; }`**
|
||||
ISO-standard name for the channel. Defaults to `string.Empty`.
|
||||
|
||||
- **`double ScaleFactor { get; set; }`**
|
||||
Scaling factor applied to raw measurements. Defaults to `1`.
|
||||
|
||||
- **`int CalibrationRecordId { get; set; }`**
|
||||
Identifier linking to a calibration record. Non-nullable; defaults to `-1`.
|
||||
|
||||
- **`string CalibrationRecordXML { get; set; }`**
|
||||
XML blob containing full calibration record details. Defaults to `string.Empty`.
|
||||
|
||||
- **`DateTime Timestamp { get; set; }`**
|
||||
Timestamp of when the diagnostic entry was recorded. Defaults to `DateTime.MinValue`.
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
- **`DiagnosticRunId` in `DiagnosticEntry` is non-nullable and defaults to `-1`**, implying a valid `DiagnosticRun` must be associated (though `-1` may indicate an unassigned or invalid state).
|
||||
- **`DASChannelIdx` is a non-nullable `int` defaulting to `0`**, suggesting zero-based indexing is assumed.
|
||||
- **All `DiagnosticStatus` properties default to `DiagnosticStatus.Untested`**, indicating a safe initial state before validation.
|
||||
- **`PreTest` defaults to `true`**, implying the system assumes pre-test unless explicitly marked otherwise.
|
||||
- **Null handling in constructors**: Values from `SqlDataReader` are only assigned if `!DBNull.Value.Equals(...)`. This means missing database columns or `NULL` values result in the property retaining its default value (e.g., `null`, `0`, `string.Empty`, `DiagnosticStatus.Untested`).
|
||||
- **`DiagnosticEntry` properties map directly to database column names** (e.g., `reader["Timestamp"]` → `Timestamp` property). Column name casing must match exactly in the database.
|
||||
|
||||
## 4. Dependencies
|
||||
- **Depends on**:
|
||||
- `DTS.Common.Interface.Sensors.AnalogDiagnostics` namespace (for `IDiagnosticRun` and `IDiagnosticEntry` interfaces).
|
||||
- `System.Data.SqlClient` (for `SqlDataReader` usage).
|
||||
- `DiagnosticStatus` enum (used in `DiagnosticEntry` properties; defined in `DTS.Common.Interface.Sensors.AnalogDiagnostics`, not shown in source).
|
||||
- **Depended on by**:
|
||||
- Data access layers (e.g., repositories or data readers) that populate these objects from SQL queries.
|
||||
- Reporting or analysis modules that consume diagnostic test results.
|
||||
- Likely used in conjunction with `IDiagnosticRun`/`IDiagnosticEntry` interfaces for testability or inversion of control.
|
||||
|
||||
## 5. Gotchas
|
||||
- **`DASChannelIdx` is read as `short` from `SqlDataReader` but stored as `int`**:
|
||||
```csharp
|
||||
DASChannelIdx = (short)reader["DASChannelIdx"];
|
||||
```
|
||||
This may cause runtime exceptions if the database column is larger than `Int16` (e.g., `int` or `bigint`). Type mismatch is not validated at compile time.
|
||||
|
||||
- **`DiagnosticStatus` cast assumes underlying type is `short`**:
|
||||
```csharp
|
||||
ExcitationStatus = (DiagnosticStatus)(short)reader["ExcitationStatus"];
|
||||
```
|
||||
If the database column is stored as `int` or `tinyint`, this cast may throw `InvalidCastException` or produce incorrect values.
|
||||
|
||||
- **No validation or business logic**: These are pure DTOs. Consumers must enforce constraints (e.g., `DiagnosticRunId != -1`, `PreTest` semantics).
|
||||
|
||||
- **Default `DiagnosticRunId = -1` is ambiguous**: May indicate "uninitialized" or "invalid", but no explicit check or constant is defined for this sentinel value.
|
||||
|
||||
- **No immutability guarantees**: All properties have public setters; objects can be mutated after construction.
|
||||
|
||||
- **`Timestamp` property name vs. database column**: The property is named `Timestamp` (PascalCase), but SQL Server column is likely `Timestamp` (case-insensitive). However, if the DB uses `timestamp` (deprecated synonym for `rowversion`) instead of `datetime`, the cast `(DateTime)reader["Timestamp"]` will fail.
|
||||
|
||||
- **No null-safety for string properties**: If `reader["DataPROUser"]` returns `null` (not `DBNull`), the cast `(string)reader["..."]` succeeds but may yield `null` (not `string.Empty`). Only `DBNull` is guarded against.
|
||||
|
||||
- **No error handling in constructor**: Exceptions from invalid casts or missing columns propagate unhandled.
|
||||
@@ -0,0 +1,46 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Sensors/SensorsList/DragAndDropPayload.cs
|
||||
generated_at: "2026-04-16T03:18:26.859220+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "7132134efcdc1e7d"
|
||||
---
|
||||
|
||||
# SensorsList
|
||||
|
||||
## 1. Purpose
|
||||
This module defines a data carrier class, `DragAndDropPayload`, used to encapsulate drag-and-drop operations involving sensor items in the DTS (presumably *Data Transfer System* or domain-specific) UI. It serializes an array of `IDragAndDropItem` objects (representing sensor entities) into a strongly-typed payload, enabling safe and consistent data exchange during drag-and-drop interactions—such as reordering, copying, or moving sensors between views or containers—by leveraging standardized clipboard/data format strings.
|
||||
|
||||
## 2. Public Interface
|
||||
- **`DragAndDropPayload(IDragAndDropItem[] items)`**
|
||||
Constructor that initializes the payload with a non-null array of `IDragAndDropItem` objects. The array is stored directly (no defensive copy is performed).
|
||||
- **`IDragAndDropItem[] Items { get; }`**
|
||||
Read-only property exposing the array of drag-and-drop items contained in this payload.
|
||||
- **`const string FORMAT`**
|
||||
A constant string `"DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload"` representing the primary data format identifier for serialization/deserialization (e.g., in `DataObject` or clipboard operations).
|
||||
- **`const string ALT_FORMAT`**
|
||||
A constant string `"ALT_DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload"` representing an alternate format identifier, likely used for context-sensitive operations (e.g., Alt+drag).
|
||||
- **`const string CTRL_FORMAT`**
|
||||
A constant string `"CTRL_DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload"` representing a format identifier for modifier-key-specific drag operations (e.g., Ctrl+drag for copying).
|
||||
|
||||
## 3. Invariants
|
||||
- `Items` is never `null` (enforced by constructor: passing `null` would throw `ArgumentNullException` at runtime if not handled elsewhere, but the source does not show validation—see *Gotchas*).
|
||||
- `Items` is not defensively copied; the array reference is stored as-is, so external mutation of the array *after* construction will affect the payload’s state.
|
||||
- The three format constants are mutually distinct and follow a naming convention: base format + optional modifier prefixes (`ALT_`, `CTRL_`).
|
||||
- No ordering guarantees are specified for the `Items` array—its semantics (e.g., sorted, insertion-ordered) are determined by the caller.
|
||||
|
||||
## 4. Dependencies
|
||||
- **Depends on**:
|
||||
- `DTS.Common.Interface.Sensors.SensorsList.IDragAndDropItem` (interface, likely defining contract for draggable sensor items).
|
||||
- **Depended on by**:
|
||||
- UI components handling drag-and-drop (e.g., `ListView`, `TreeView`, custom drop zones) that serialize/deserialize this payload using the `FORMAT` constants.
|
||||
- Serialization/deserialization logic (not visible here) that uses the `FORMAT` strings to reconstruct `DragAndDropPayload` instances.
|
||||
- Likely used in conjunction with WPF/WinForms drag-drop APIs (e.g., `DragEventArgs.Data.GetData(FORMAT)`).
|
||||
|
||||
## 5. Gotchas
|
||||
- **No null-safety in constructor**: The constructor accepts `items` without validation; passing `null` will result in `Items` being `null`, potentially causing `NullReferenceException` at runtime when accessed.
|
||||
- **No defensive copy**: Callers can mutate the `Items` array after construction by retaining a reference to the original array, breaking immutability expectations.
|
||||
- **Format string semantics are implicit**: The distinction between `FORMAT`, `ALT_FORMAT`, and `CTRL_FORMAT` is not documented in this file—consumers must infer behavior from naming (e.g., `ALT_FORMAT` may indicate "move" vs. "copy" semantics), but this is not guaranteed.
|
||||
- **No versioning or backward compatibility handling**: If `IDragAndDropItem` evolves, deserialization of older payloads may fail silently or corrupt data.
|
||||
- **None identified from source alone.** *(Note: The above gotchas are inferred from common pitfalls in similar patterns, but strictly speaking, the source file does not explicitly confirm or deny them.)*
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Sensors/StreamOut/UDPStreamProfilePacket.cs
|
||||
generated_at: "2026-04-16T03:18:20.383714+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "d7985184134cc083"
|
||||
---
|
||||
|
||||
# StreamOut
|
||||
|
||||
## 1. Purpose
|
||||
The `UDPStreamProfilePacket` class defines the structural metadata for a UDP-based stream profile packet used in sensor data transmission. It encapsulates fixed-size header and payload configuration parameters—such as header lengths, channel-specific data identifiers, timing information, and payload scaling—required to correctly serialize/deserialize or interpret raw UDP packets conforming to a proprietary sensor streaming protocol. This class serves as a data contract for constructing or parsing stream profile packets in the DTS sensor infrastructure.
|
||||
|
||||
## 2. Public Interface
|
||||
All members are public properties with `int` type and default values initialized inline.
|
||||
|
||||
- **`TransHeader`** (`int`, default `4`)
|
||||
Represents the size (in bytes) of the transport header. Default value is `4`.
|
||||
|
||||
- **`TimeHeader`** (`int`, default `24`)
|
||||
Represents the size (in bytes) of the primary timestamp header. Default value is `24`.
|
||||
|
||||
- **`SecondTimeHeader`** (`int`, default `0`)
|
||||
Represents the size (in bytes) of a secondary timestamp header, if present. Default is `0`, indicating absence.
|
||||
|
||||
- **`ChannelSpecificDataWord`** (`int`, default `0`)
|
||||
Identifier or size (in bytes) for channel-specific data word; semantics unclear from source. Default is `0`.
|
||||
|
||||
- **`PCMChannelSpecificDataWord`** (`int`, default `0`)
|
||||
Identifier or size (in bytes) for PCM (Pulse Code Modulation) channel-specific data word; semantics unclear from source. Default is `0`.
|
||||
|
||||
- **`Id`** (`int`, default `0`)
|
||||
Packet or stream identifier. Default is `0`.
|
||||
|
||||
- **`SampleTime`** (`int`, default `0`)
|
||||
Timestamp or sample time value (units unclear—likely milliseconds or microseconds). Default is `0`.
|
||||
|
||||
- **`PayloadFactor`** (`int`, default `2`)
|
||||
Multiplicative factor applied to derive payload size or configure payload layout. Default is `2`.
|
||||
|
||||
- **`Trailer`** (`int`, default `0`)
|
||||
Size (in bytes) of the packet trailer (e.g., checksum, padding, or footer). Default is `0`.
|
||||
|
||||
## 3. Invariants
|
||||
- All properties are nullable-free value types (`int`) and always hold a non-null integer value.
|
||||
- No explicit validation is enforced on property values (e.g., negative sizes or zero `PayloadFactor` are allowed unless constrained elsewhere).
|
||||
- No ordering guarantees are implied (e.g., `TransHeader + TimeHeader + SecondTimeHeader + ...` is not validated against total packet size).
|
||||
- Default values are statically assigned and immutable unless explicitly modified by consumer code.
|
||||
|
||||
## 4. Dependencies
|
||||
- **Imports**:
|
||||
- `System`, `System.Collections.Generic`, `System.Linq`, `System.Runtime.Remoting.Channels`, `System.Text`, `System.Threading.Tasks`
|
||||
- `System.Runtime.Remoting.Channels` is imported but unused (no remoting types referenced in the class).
|
||||
- **Namespace usage**:
|
||||
- Nested under `DTS.Common.Classes.Sensors.StreamOut`, implying integration with other sensor/streaming components (e.g., `UDPStreamProfile`, `SensorStreamManager`).
|
||||
- **Depended upon**:
|
||||
- Inferred to be used by serialization/deserialization logic for UDP sensor streams (e.g., packet builders, parsers, or configuration modules), though no direct references are visible in this file.
|
||||
|
||||
## 5. Gotchas
|
||||
- **Ambiguous semantics**: Units and exact meaning of fields (e.g., `PayloadFactor`, `ChannelSpecificDataWord`, `SampleTime`) are not documented in this class. Their interpretation depends on external protocol specs or companion code.
|
||||
- **Unused import**: `System.Runtime.Remoting.Channels` is imported but unused—likely legacy or accidental.
|
||||
- **No immutability or validation**: Properties are mutable and lack validation; consumers must ensure consistency (e.g., non-negative header/trailer sizes).
|
||||
- **No constructor or factory pattern**: Relies on default initialization; no compile-time guarantee of valid combinations (e.g., `SecondTimeHeader > 0` may require `TimeHeader > 0`, but no enforcement exists).
|
||||
- **Hardcoded defaults**: Default values (`TransHeader=4`, `TimeHeader=24`, `PayloadFactor=2`) may reflect legacy protocol versions; changing them without coordinated updates could break interoperability.
|
||||
- **No documentation**: XML comments or inline explanations are absent, increasing reliance on external documentation or reverse engineering.
|
||||
|
||||
None identified beyond the above.
|
||||
124
enriched-qwen3-coder-next/Common/DTS.Common/Classes/TMAT.md
Normal file
124
enriched-qwen3-coder-next/Common/DTS.Common/Classes/TMAT.md
Normal file
@@ -0,0 +1,124 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/TMAT/TmtSingleFile.cs
|
||||
- Common/DTS.Common/Classes/TMAT/TmtSplitFiles.cs
|
||||
- Common/DTS.Common/Classes/TMAT/TMTBase.cs
|
||||
generated_at: "2026-04-16T03:16:31.984201+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "39a472cd530a38e8"
|
||||
---
|
||||
|
||||
# Documentation: TMATS Template Handling Module
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides functionality for reading, updating, and serializing TMATS (Test Measurement and Test Specification) template files used in DAS (Data Acquisition System) configuration workflows. It supports two template formats—single-file (`TmtSingleFile`) and split-file (`TmtSplitFile`)—and abstracts the underlying file structure through a common interface (`ITMTTemplate`) and base class (`TmtBase`). The module enables dynamic substitution of predefined placeholder patterns (e.g., `{TEST ID}`, `{{CHANNEL {0} NAME}}`) with runtime values, ensuring generated test configurations conform to TMATS specifications.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Enums (used in interface methods)
|
||||
|
||||
- **`TMTGlobalKeys`**
|
||||
Enum of global (non-channel-specific) placeholder keys. Each field is annotated with a `[TMTKey(...)]` attribute specifying the literal pattern to search for in template files (e.g., `{TEST ID}`, `{DAS SERIAL NUMBER}`). Used in `UpdateValue(TMTGlobalKeys, string)`.
|
||||
|
||||
- **`TMTChannelKeys`**
|
||||
Enum of channel-specific placeholder keys for *single-file* templates. Each field uses a format string with `{0}` for channel number (e.g., `{{CHANNEL {0} NAME}}`). Used in `UpdateValue(TMTChannelKeys, string, int)`.
|
||||
|
||||
- **`TMTChannelKeysEx`**
|
||||
Enum of channel-specific placeholder keys for *split-file* templates. Keys use simpler, non-formatted patterns (e.g., `{CHANNEL NAME}`, `{CHANNEL NUMBER}`). Used in `UpdateValue(TMTChannelKeysEx, string, int)`.
|
||||
|
||||
### Classes
|
||||
|
||||
#### `TMTKey` (Helper class)
|
||||
|
||||
- **`public static string GetKey(TMTGlobalKeys key)`**
|
||||
Returns the literal pattern string associated with the given `TMTGlobalKeys` enum value (e.g., `"TEST ID}"` → `"{TEST ID}"`).
|
||||
|
||||
- **`public static string GetKey(TMTChannelKeysEx key)`**
|
||||
Returns the literal pattern string for `TMTChannelKeysEx` keys.
|
||||
|
||||
- **`public static string GetKey(TMTChannelKeys key, int channelNumber)`**
|
||||
Returns the formatted pattern string for `TMTChannelKeys` keys, substituting `{0}` with `channelNumber` (e.g., `"{CHANNEL {0} NAME}"` → `"{CHANNEL 1 NAME}"` for `channelNumber=1`).
|
||||
|
||||
#### `TmtBase` (Abstract base class)
|
||||
|
||||
- **`public static string TMT_LimitString(string s)`**
|
||||
Truncates input string `s` to a maximum of 200 characters (per `TMT_MAX_CHANNEL_LENGTH`). Used to enforce TMATS file length constraints.
|
||||
|
||||
- **`public static void UpdateChannelField(...)`**
|
||||
High-level helper to update a single channel field in a template. Handles type-specific formatting (e.g., scaling, signedness, masking via `RunTestVariables.MaskEUMetaData`). Calls `template.UpdateValue(...)` internally.
|
||||
|
||||
- **`public static void UpdateGlobalField(...)`**
|
||||
High-level helper to update a single global field in a template. Populates fields like serial number, sample rate, channel IDs, timestamps, etc., using data from `IDASCommunication`, `IConfigurationData`, and parameters. Calls `template.UpdateValue(...)` internally.
|
||||
|
||||
- **`public static int GetNumberOfStreamedChannels(IDASCommunication das)`**
|
||||
Returns the number of streamed channels based on hardware type and module configuration. Special handling for `SLICE6_AIR_TC` (hardcoded 24) and reconfigurable devices (e.g., TSR AIR).
|
||||
|
||||
- **Abstract methods (must be implemented by derived classes):**
|
||||
- `public abstract void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber);`
|
||||
- `public abstract void UpdateValue(TMTGlobalKeys key, string value);`
|
||||
- `public abstract void UpdateValue(TMTChannelKeys key, string value, int channelNumber);`
|
||||
- `public abstract string[] GetAllLines();`
|
||||
|
||||
#### `TmtSingleFile` (Concrete implementation)
|
||||
|
||||
- **`public TmtSingleFile(string templateLocation)`**
|
||||
Constructor. Reads all lines from `templateLocation` into an internal `_allLines` list. Does *not* throw if file is missing; `_allLines` remains empty.
|
||||
|
||||
- **`public override void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber)`**
|
||||
Replaces *all* occurrences of `pattern = TMTKey.GetKey(key)` in `_allLines` with `value`. Does *not* consider channel context—applies to *all* matching lines.
|
||||
|
||||
- **`public override void UpdateValue(TMTGlobalKeys key, string value)`**
|
||||
Replaces *all* occurrences of `pattern = TMTKey.GetKey(key)` in `_allLines` with `value`.
|
||||
|
||||
- **`public override void UpdateValue(TMTChannelKeys key, string value, int channelNumber)`**
|
||||
Replaces *all* occurrences of `pattern = TMTKey.GetKey(key, channelNumber)` in `_allLines` with `value`.
|
||||
|
||||
- **`public override string[] GetAllLines()`**
|
||||
Returns a copy of `_allLines` as an array.
|
||||
|
||||
#### `TmtSplitFile` (Concrete implementation)
|
||||
|
||||
- **`public TmtSplitFile(string dasTemplate, string channelTemplate)`**
|
||||
Constructor. Reads global lines from `dasTemplate` into `_lines`, and channel template lines from `channelTemplate` into `_channelTemplate`. Does *not* throw if files are missing; corresponding lists remain empty.
|
||||
|
||||
- **`public override string[] GetAllLines()`**
|
||||
Returns concatenation of `_lines` (global section) followed by channel sections for all channel numbers present in `_allChannels`. Channel sections are inserted in ascending numeric order (from `min` to `max` key). If no channels exist, returns only `_lines`.
|
||||
|
||||
- **`public override void UpdateValue(TMTChannelKeysEx key, string value, int channelNumber)`**
|
||||
Ensures a channel entry exists for `channelNumber` in `_allChannels` (via `AddChannelIfNeeded`), then replaces *all* occurrences of `pattern = TMTKey.GetKey(key)` in that channel’s line list with `value`.
|
||||
|
||||
- **`public override void UpdateValue(TMTGlobalKeys key, string value)`**
|
||||
Replaces *all* occurrences of `pattern = TMTKey.GetKey(key)` in `_lines` with `value`.
|
||||
|
||||
- **`public override void UpdateValue(TMTChannelKeys key, string value, int channelNumber)`**
|
||||
Replaces *all* occurrences of `pattern = TMTKey.GetKey(key, channelNumber)` in `_lines` (global section) with `value`.
|
||||
⚠️ **Note**: This method does *not* operate on per-channel data in `_allChannels`—it updates the global template file.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Template file existence is not enforced**: Constructors for both `TmtSingleFile` and `TmtSplitFile` silently proceed if the specified file(s) do not exist, resulting in empty `_allLines`/`_lines`/`_channelTemplate` lists.
|
||||
- **Pattern matching is substring-based**: `Contains(pattern)` is used to locate lines for replacement. This may cause unintended matches if patterns are substrings of unrelated text (e.g., `{NAME}` would match `{NAME OF PROGRAM}`).
|
||||
- **All replacements are global per line list**: Each `UpdateValue` call replaces *every* occurrence of the pattern in the relevant line collection (e.g., all lines in `_allLines` for `TmtSingleFile`). There is no support for updating only the *first* occurrence or a specific line index.
|
||||
- **Channel keys for split files are stored separately**: In `TmtSplitFile`, `TMTChannelKeysEx` updates affect per-channel data in `_allChannels`, while `TMTChannelKeys` updates affect only the global `_lines`.
|
||||
- **Channel numbering is 1-based**: `UpdateChannelField` uses `1 + channelIndex` for `TMTChannelKeysEx.ChannelNumber`.
|
||||
- **String length is capped at 200 characters**: `TMT_LimitString` enforces this limit for channel names and other string fields.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
- **Enums**: `DTS.Common.Enums.DASFactory.TMTGlobalKeys`, `DTS.Common.Enums.DASFactory.TMTChannelKeys`, `DTS.Common.Enums.DASFactory.TMTChannelKeysEx` (defined in same file).
|
||||
- **Interfaces**: `DTS.Common.Interface.DASFactory.IDASCommunication`, `DTS.Common.Interface.DASFactory.Config.IConfigurationData`.
|
||||
- **Constants/Types**: `DTS.Common.Enums.DASFactory.DFConstantsAndEnums.ModuleType`, `DTS.Common.Enums.Hardware.HardwareTypes`, `DTS.Common.Constants.Constants.UDP_STREAM_CH10_TF2`, `RunTestVariables` (static class with `MaskEUMetaData` field).
|
||||
- **System**: `System.IO.File`, `System.Collections.Generic`, `System.Linq`, `System.Reflection`, `System.DateTime`.
|
||||
- **Consumers**: This module is used by higher-level code that generates TMATS files (e.g., test execution or configuration tools), likely via `TmtBase.UpdateChannelField` and `TmtBase.UpdateGlobalField`.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`TMTChannelKeys` in `TmtSplitFile` updates global lines, not per-channel lines**: Calling `UpdateValue(TMTChannelKeys, ...)` on a `TmtSplitFile` instance updates the global template file (`_lines`), *not* the per-channel template (`_channelTemplate` or `_allChannels`). This is likely unintentional and may cause incorrect behavior if channel-specific global keys (e.g., `{{CHANNEL {0} NAME}}`) are expected to be updated per channel.
|
||||
- **No validation of pattern existence**: `TMTKey.GetKey(...)` returns `string.Empty` if the enum value lacks a `[TMTKey]` attribute or reflection fails. This results in replacing empty strings (i.e., no-op or unintended global replacement).
|
||||
- **Substring matching may cause false positives**: Using `Contains(pattern)` can match patterns embedded in other text (e.g., `{CHANNEL 1 NAME}` would match lines containing `{{CHANNEL 10 NAME}}`).
|
||||
- **Channel numbering assumptions**: `GetNumberOfStreamedChannels` assumes specific hardware types and module counts. The logic for reconfigurable devices (e.g., TSR AIR) is hardcoded and may not cover all future configurations.
|
||||
- **No error handling for file I/O**: `File.ReadAllLines` may throw `IOException` or `UnauthorizedAccessException`, but these are not caught or handled.
|
||||
- **`_allChannels` dictionary may have gaps**: `GetAllLines` iterates from `min` to `max` key, inserting only existing channels. If channels 1, 2, and 5 exist, channels 3 and 4 are skipped—this may be intentional or a bug depending on TMATS spec requirements.
|
||||
- **`TMT_MAX_CHANNEL_LENGTH` is hardcoded**: While documented as 200 (increased from 50), this is not configurable and may need adjustment for future TMATS versions.
|
||||
158
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Tags.md
Normal file
158
enriched-qwen3-coder-next/Common/DTS.Common/Classes/Tags.md
Normal file
@@ -0,0 +1,158 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/Tags/TagAssignment.cs
|
||||
- Common/DTS.Common/Classes/Tags/Tag.cs
|
||||
- Common/DTS.Common/Classes/Tags/TagAwareBase.cs
|
||||
- Common/DTS.Common/Classes/Tags/TagsInstance.cs
|
||||
generated_at: "2026-04-16T03:17:02.180213+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "9217697aeaa1fbf6"
|
||||
---
|
||||
|
||||
# Tagging System Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides a tag-based association system for domain objects in the DTS application. It enables arbitrary metadata (tags) to be attached to various object types (e.g., devices, locations, users) via a many-to-many relationship. The system supports creating, querying, and associating tags with objects, using a combination of in-memory caching (`TagsInstance`) and database persistence. Tags themselves are immutable once created (no edit/delete/obsolete operations are exposed), and tag assignments are stored separately in a `TagAssignment` table. The `TagAwareBase` abstract class provides reusable tagging functionality for any domain class that needs to support tagging.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `TagAssignment` class (`DTS.Common.Classes.Tags.TagAssignment`)
|
||||
- **`int ObjectID { get; set; }`**
|
||||
The ID of the object (e.g., device, location) to which the tag is assigned.
|
||||
- **`int TagID { get; set; }`**
|
||||
The ID of the tag being assigned.
|
||||
- **`TagTypes ObjectType { get; set; }`**
|
||||
The type of the object (e.g., `TagTypes.Device`, `TagTypes.Location`). *Note: Property name is `ObjectType`, not `TagType`.*
|
||||
- **`TagAssignment()`**
|
||||
Default constructor.
|
||||
- **`TagAssignment(IDataReader reader)`**
|
||||
Constructor that initializes fields from a database reader using column names `"TagID"`, `"ObjectID"`, and `"ObjectType"`.
|
||||
|
||||
### `Tag` class (`DTS.Common.Classes.Tags.Tag`)
|
||||
- **`const int INVALID_ID = -1`**
|
||||
Sentinel value indicating an uninitialized or non-existent tag ID.
|
||||
- **`int ID { get; set; }`**
|
||||
Unique identifier for the tag.
|
||||
- **`string Text { get; set; }`**
|
||||
Human-readable tag text (case-sensitive, whitespace-sensitive).
|
||||
- **`bool IsObsolete { get; set; }`**
|
||||
Flag indicating whether the tag is obsolete. *Currently not used for filtering or validation in the provided code.*
|
||||
- **`Tag(string tagText, int tagId)`**
|
||||
Constructor that initializes `ID`, `Text`, and sets `IsObsolete = false`.
|
||||
- **`Tag(Tag copy)`**
|
||||
Copy constructor.
|
||||
- **`Tag(IDataReader reader)`**
|
||||
Constructor that initializes fields from a database reader using columns `"TagId"`, `"Obsolete"`, and `"TagText"`.
|
||||
- **`Tag()`**
|
||||
Default constructor.
|
||||
- **`object Clone()`**
|
||||
Returns a new `Tag` instance with identical `ID`, `Text`, and `IsObsolete` values.
|
||||
|
||||
### `TagAwareBase` abstract class (`DTS.Common.Classes.TagAwareBase`)
|
||||
- **`abstract TagTypes TagType { get; }`**
|
||||
Must be implemented by derived classes to specify the object type for tag assignments.
|
||||
- **`byte[] TagsBlobBytes { get; set; }`**
|
||||
Binary representation of `TagIDs` (int array → byte array). Setter silently fails if input is too short; logs exceptions.
|
||||
- **`int[] TagIDs { get; set; }`**
|
||||
Array of tag IDs currently assigned to this object. Setter replaces array with empty array if `null`.
|
||||
- **`void SetTagsFromCommaSeparatedString(string tagText, ...)`**
|
||||
Parses `tagText` by commas, trims leading whitespace per tag, and updates `TagIDs` and `TagIDs` property. *Note: Leading whitespace is trimmed, but trailing whitespace is preserved in tag text.*
|
||||
- **`virtual void SetTags(string[] tagsText, ...)`**
|
||||
Adds tags via `TagsInstance.AddRange`, then updates `TagIDs` using `TagsInstance.GetIDsFromTagText`. Raises `OnPropertyChanged("TagIDs")`.
|
||||
- **`string GetTagsAsCommaSeparatedString(TagsGetDelegate tagsGet)`**
|
||||
Returns comma-separated tag text (e.g., `"tag1,tag2"`), using `GetTagsArray` internally.
|
||||
- **`virtual string[] GetTagsArray(TagsGetDelegate tagsGet)`**
|
||||
Returns array of tag text strings corresponding to `TagIDs`.
|
||||
- **`virtual int[] GetTagIDs()`**
|
||||
Returns current `TagIDs`.
|
||||
- **`virtual void RemoveTags(string[] tagsText)`**
|
||||
Stub implementation — does nothing. *No-op.*
|
||||
- **`bool TagCompatible(string tags, TagsGetDelegate tagsGet)`**
|
||||
Returns `true` if *any* tag in the input comma-separated string matches *any* tag on this object. Empty/whitespace-only tags are ignored. Returns `true` if input is null/empty or all tags are empty.
|
||||
- **`virtual bool TagCompatible(int[] tags)`**
|
||||
Returns `true` if `tags` is empty or if there is any intersection between `tags` and `TagIDs`.
|
||||
- **`virtual bool HasIntersectingTag(int[] tags)`**
|
||||
Returns `true` if `tags` and `TagIDs` share at least one ID.
|
||||
- **`void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags, ...)`**
|
||||
Calls `SetTagsFromCommaSeparatedString`, then `Commit`.
|
||||
- **`void Commit(int id, TagTypes tagType, ...)`**
|
||||
Deletes existing assignments for `(tagType, id)` via `tagAssignmentsDelete`, then inserts new assignments for each ID in `TagIDs` via `tagAssignmentInsert`.
|
||||
- **`List<int> GetTagIdList(int objectId, TagTypes tagType, TagAssignmentsGet tagAssignmentsGet)`**
|
||||
Retrieves all tag assignments for given `tagType`, filters to those matching `objectId`, and returns distinct `TagID`s.
|
||||
|
||||
### `TagsInstance` class (`DTS.Common.Classes.Tags.TagsInstance`)
|
||||
- **`static TagsInstance GetTagsInstance(TagsGetDelegate tagsGet)`**
|
||||
Returns singleton instance (lazy-initialized). Requires `tagsGet` delegate for initial population.
|
||||
- **`bool AddTag(string tagText, ...)`**
|
||||
Adds `tagText` (trimmed of leading whitespace) to DB and cache if not already present. Returns `false` if tag already exists or input is null/empty.
|
||||
- **`static bool MigrateTag(string tagText, ...)`**
|
||||
Adds `tagText` to DB/cache (even if duplicate). Intended for data migration. *No deduplication.*
|
||||
- **`bool ContainsTag(string text)`**
|
||||
Checks if `text` exists in in-memory cache (case-sensitive).
|
||||
- **`static bool[] AddRange(string[] tagText, ...)`**
|
||||
Calls `AddTag` for each element (trims leading whitespace). Returns array of success flags.
|
||||
- **`static int GetIDFromTagText(string tagText, TagsGetDelegate tagsGet, TagsGetIdDelegate tagsGetId)`**
|
||||
Looks up tag ID in DB via `tagsGetId`. Returns `Tag.INVALID_ID` (-1) if not found.
|
||||
- **`static int[] GetIDsFromTagText(string[] tagText, TagsGetDelegate tagsGet, TagsGetIdDelegate tagsGetId)`**
|
||||
Returns array of tag IDs for input texts, filtering out `Tag.INVALID_ID`.
|
||||
- **`static string GetTagTextFromID(int tagID, TagsGetDelegate tagsGet)`**
|
||||
Looks up tag text from in-memory cache. Returns `null` if invalid ID or not found.
|
||||
- **`static string[] GetTagTextFromIDs(int[] tagId, TagsGetDelegate tagsGet)`**
|
||||
Returns array of tag texts for IDs, skipping invalid IDs and null/empty text.
|
||||
- **`void UpdateList(TagsGetDelegate tagsGet)`**
|
||||
Refreshes in-memory cache by fetching all tags via `tagsGet(null, out tags)`.
|
||||
|
||||
### Delegates (`TagsInstance`)
|
||||
- **`TagsGetDelegate`**
|
||||
`ulong delegate(int? id, out ITag[] tags)` — Fetches tags by ID (or all if `id == null`).
|
||||
- **`TagsGetIdDelegate`**
|
||||
`ulong delegate(string text, out int? id)` — Fetches tag ID by text.
|
||||
- **`TagsInsertDelegate`**
|
||||
`ulong delegate(ref ITag tag)` — Inserts a tag into DB, updating `tag.ID`.
|
||||
- **`GetSqlCommandDelegate`**
|
||||
`SqlCommand delegate(bool bNewConnection)` — Factory for SQL commands.
|
||||
- **`TagAssignmentsGet`**
|
||||
`ulong delegate(TagTypes? tagType, out ITagAssignment[] records)` — Fetches assignments (optionally filtered by type).
|
||||
- **`TagAssignmentsDelete`**
|
||||
`ulong delegate(TagTypes objectType, int objectId)` — Deletes assignments for object.
|
||||
- **`TagAssignmentsInsert`**
|
||||
`ulong delegate(ITagAssignment tagAssignment)` — Inserts a single assignment.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Tag immutability**: Tags cannot be renamed, edited, or deleted in the current implementation. `Tag.Commit` only updates `ID` if the tag already exists in the DB; no other fields are persisted.
|
||||
- **Tag ID validity**: `Tag.INVALID_ID = -1` is used as a sentinel for uninitialized or non-existent tags. All tag ID lookups return this value on failure.
|
||||
- **Cache consistency**: `TagsInstance` maintains an in-memory cache (`_tagsLookup`) that is only updated on startup or when `AddTag`/`MigrateTag`/`UpdateList` is called. It is *not* automatically synchronized with DB changes.
|
||||
- **Whitespace handling**: Leading whitespace is trimmed from tag text during `AddTag`/`AddRange`/`SetTags`, but trailing whitespace is preserved in tag text and comparisons.
|
||||
- **Assignment integrity**: `TagAssignment` records require non-null `ObjectID`, `TagID`, and `ObjectType`. `Commit` deletes all prior assignments for an object before inserting new ones.
|
||||
- **Tag compatibility logic**: `TagCompatible(string)` returns `true` if *any* input tag matches *any* object tag (logical OR), not AND.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.Base.BasePropertyChanged`**
|
||||
Base class for `Tag`, `TagAssignment`, and `TagAwareBase` to support property change notifications.
|
||||
- **`DTS.Common.Interface.Tags`**
|
||||
Interfaces `ITag`, `ITagAssignment`, and `TagTypes` enum.
|
||||
- **`System.Data`**
|
||||
`IDataReader`, `SqlCommand`.
|
||||
- **`DTS.Common.Utilities.Logging`**
|
||||
`APILogger` for exception logging.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **`TagAwareBase`** is intended to be inherited by domain classes requiring tagging (e.g., device, location, user classes).
|
||||
- **`TagsInstance`** is used by `TagAwareBase` and callers to manage tag creation, lookup, and assignment.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **Property name mismatch**: In `TagAssignment`, the property `TagTypes ObjectType` is named `ObjectType`, *not* `TagType`. This may cause confusion.
|
||||
- **Whitespace trimming**: Only *leading* whitespace is trimmed during tag creation (`TrimStart()`), but not trailing. `"tag "` and `"tag"` are treated as distinct.
|
||||
- **No tag editing/deletion**: `Tag` objects cannot be edited, renamed, or deleted. `IsObsolete` is stored but unused in filtering or validation logic.
|
||||
- **Cache staleness**: `TagsInstance` cache is not auto-updated. If tags are added externally (e.g., via direct DB writes), `UpdateList` must be called manually.
|
||||
- **`RemoveTags` is a stub**: `TagAwareBase.RemoveTags` does nothing. No tag removal from objects is implemented.
|
||||
- **`TagCompatible` semantics**: `TagCompatible(string)` returns `true` if *any* input tag matches *any* object tag (OR logic), not all tags (AND). This may be counterintuitive.
|
||||
- **`TagsBlobBytes` setter ignores short arrays**: If `value.Length < sizeof(int)`, the setter returns without modifying `TagIDs`.
|
||||
- **`MigrateTag` bypasses deduplication**: Unlike `AddTag`, `MigrateTag` will insert duplicate tags into the DB/cache.
|
||||
- **`TagAssignment.ObjectType` type**: The property is named `ObjectType` but holds `TagTypes`, which likely represents the *object* type (e.g., device), not the tag type.
|
||||
@@ -0,0 +1,126 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/TestMetaData/TestEngineerDetailsDbRecord.cs
|
||||
- Common/DTS.Common/Classes/TestMetaData/CustomerDetailsDbRecord.cs
|
||||
- Common/DTS.Common/Classes/TestMetaData/LabratoryDetailsDbRecord.cs
|
||||
generated_at: "2026-04-16T03:15:34.968260+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "b20907858a69ef9c"
|
||||
---
|
||||
|
||||
# Documentation: Test Metadata Database Record Classes
|
||||
|
||||
## 1. Purpose
|
||||
These three classes—`TestEngineerDetailsDbRecord`, `CustomerDetailsDbRecord`, and `LabratoryDetailsDbRecord`—represent immutable data transfer objects (DTOs) for loading and storing metadata about test engineers, customers, and laboratories from a database. They implement `INotifyPropertyChanged` via `BasePropertyChanged` to support UI binding, and provide constructors for instantiation from an `IDataReader` (database query results) or from another instance of the same interface type. Each class encapsulates domain-specific fields (e.g., contact info, reference numbers) alongside common metadata fields (e.g., `LastModified`, `Version`, `LocalOnly`) used for auditing and synchronization. They serve as the foundational data layer for test metadata management within the DTS system.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `TestEngineerDetailsDbRecord`
|
||||
- **Namespace**: `DTS.Common.Classes.TestEngineerDetails`
|
||||
- **Implements**: `ITestEngineerDetailsDbRecord`
|
||||
- **Inherits**: `Base.BasePropertyChanged`
|
||||
|
||||
| Member | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| Constructor | `TestEngineerDetailsDbRecord()` | Default parameterless constructor. |
|
||||
| Constructor | `TestEngineerDetailsDbRecord(ITestEngineerDetailsDbRecord)` | Copy constructor: initializes all properties from another instance of the interface. |
|
||||
| Constructor | `TestEngineerDetailsDbRecord(IDataReader reader)` | Constructor from database: reads values using `Utility.GetString`, `Utility.GetDateTime`, `Utility.GetInt`, and `Utility.GetBool`. |
|
||||
| Property | `int TestEngineerId { get; set; }` | Internal database ID; defaults to `-1`; read-only in UI (`[ReadOnly(true)]`, `[Browsable(false)]`). |
|
||||
| Property | `string Name { get; set; }` | Internal name (likely primary identifier); defaults to `""`; read-only in UI. |
|
||||
| Property | `string TestEngineerName { get; set; }` | Display name; defaults to `"NOVALUE"`; marked with `[DisplayResource("TestEngineerName")]`. |
|
||||
| Property | `string TestEngineerPhone { get; set; }` | Phone number; defaults to `"NOVALUE"`; marked with `[DisplayResource("TestEngineerPhone")]`. |
|
||||
| Property | `string TestEngineerFax { get; set; }` | Fax number; defaults to `"NOVALUE"`; marked with `[DisplayResource("TestEngineerFax")]`. |
|
||||
| Property | `string TestEngineerEmail { get; set; }` | Email address; defaults to `"NOVALUE"`; marked with `[DisplayResource("TestEngineerEmail")]`. |
|
||||
| Property | `bool LocalOnly { get; set; }` | Indicates if record is local-only (not synchronized); defaults to `false`; read-only in UI. |
|
||||
| Property | `DateTime LastModified { get; set; }` | Timestamp of last modification; defaults to `DateTime.MinValue`; read-only in UI. |
|
||||
| Property | `string LastModifiedBy { get; set; }` | User who last modified the record; defaults to `""`; read-only in UI. |
|
||||
| Property | `int Version { get; set; }` | Version number for concurrency control; defaults to `-1`; read-only in UI. |
|
||||
| Method | `bool IsInvalidBlank()` | Returns `true` if `Name` is `null`, empty, or whitespace. |
|
||||
|
||||
### `CustomerDetailsDbRecord`
|
||||
- **Namespace**: `DTS.Common.Classes.CustomerDetails`
|
||||
- **Implements**: `ICustomerDetailsDbRecord`
|
||||
- **Inherits**: `Base.BasePropertyChanged`
|
||||
|
||||
| Member | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| Constructor | `CustomerDetailsDbRecord()` | Default parameterless constructor. |
|
||||
| Constructor | `CustomerDetailsDbRecord(ICustomerDetailsDbRecord)` | Copy constructor. |
|
||||
| Constructor | `CustomerDetailsDbRecord(IDataReader reader)` | Constructor from database. |
|
||||
| Property | `int CustomerId { get; set; }` | Internal database ID; defaults to `-1`; read-only in UI. |
|
||||
| Property | `string Name { get; set; }` | Internal name; defaults to `""`; read-only in UI. |
|
||||
| Property | `string CustomerName { get; set; }` | Display name; defaults to `""`; marked with `[DisplayResource("CustomerName")]`. |
|
||||
| Property | `string CustomerTestRefNumber { get; set; }` | Customer test reference number; defaults to `""`; marked with `[DisplayResource("CustomerTestRefNumber")]`. |
|
||||
| Property | `string ProjectRefNumber { get; set; }` | Project reference number; defaults to `"NOVALUE"`; marked with `[DisplayResource("ProjectRefNumber")]`. |
|
||||
| Property | `string CustomerOrderNumber { get; set; }` | Customer order number; defaults to `"NOVALUE"`; marked with `[DisplayResource("CustomerOrderNumber")]`. |
|
||||
| Property | `string CustomerCostUnit { get; set; }` | Cost center/unit; defaults to `"NOVALUE"`; marked with `[DisplayResource("CustomerCostUnit")]`. |
|
||||
| Property | `bool LocalOnly { get; set; }` | Local-only flag; defaults to `false`; read-only in UI. |
|
||||
| Property | `DateTime LastModified { get; set; }` | Modification timestamp; defaults to `DateTime.MinValue`; read-only in UI. |
|
||||
| Property | `string LastModifiedBy { get; set; }` | Modifier username; defaults to `""`; read-only in UI. |
|
||||
| Property | `int Version { get; set; }` | Version number; defaults to `-1`; read-only in UI. |
|
||||
| Method | `bool IsInvalidBlank()` | Returns `true` if `Name` is blank. |
|
||||
|
||||
### `LabratoryDetailsDbRecord`
|
||||
- **Namespace**: `DTS.Common.Classes.LabratoryDetails` *(Note: Typo in namespace and class name: "Labratory" instead of "Laboratory")*
|
||||
- **Implements**: `ILabratoryDetailsDbRecord`
|
||||
- **Inherits**: `Base.BasePropertyChanged`
|
||||
|
||||
| Member | Signature | Description |
|
||||
|--------|-----------|-------------|
|
||||
| Constructor | `LabratoryDetailsDbRecord()` | Default parameterless constructor. |
|
||||
| Constructor | `LabratoryDetailsDbRecord(ILabratoryDetailsDbRecord)` | Copy constructor. |
|
||||
| Constructor | `LabratoryDetailsDbRecord(IDataReader reader)` | Constructor from database. |
|
||||
| Property | `int LabratoryId { get; set; }` | Internal database ID; defaults to `-1`; read-only in UI. |
|
||||
| Property | `string Name { get; set; }` | Internal name; defaults to `""`; read-only in UI. |
|
||||
| Property | `string LabratoryName { get; set; }` | Display name; defaults to `string.Empty`; marked with `[DisplayResource("LabratoryName")]`. |
|
||||
| Property | `string LabratoryContactName { get; set; }` | Contact person name; defaults to `string.Empty`; marked with `[DisplayResource("LabratoryContactName")]`. |
|
||||
| Property | `string LabratoryContactPhone { get; set; }` | Contact phone; defaults to `"NOVALUE"`; marked with `[DisplayResource("LabratoryContactPhone")]`. |
|
||||
| Property | `string LabratoryContactFax { get; set; }` | Contact fax; defaults to `"NOVALUE"`; marked with `[DisplayResource("LabratoryContactFax")]`. |
|
||||
| Property | `string LabratoryContactEmail { get; set; }` | Contact email; defaults to `"NOVALUE"`; marked with `[DisplayResource("LabratoryContactEmail")]`. |
|
||||
| Property | `string LabratoryTestRefNumber { get; set; }` | Lab test reference number; defaults to `string.Empty`; marked with `[DisplayResource("LabratoryTestRefNumber")]`. |
|
||||
| Property | `string LabratoryProjectRefNumber { get; set; }` | Lab project reference number; defaults to `string.Empty`; marked with `[DisplayResource("LabratoryProjectRefNumber")]`. |
|
||||
| Property | `bool LocalOnly { get; set; }` | Local-only flag; defaults to `false`; read-only in UI. |
|
||||
| Property | `DateTime LastModified { get; set; }` | Modification timestamp; defaults to `DateTime.MinValue`; read-only in UI. |
|
||||
| Property | `string LastModifiedBy { get; set; }` | Modifier username; defaults to `""`; read-only in UI. |
|
||||
| Property | `int Version { get; set; }` | Version number; defaults to `-1`; read-only in UI. |
|
||||
| Method | `bool IsInvalidBlank()` | Returns `true` if `Name` is blank. |
|
||||
|
||||
## 3. Invariants
|
||||
- **`Name` is required**: All three classes enforce that `Name` must not be `null`, empty, or whitespace for validity. This is checked via `IsInvalidBlank()`.
|
||||
- **Default values for display fields**: Non-essential contact/reference fields default to `"NOVALUE"` (e.g., `TestEngineerPhone`, `ProjectRefNumber`) or `string.Empty` (e.g., `LabratoryName`, `CustomerName`).
|
||||
- **Metadata fields initialized to sentinel values**:
|
||||
- `LastModified` → `DateTime.MinValue`
|
||||
- `Version` → `-1`
|
||||
- `LocalOnly` → `false`
|
||||
- **UI visibility**: Properties marked `[Browsable(false)]` and `[ReadOnly(true)]` are intended for internal/backend use only (e.g., `CustomerId`, `LastModified`).
|
||||
- **`[DisplayResource]` attribute usage**: Only user-facing fields (e.g., `CustomerName`, `TestEngineerEmail`) carry `[DisplayResource]`, indicating localization support via resource keys.
|
||||
- **Immutability in practice**: Though setters exist, the `[ReadOnly(true)]` attribute and internal naming (`_name`, `_version`) suggest these are *mostly* immutable after construction—especially when populated from a database.
|
||||
|
||||
## 4. Dependencies
|
||||
- **Core dependencies (all three classes)**:
|
||||
- `DTS.Common.Base.Classes.BasePropertyChanged` (base class for `INotifyPropertyChanged` implementation)
|
||||
- `DTS.Common.Interface.TestMetaData` (interfaces: `ITestEngineerDetailsDbRecord`, `ICustomerDetailsDbRecord`, `ILabratoryDetailsDbRecord`)
|
||||
- `DTS.Common.Utilities.Logging` (imported but *not used* in the provided code—likely legacy or for future use)
|
||||
- `System.Data` (`IDataReader` for database population)
|
||||
- `System.ComponentModel` (`[Browsable]`, `[ReadOnly]`, `[DisplayResource]` attributes)
|
||||
- **Internal utilities**:
|
||||
- `Utility.GetString`, `Utility.GetDateTime`, `Utility.GetInt`, `Utility.GetBool` (static methods for safe `IDataReader` access)
|
||||
- **Inferred consumers**:
|
||||
- Data access layers (DALs) that populate records from SQL queries.
|
||||
- UI components (e.g., WPF/WinForms) relying on `INotifyPropertyChanged` and `[DisplayResource]` for binding and localization.
|
||||
- Synchronization or caching services that use `LocalOnly`, `LastModified`, and `Version` for conflict resolution.
|
||||
|
||||
## 5. Gotchas
|
||||
- **Typo in namespace/class name**: The `LabratoryDetailsDbRecord` class and its namespace use "Labratory" (misspelled) instead of "Laboratory". This is likely historical and should be preserved for compatibility.
|
||||
- **`[DisplayResource]` attribute behavior is undefined**: The source does not show how `[DisplayResource]` is processed. Its runtime behavior (e.g., resource lookup mechanism) is not documented here.
|
||||
- **No validation on non-blank fields**: While `IsInvalidBlank()` checks `Name`, there is no validation for required contact fields (e.g., `TestEngineerEmail`). An instance may be "valid" yet missing critical data.
|
||||
- **`LocalOnly` semantics unclear**: The purpose of `LocalOnly` is not explained—e.g., whether it affects persistence, synchronization, or visibility.
|
||||
- **Default `"NOVALUE"` string**: This sentinel value is used inconsistently:
|
||||
- `TestEngineerDetailsDbRecord`: `"NOVALUE"` for phone/fax/email
|
||||
- `CustomerDetailsDbRecord`: `"NOVALUE"` for project/order/cost-unit
|
||||
- `LabratoryDetailsDbRecord`: `"NOVALUE"` for contact phone/fax/email
|
||||
Consumers must be aware of this convention to avoid misinterpreting `"NOVALUE"` as a literal value.
|
||||
- **No null-safety guarantees**: `Utility.GetString` and similar methods are used, but their behavior on `DBNull` or missing columns is not specified in the source.
|
||||
- **Copy constructor does not validate**: The copy constructor accepts `ITestEngineerDetailsDbRecord` (etc.) without checking for null or invalid state. A copy of an invalid record remains invalid.
|
||||
- **No explicit immutability enforcement**: Despite `[ReadOnly(true)]`, the properties remain settable programmatically—e.g., after construction from a database, callers can still mutate fields.
|
||||
@@ -0,0 +1,123 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/TestSetups/SimpleHardware.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/TestSetupHelper.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/ExtraProperties.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/ROIPeriodChannelRecord.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/TestSetupHardwareRecord.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/TestSetupROIsRecord.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/CalculatedChannelRecord.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/ISFFile.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/GraphRecord.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/RegionOfInterest.cs
|
||||
- Common/DTS.Common/Classes/TestSetups/ISFSensorRecord.cs
|
||||
generated_at: "2026-04-16T03:18:08.842826+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "9bc5c021742b55c0"
|
||||
---
|
||||
|
||||
# TestSetups Module Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides core data structures and helper utilities for representing and managing test setup configurations within the DTS system. It defines immutable and mutable record types that model database entities (e.g., hardware assignments, ROIs, calculated channels, graphs), along with supporting infrastructure for ISF file I/O and test setup naming. The module serves as the data layer abstraction for test setup management—enabling serialization/deserialization from database queries, file formats (ISF), and interoperation with UI and business logic layers through interfaces and property change notifications.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Classes
|
||||
|
||||
#### `SimpleHardware`
|
||||
- **Signature**: `public class SimpleHardware : Tuple<string, string, int, int>`
|
||||
- **Behavior**: A lightweight, immutable tuple-based representation of hardware configuration. Exposes `SerialNumber`, `ParentDAS`, `DASId`, and `DASType` via named properties derived from tuple items. Used for passing hardware metadata without database persistence.
|
||||
|
||||
#### `TestSetupHelper`
|
||||
- **Signature**: `public abstract class TestSetupHelper`
|
||||
- **Behavior**: A static helper class for managing test setup names by ID. Provides `SetTestSetupName`, `GetTestSetupName`, and `ClearTestSetupNames` methods. Maintains an internal dictionary mapping integer IDs to string names.
|
||||
|
||||
#### `ExtraProperty`
|
||||
- **Signature**: `[Serializable] public class ExtraProperty : IExtraProperty`
|
||||
- **Behavior**: A mutable, INotifyPropertyChanged-enabled class representing a key-value pair for extra properties. Supports two constructors: parameterized (`key`, `value`) and copy constructor from `IExtraProperty`. Includes `PasteCommand` and `ItemStatus` properties (ignored during JSON serialization via `[ScriptIgnore]`).
|
||||
|
||||
#### `ROIPeriodChannelRecord`
|
||||
- **Signature**: `public class ROIPeriodChannelRecord : BasePropertyChanged, IROIPeriodChannelRecord`
|
||||
- **Behavior**: Represents a record from the `ROIPeriodChannels` database table. Properties: `TestSetupROIId`, `ChannelName`, `ChannelId`. Constructor accepts `IDataReader` and `storedProcedureVersionToUse`; `ChannelId` is set to `-1` if the DB version predates its introduction (`Constants.ROIPERIODCHANNELS_CHANNELID_DB_VERSION`).
|
||||
|
||||
#### `TestSetupHardwareRecord`
|
||||
- **Signature**: `public class TestSetupHardwareRecord : Base.BasePropertyChanged, ITestSetupHardwareRecord`
|
||||
- **Behavior**: Represents a record from the `TestSetupHardware` table. Properties: `DASId`, `TestSetupId`, `AddDAS`, `SamplesPerSecond`, `IsClockMaster`, `PTPDomainId`, `AntiAliasFilterRate`. Supports three constructors: default, `IDataReader` (with version-aware `PTPDomainId` parsing), and copy constructor from `ITestSetupHardwareRecord`.
|
||||
|
||||
#### `TestSetupROIsRecord`
|
||||
- **Signature**: `public class TestSetupROIsRecord : BasePropertyChanged, ITestSetupROIRecord`
|
||||
- **Behavior**: Represents a record from the `TestSetupROIs` table. Properties: `TestSetupROIId`, `TestSetupId`, `Suffix`, `ROIStart`, `ROIEnd`, `IsEnabled`, `IsDefault`. Constructor accepts `IDataReader`; note: `TestSetupId` is incorrectly assigned from `"TestSetupROIId"` column in constructor (see *Gotchas*).
|
||||
|
||||
#### `CalculatedChannelRecord`
|
||||
- **Signature**: `public class CalculatedChannelRecord : BasePropertyChanged, ICalculatedChannelRecord`
|
||||
- **Behavior**: Represents a calculated channel record. Properties include `Name`, `TestSetupName`, `Id`, `Operation`, `CalculatedValueCode`, `InputChannelIds` (string array), `CFCForInputChannels`, `ChannelFilterClassForOutput`, `TestSetupId`, `ViewInRealtime`, `ClipLength`. Supports default, copy (`ICalculatedChannelRecord`), and `IDataReader` constructors. Input channel IDs are parsed from CSV using `CultureInfo.InvariantCulture.TextInfo.ListSeparator`.
|
||||
|
||||
#### `ISFFile`
|
||||
- **Signature**: `public class ISFFile`
|
||||
- **Behavior**: Handles reading/writing ISF (Instrumentation Sensor Format) files. Contains fixed-length header fields (`TestSetupName`, `NumberOfRecords`, `TestType`, `TestDivision`, `TCFile`) and a list of `IISFSensorRecord` objects. Methods: `AddRecord`, `WriteToFile`, `AddSensors`. Header line parsing uses fixed offsets and padding with spaces.
|
||||
|
||||
#### `GraphRecord`
|
||||
- **Signature**: `public class GraphRecord : BasePropertyChanged, IGraphRecord`
|
||||
- **Behavior**: Represents a graph configuration record. Properties: `GraphId`, `TestSetupId`, `GraphName`, `GraphDescription`, `ChannelsString`, axis range flags (`UseDomainMin`, `UseDomainMax`, `UseRangeMin`, `UseRangeMax`) and their corresponding min/max values, `ThresholdsString`, `LocalOnly` (deprecated). Supports default, copy, and `IDataReader` constructors.
|
||||
|
||||
#### `RegionOfInterest`
|
||||
- **Signature**: `[Serializable] public class RegionOfInterest : IRegionOfInterest`
|
||||
- **Behavior**: A mutable, INotifyPropertyChanged-enabled class modeling a time-based ROI. Properties: `Suffix`, `Start`, `End`, `IsEnabled`, `IsDefault`, `ChannelNames`, `ChannelIds`. Includes validation to ensure `Start < End`. Notifies via `RegionOfInterestChangedEvent` (via Prism EventAggregator) on value changes, unless `Deserializing` is true. Provides utility methods for channel name formatting (`GetAnalogChanName`, `GetChanName`, `RemoveParentDASName`, `RemoveAssignedByIDFromHardwareString`) and silent assignment (`SetChannelNamesNoNotify`, `SetChannelIdsNoNotify`).
|
||||
|
||||
#### `ISFSensorRecord`
|
||||
- **Signature**: `public class ISFSensorRecord : IISFSensorRecord`
|
||||
- **Behavior**: Represents a single sensor record in an ISF file (comprising 4 fixed-length records of `RECORD_LENGTH` chars each). Exposes structured properties for sensor metadata (e.g., `DataChannelNumber`, `Tag`, `SerialNumber`, `Sensitivity`, `Capacity`, `EngineeringUnits`, `C1`, `C2`, `C3`, `EID`, `CommentPart1/2/3`, `SensorType`, `TOMConfigurationName`). Includes methods to set/get values and `Write` to `BinaryWriter`. Default constructor initializes `TOMConfigurationName` to `"STANDARD"`.
|
||||
|
||||
### Extension Methods (in `ISFFile`)
|
||||
- `Fill<T>(this T[] sourceArray, T with)`: Fills entire array with value.
|
||||
- `SubFill<T>(this T[] source, T with, int startIndex, int finalIndex)`: Fills from `startIndex` to `finalIndex` (exclusive), respecting array bounds.
|
||||
- `SetValues<T>(this T[] source, T[] with, int startIndex, int length, T pad)`: Copies `with` array into `source` starting at `startIndex`, padding remaining space with `pad`.
|
||||
- `GetValues<T>(this T[] source, int startIndex, int length)`: Returns a new array of `length` elements starting at `startIndex`.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`SimpleHardware`**: Immutable after construction; tuple item mapping is fixed (`Item1→SerialNumber`, `Item2→ParentDAS`, `Item3→DASId`, `Item4→DASType`).
|
||||
- **`TestSetupROIsRecord` constructor**: `TestSetupId` is incorrectly assigned from `"TestSetupROIId"` column (see *Gotchas*); no invariant violation is enforced by code.
|
||||
- **`RegionOfInterest.Start` and `End`**: `Start < End` is enforced via setter logic (`Start` capped at `End - 0.01`, `End` capped at `Start + 0.01`). Infinity values are explicitly excluded from notifications (per comment referencing "FB 43462").
|
||||
- **`ISFFile` header fields**: All fields are fixed-width and space-padded. `NumberOfRecords` is derived as `4 * number of sensor records`.
|
||||
- **`ISFSensorRecord`**: Each record consists of exactly 4 fixed-length `char[]` arrays (`Record1`–`Record4`), each of length `ConstantsAndEnums.RECORD_LENGTH`.
|
||||
- **`CalculatedChannelRecord.InputChannelIds`**: Stored as a string array; parsed from CSV using `ListSeparator` (e.g., comma in invariant culture).
|
||||
- **`GraphRecord` axis flags**: `UseDomainMin/Max` and `UseRangeMin/Max` flags control whether corresponding min/max values are applied.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Internal Dependencies
|
||||
- **`DTS.Common.Base`**: Base classes (`BasePropertyChanged`) used by `ROIPeriodChannelRecord`, `TestSetupROIsRecord`, `CalculatedChannelRecord`, `GraphRecord`.
|
||||
- **`DTS.Common.Interface.*`**: Interfaces implemented by record classes:
|
||||
- `IROIPeriodChannelRecord`, `ITestSetupHardwareRecord`, `ITestSetupROIRecord`, `ICalculatedChannelRecord`, `IGraphRecord`, `IISFSensorRecord`, `IExtraProperty`, `IRegionOfInterest`.
|
||||
- **`DTS.Common.Enums`**: `Operations` enum used by `CalculatedChannelRecord`.
|
||||
- **`DTS.Common.Interface.Sensors`**: `ISensorData` used by `ISFSensorRecord.SetSensor`.
|
||||
- **`DTS.Common.Events.RegionOfInterest`**: `RegionOfInterestChangedEvent` used by `RegionOfInterest`.
|
||||
- **`Prism.*`**: `IEventAggregator`, `IContainerProvider`, `ContainerLocator` used by `RegionOfInterest.NotifyChanged`.
|
||||
|
||||
### External Dependencies
|
||||
- **System.Data**: `IDataReader` for database record construction.
|
||||
- **System.ComponentModel**: `INotifyPropertyChanged` via `PropertyChangedEventHandler`.
|
||||
- **System.Web.Script.Serialization**: `[ScriptIgnore]` attribute.
|
||||
- **System.Linq**: Used for array equality checks (`SequenceEqual`) and LINQ queries.
|
||||
- **System**: Core types (`string`, `char[]`, `double`, `int`, `long`, `short`, `byte`, `bool`, `ICommand`).
|
||||
|
||||
### Inferred Usage
|
||||
- **Database**: All record classes with `IDataReader` constructors imply usage with stored procedures (e.g., `sp_ROIPeriodChannelsGet`, `sp_TestSetupROIsGet`).
|
||||
- **ISF I/O**: `ISFFile` and `ISFSensorRecord` are used for writing sensor data to ISF files.
|
||||
- **UI**: `ExtraProperty`, `RegionOfInterest`, and record classes implement `INotifyPropertyChanged`, indicating use in data-bound UI layers (e.g., WPF).
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`TestSetupROIsRecord` constructor bug**: `TestSetupId = Utility.GetInt(reader, "TestSetupROIId");` incorrectly reads from `"TestSetupROIId"` instead of `"TestSetupId"`. This will cause incorrect `TestSetupId` values when constructing from database reader.
|
||||
- **`ISFSensorRecord.GetCapacity()`, `GetSensitivity()`, etc.**: Methods like `CapacityCharacters.ToString()` return the underlying `char[]`'s `ToString()` (i.e., type name), not the string content. Correct usage requires `new string(char[])` or `string.Concat(char[])`. This is likely a bug.
|
||||
- **`RegionOfInterest.Suffix` validation**: Enforces that non-empty suffixes must start with `"_"` and be otherwise whitespace-free. If input violates this, it is auto-corrected (e.g., `"ROI1"` → `"_ROI1"`).
|
||||
- **`RegionOfInterest.Deserializing` flag**: A static flag used to suppress change notifications during deserialization (e.g., to avoid triggering UI updates or event publishing during object construction). Requires careful coordination to avoid missed updates.
|
||||
- **`ISFFile.NumberOfRecords` semantics**: `SetNumberOfRecords` sets `NumberOfRecords` to `4 * Records.Length`, implying each sensor record occupies 4 "records" in the ISF file (consistent with `ISFSensorRecord` having 4 `char[]` fields).
|
||||
- **`CalculatedChannelRecord.InputChannelIds` copy constructor**: Uses `CopyTo` on `record.InputChannelIds` into `_inputChannelIds`, but `_inputChannelIds` is initialized to `new string[0]` *before* the copy, causing `ArgumentException` if `record.InputChannelIds.Length > 0`. Should initialize `_inputChannelIds` to `new string[record.InputChannelIds.Length]` first.
|
||||
- **`ISFSensorRecord.TOMConfigurationName`**: Default value `"STANDARD"` is hardcoded; other values are not supported per comments.
|
||||
- **`RegionOfInterest.GetAnalogChanName` logic**: Distinguishes `"TEST_SPECIFIC_ANALOG_SERIAL"` and `"VOLTAGE_INPUT"` DAS types for special channel name parsing. Relies on `SensorConstants` values (not shown in source).
|
||||
- **`TestSetupHelper.TestSetupNames`**: Static dictionary is shared across all usages; `ClearTestSetupNames()` affects all callers. No thread-safety is evident.
|
||||
169
enriched-qwen3-coder-next/Common/DTS.Common/Classes/WinApi.md
Normal file
169
enriched-qwen3-coder-next/Common/DTS.Common/Classes/WinApi.md
Normal file
@@ -0,0 +1,169 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/WinApi/WindowsAPIHelpers.cs
|
||||
generated_at: "2026-04-16T03:16:58.945801+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "32ac28362ec2b57c"
|
||||
---
|
||||
|
||||
# WinApi
|
||||
|
||||
## Documentation: `WindowsAPIHelpers.cs`
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
This module provides interoperability helpers for Windows API integration, specifically to support custom window sizing and positioning behavior in WPF applications. It defines P/Invoke-compatible structures (`POINT`, `RECT`, `MINMAXINFO`, `MONITORINFO`, `WINDOWPOS`, `WM`, `SWP`) and exposes two Win32 functions (`GetMonitorInfo`, `MonitorFromWindow`) to enable accurate adjustment of a window’s maximized size and position to match the *work area* of the monitor on which the window resides—rather than the full screen (which may include taskbars or other non-client areas). This is typically used in response to the `WM_GETMINMAXINFO` message to prevent maximized windows from overlapping system UI elements.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### Structs
|
||||
|
||||
- **`POINT`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINT { public int x; public int y; public POINT(int x, int y); }
|
||||
```
|
||||
Represents a point in 2D space with integer coordinates. Used as a field in other structures.
|
||||
|
||||
- **`RECT`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 0)]
|
||||
public struct RECT
|
||||
{
|
||||
public int left, top, right, bottom;
|
||||
public static readonly RECT Empty;
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
public RECT(int left, int top, int right, int bottom);
|
||||
public bool IsEmpty { get; }
|
||||
public override string ToString();
|
||||
public override bool Equals(object obj);
|
||||
public override int GetHashCode();
|
||||
public static bool operator ==(RECT, RECT);
|
||||
public static bool operator !=(RECT, RECT);
|
||||
}
|
||||
```
|
||||
Represents a rectangle with integer coordinates. Includes computed `Width` and `Height` properties, equality operators, and an `IsEmpty` check (true if `left >= right` or `top >= bottom`). Note: `Height` is computed as `bottom - top` (not `Math.Abs`), so negative heights are possible if `bottom < top`.
|
||||
|
||||
- **`MINMAXINFO`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MINMAXINFO
|
||||
{
|
||||
public POINT ptReserved;
|
||||
public POINT ptMaxSize;
|
||||
public POINT ptMaxPosition;
|
||||
public POINT ptMinTrackSize;
|
||||
public POINT ptMaxTrackSize;
|
||||
}
|
||||
```
|
||||
Used to convey minimum/maximum tracking and maximized window geometry. Populated by `GetMinMaxInfo`.
|
||||
|
||||
- **`MONITORINFO`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
|
||||
public class MONITORINFO
|
||||
{
|
||||
public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
|
||||
public RECT rcMonitor = new RECT();
|
||||
public RECT rcWork = new RECT();
|
||||
public int dwFlags = 0;
|
||||
}
|
||||
```
|
||||
Contains monitor-specific information. `cbSize` is auto-initialized to the unmanaged size of the struct. `rcMonitor` is the full monitor rectangle; `rcWork` is the work area (excluding taskbars, etc.).
|
||||
|
||||
- **`WINDOWPOS`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WINDOWPOS
|
||||
{
|
||||
public IntPtr hwnd;
|
||||
public IntPtr hwndInsertAfter;
|
||||
public int x, y, cx, cy;
|
||||
public int flags;
|
||||
}
|
||||
```
|
||||
Used in `WM_WINDOWPOSCHANGING`/`WM_WINDOWPOSCHANGED` messages. Not used directly in this file but defined for completeness.
|
||||
|
||||
#### Enums
|
||||
|
||||
- **`WM`**
|
||||
```csharp
|
||||
public enum WM { WINDOWMAX = 0x0024, WINDOWPOSCHANGING = 0x0046; }
|
||||
```
|
||||
Windows message constants. `WINDOWMAX` is likely a typo or nonstandard alias (standard is `WM_SYSCOMMAND` with `SC_MAXIMIZE`, or `WM_SIZE` with `SIZE_MAXIMIZED`). `WINDOWPOSCHANGING` is `WM_WINDOWPOSCHANGING`.
|
||||
|
||||
- **`SWP`**
|
||||
```csharp
|
||||
public enum SWP { NOMOVE = 0x0002; }
|
||||
```
|
||||
Flags for `SetWindowPos`. `NOMOVE` preserves current position.
|
||||
|
||||
#### Methods
|
||||
|
||||
- **`GetMinMaxInfo(IntPtr hwnd, IntPtr lParam)`**
|
||||
```csharp
|
||||
public static void GetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
|
||||
```
|
||||
Handles the `WM_GETMINMAXINFO` message by adjusting `ptMaxSize` and `ptMaxPosition` in the `MINMAXINFO` structure to fit the *work area* of the monitor containing `hwnd`. Uses `MonitorFromWindow` with `MONITOR_DEFAULTTONEAREST` (`0x00000002`) to locate the monitor, then calls `GetMonitorInfo` to retrieve monitor geometry. Writes the modified `MINMAXINFO` back to `lParam`.
|
||||
|
||||
#### P/Invoke Exports
|
||||
|
||||
- **`GetMonitorInfo`**
|
||||
```csharp
|
||||
[DllImport("user32")]
|
||||
public static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
|
||||
```
|
||||
Retrieves monitor information. Caller must initialize `MONITORINFO.cbSize` before calling.
|
||||
|
||||
- **`MonitorFromWindow`**
|
||||
```csharp
|
||||
[DllImport("User32")]
|
||||
public static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
|
||||
```
|
||||
Returns a handle to the monitor that contains the window. `flags` is typically `MONITOR_DEFAULTTONEAREST` (`0x00000002`).
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- `MONITORINFO.cbSize` **must** be set to `Marshal.SizeOf(typeof(MONITORINFO))` before calling `GetMonitorInfo`; otherwise, the call will fail (returns `false`).
|
||||
- `RECT.IsEmpty` is defined as `left >= right || top >= bottom`. This implies a rectangle with `left == right` or `top == bottom` is considered empty.
|
||||
- `RECT.Height` is computed as `bottom - top` (not `Math.Abs(bottom - top)`), so if `bottom < top`, `Height` is negative. This may indicate an inverted rectangle (e.g., from drag-select), but the code does not enforce non-negative height.
|
||||
- `GetMinMaxInfo` assumes the window is on a valid monitor. If `MonitorFromWindow` returns `IntPtr.Zero`, no adjustment is made, and the original `MINMAXINFO` values are preserved.
|
||||
- The `ptMaxPosition` values are computed as absolute offsets from the monitor’s left/top edge (`Math.Abs(rcWorkArea.left - rcMonitorArea.left)`), which correctly yields the top-left corner of the work area relative to the monitor.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
#### Dependencies *on* this module:
|
||||
- **WPF/Win32 interop layer**: This module is intended for use in WPF applications (evidenced by `System.Windows` namespace usage, though not directly referenced in this file). Likely consumed by window message handlers (e.g., `Window.SourceInitialized` or `OnSourceInitialized` overrides) to subclass window procedures and handle `WM_GETMINMAXINFO`.
|
||||
- **`System.Runtime.InteropServices`**: Required for `StructLayout`, `DllImport`, `Marshal.PtrToStructure`, and `Marshal.StructureToPtr`.
|
||||
|
||||
#### Dependencies *of* this module:
|
||||
- **`user32.dll`**: For `GetMonitorInfo` and `MonitorFromWindow`.
|
||||
- **No external libraries beyond .NET Framework core types** (no NuGet dependencies implied).
|
||||
|
||||
#### Known consumers (inferred):
|
||||
- Any class handling `WM_GETMINMAXINFO` (e.g., via `HwndSource.AddHook`) will call `WindowsAPIHelpers.GetMinMaxInfo`.
|
||||
- Likely used in custom window management logic (e.g., `MainWindow.xaml.cs` or a base window class).
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **`RECT.Height` is *not* absolute**: `Height => bottom - top` (not `Math.Abs`). This may cause unexpected negative heights if rectangles are inverted. Use `Math.Abs` externally if needed.
|
||||
- **`MONITORINFO` is a `class`, not a `struct`**: This is unusual for P/Invoke marshaling (typically `struct` is preferred). While it works due to `StructLayout`, it introduces heap allocation and reference semantics. Ensure the instance is not reused across threads without synchronization.
|
||||
- **`WINDOWMAX` enum value is nonstandard**: The Win32 constant for maximization is `WM_SYSCOMMAND` with `SC_MAXIMIZE` (0xF030), not `0x0024`. `0x0024` is `WM_USER + 36` in some contexts but not a standard system message. This may be a typo or internal alias.
|
||||
- **`rcMonitor` vs `rcWork` semantics**: `rcMonitor` is the full monitor bounds; `rcWork` excludes taskbars, etc. The code correctly uses `rcWork` for `ptMaxSize`/`ptMaxPosition`, but callers must understand this distinction.
|
||||
- **No validation of `lParam` in `GetMinMaxInfo`**: Assumes `lParam` points to a valid `MINMAXINFO` structure. Passing `IntPtr.Zero` or invalid memory will cause a crash.
|
||||
- **Missing `WM` constants**: Only two `WM` values are defined (`WINDOWMAX`, `WINDOWPOSCHANGING`). Other common messages (e.g., `WM_SIZE`, `WM_GETMINMAXINFO`) are not included, suggesting this is a partial set.
|
||||
- **`MONITOR_DEFAULTTONEAREST` flag is hardcoded**: The `MonitorFromWindow` call uses `0x00000002` directly instead of a named constant (e.g., `MONITOR_DEFAULTTONEAREST = 2`). While correct, it reduces readability.
|
||||
|
||||
None identified beyond these.
|
||||
@@ -0,0 +1,54 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common/Classes/WindowsFolder/WindowsFolder.cs
|
||||
generated_at: "2026-04-16T03:17:08.376962+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "f16db9efe9d28ad5"
|
||||
---
|
||||
|
||||
# WindowsFolder
|
||||
|
||||
### 1. **Purpose**
|
||||
The `WindowsFolder` class provides a utility method to open the *Manuals* folder in Windows Explorer. It is designed to support user-facing documentation access by launching the folder containing application manuals. The class assumes the *Manuals* folder resides in a subdirectory of the provided `path` argument, and relies on the runtime `CurrentDirectory` being correctly set (per comments, this is always true in the deployed environment, even for non-default installations).
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### `public static void OpenManualsFolder(string path)`
|
||||
- **Signature**: `void OpenManualsFolder(string path)`
|
||||
- **Behavior**: Constructs the full path to the *Manuals* folder by appending `Constants.ManualsFolder` to the input `path`, then launches Windows Explorer (`Constants.WindowsExplorer`) with that path as an argument.
|
||||
- **Throws**: May throw `Win32Exception` (e.g., if `explorer.exe` fails to start), `InvalidOperationException` (e.g., if `Process.Start` is unsupported), or `ArgumentNullException`/`ArgumentException` if `path` is null/invalid. *(Note: Exception behavior is inferred from `Process.Start` semantics; not explicitly documented in source.)*
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
- The `path` argument must represent a valid directory path (though validation is not performed in this method).
|
||||
- The *Manuals* folder must exist at `Path.Combine(path, Constants.ManualsFolder)` for the operation to succeed meaningfully.
|
||||
- `Constants.ManualsFolder` and `Constants.WindowsExplorer` must be non-null, non-empty strings at runtime (assumed from usage).
|
||||
- The application’s `Environment.CurrentDirectory` is expected to be consistent with the caller’s intent (per comments), though this is not enforced here.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
- **Internal**:
|
||||
- `Constants.ManualsFolder` (string constant)
|
||||
- `Constants.WindowsExplorer` (string constant)
|
||||
*(These are referenced but not defined in the provided source; must be defined in `DTS.Common.Classes.WindowsFolders` or a referenced `Constants` type.)*
|
||||
- **External**:
|
||||
- `System.Diagnostics.Process` (for launching Explorer)
|
||||
- `System.IO.Path` (for path concatenation)
|
||||
- **Depended on by**: Unknown from this file alone (no usage references provided). Likely called from UI layers (e.g., help menu handlers).
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
- **Path assumption**: The method *does not* use `CurrentDirectory` directly despite the comment implying reliance on it; it uses the passed `path` argument. If `path` is incorrect or outdated, the folder may not open.
|
||||
- **No existence check**: The method does not verify that `manualsPath` exists before launching Explorer, which may result in Explorer opening an empty or non-existent folder without error feedback.
|
||||
- **Platform dependency**: Uses Windows-specific `explorer.exe`; will fail on non-Windows platforms (no fallback or guard is present).
|
||||
- **No async handling**: Blocking call to `Process.Start` may cause UI thread hangs if invoked synchronously on a UI thread (though `Process.Start` is typically non-blocking for Explorer).
|
||||
- **Missing constants**: `Constants.ManualsFolder` and `Constants.WindowsExplorer` are referenced but not defined here—critical for correctness. Their values must be verified externally.
|
||||
- **No error handling**: No try/catch around `Process.Start`; exceptions propagate directly.
|
||||
|
||||
*None identified beyond the above.*
|
||||
Reference in New Issue
Block a user