init
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/ChannelCodes/TextPastedArgs.cs
|
||||
- Common/DTS.CommonCore/Classes/ChannelCodes/ChannelCode.cs
|
||||
generated_at: "2026-04-16T02:39:51.595748+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "9a72b7f2cc9cf8aa"
|
||||
---
|
||||
|
||||
# ChannelCodes
|
||||
|
||||
## Documentation: ChannelCode Module
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module provides core data and command infrastructure for handling *channel codes*—named identifiers (e.g., ISO or user-defined codes) used to categorize or label channels in the system. It defines the `ChannelCode` class as the canonical implementation of `IChannelCode`, including persistence support via `IDataReader`, equality semantics, and property change notification. It also defines `PasteCommandClass`, a `ICommand` implementation that intercepts text paste operations in UI text boxes, processes clipboard content (including multi-line or delimited data), and publishes structured `TextPastedArgs` events for downstream handling—while suppressing default paste behavior to enable custom logic.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `class ChannelCode : BasePropertyChanged, IChannelCode`
|
||||
|
||||
- **`int Id { get; set; }`**
|
||||
Unique numeric identifier for the channel code. Initialized to `-1` by default.
|
||||
|
||||
- **`UIItemStatus ItemStatus { get; set; }`**
|
||||
Status of the item (e.g., `None`, `New`, `Modified`, `Deleted`). Uses `SetProperty` for change notification.
|
||||
|
||||
- **`string Code { get; protected set; }`**
|
||||
The code string (e.g., `"A1"`, `"ISO-8601"`). Protected setter allows subclassing.
|
||||
|
||||
- **`string Name { get; protected set; }`**
|
||||
Human-readable name for the channel code (e.g., `"Temperature Sensor"`).
|
||||
|
||||
- **`ChannelEnumsAndConstants.ChannelCodeType CodeType { get; set; }`**
|
||||
Enumerated type of the code: `User` or `ISO`. Default is `ISO` in parameterless constructor.
|
||||
|
||||
- **`const string PASTE_ID = "ChannelCode"`**
|
||||
Static identifier used to correlate paste operations with this channel code type.
|
||||
|
||||
- **`ICommand PasteCommand { get; set; } = null`**
|
||||
Command bound to text boxes to handle paste operations. Defaults to `null` to avoid exceptions during UI construction.
|
||||
|
||||
- **`ChannelCode(IDataReader reader, IReadOnlyDictionary<short, string> channelTypeLookup)`**
|
||||
Constructor that initializes the instance from a database record. Reads `Id`, `Code`, `Name`, and `CodeTypeInt` columns. Uses `channelTypeLookup` to map `CodeTypeInt` to `ChannelCodeType` (`User` or `ISO`) via string keys (`"User"` / `"ISO"`).
|
||||
|
||||
- **`ChannelCode()`**
|
||||
Parameterless constructor. Sets `CodeType` to `ISO`.
|
||||
|
||||
- **`ChannelCode(IChannelCode channelCode)`**
|
||||
Copy constructor. Copies `Id`, `Code`, `Name`, and `CodeType` from another `IChannelCode`.
|
||||
|
||||
- **`override bool Equals(object obj)`**
|
||||
Equality comparison based on `Code`, `Name`, and `CodeType`. Returns `false` if `obj` is not a `ChannelCode`.
|
||||
|
||||
- **`~ChannelCode()`**
|
||||
Finalizer that nulls `_code` and `_name` to reduce memory footprint if the object is held longer than expected.
|
||||
|
||||
#### `class PasteCommandClass : ICommand`
|
||||
|
||||
- **`string Id { get; }`**
|
||||
Identifier passed at construction; used to tag paste events.
|
||||
|
||||
- **`bool CanExecute(object parameter)`**
|
||||
Always returns `true`.
|
||||
|
||||
- **`void Execute(object parameter)`**
|
||||
Handles paste logic:
|
||||
- Requires `parameter` to be a `TextBox`.
|
||||
- Attempts to resolve `IChannelCode` from `TextBox.DataContext`, with fallbacks to `ChannelCodeBuilder` or `ChannelNameBuilder` view models.
|
||||
- Reads clipboard text.
|
||||
- If clipboard contains **exactly one line** and **no delimiters** (`,`, `;`, `\t`), publishes a `PageModifiedEvent` and exits early (single-field paste is handled by `TextChanged`).
|
||||
- Otherwise:
|
||||
- Resets `Code` and `Name` properties (no-op assignment to trigger change notifications).
|
||||
- Publishes a `TextPastedEvent` with a `TextPastedArgs` instance containing:
|
||||
- `Text`: full clipboard content
|
||||
- `Sender`: resolved `IChannelCode`
|
||||
- `Id`: `PasteCommandClass.Id`
|
||||
- `Tag`: `TextBox.Tag`
|
||||
- Catches and reports exceptions via `PageErrorEvent`.
|
||||
|
||||
- **`PasteCommandClass(string id)`**
|
||||
Constructor storing `id` in `Id` property.
|
||||
|
||||
#### `delegate string CoerceISOCodeDelegate(...)`
|
||||
|
||||
- **`string CoerceISOCodeDelegate(string val, bool uniqueISOCodesRequired, bool useISOCodeFilterMapping)`**
|
||||
Signature for a delegate used to transform or validate incoming ISO codes. Not implemented in this file—only declared.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **`ChannelCode.Code` and `ChannelCode.Name` must be non-null**
|
||||
Initialized to `string.Empty` and never set to `null` (via `SetProperty` and constructor defaults).
|
||||
|
||||
- **`ChannelCode.Id` defaults to `-1`**
|
||||
A value of `-1` indicates the code has not been persisted or assigned.
|
||||
|
||||
- **`ChannelCode.CodeType` defaults to `ISO`**
|
||||
Unless explicitly set otherwise (e.g., via constructor with `IDataReader` or copy constructor).
|
||||
|
||||
- **Equality is based on `Code`, `Name`, and `CodeType`**
|
||||
`Id` is *not* part of equality semantics.
|
||||
|
||||
- **Paste command only processes `TextBox` parameters**
|
||||
Non-`TextBox` inputs are silently ignored.
|
||||
|
||||
- **Clipboard text is split by `Environment.NewLine`**
|
||||
Only single-line, non-delimited text bypasses `TextPastedEvent`; all other cases trigger it.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### *This module depends on:*
|
||||
- **`DTS.Common.Base`**
|
||||
Provides `BasePropertyChanged` (base class for `ChannelCode`).
|
||||
- **`DTS.Common.Interface.Channels.ChannelCodes`**
|
||||
Defines `IChannelCode` interface.
|
||||
- **`DTS.Common.Enums`**
|
||||
Provides `UIItemStatus`, `ChannelEnumsAndConstants` (enum `ChannelCodeType`, string constants `"User"`, `"ISO"`).
|
||||
- **`DTS.Common.Events`**
|
||||
Defines `PageModifiedEvent`, `TextPastedEvent`, `PageErrorEvent`, and argument types (`PageModifiedArg`, `TextPastedArgs`, `PageErrorArg`).
|
||||
- **`System.Data`**
|
||||
For `IDataReader`.
|
||||
- **`System.Windows` / `System.Windows.Controls` / `System.Windows.Input`**
|
||||
For `UIElement`, `TextBox`, `ICommand`.
|
||||
- **`Microsoft.Practices.Prism.Events`**
|
||||
For `IEventAggregator`.
|
||||
- **`Microsoft.Practices.ServiceLocation`**
|
||||
For `ServiceLocator`.
|
||||
|
||||
#### *This module is depended on by:*
|
||||
- Any UI layer components that bind `ChannelCode` instances to views (e.g., `ChannelCodeBuilder`, `ChannelNameBuilder`).
|
||||
- Event handlers subscribed to `TextPastedEvent`.
|
||||
- Code that constructs `ChannelCode` instances from database readers or clones them.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`PasteCommand` defaults to `null`**
|
||||
To avoid exceptions during UI construction (per inline comment: *"putting a null here avoids wasteful exception"*). Consumers must explicitly assign a `PasteCommandClass` instance.
|
||||
|
||||
- **`ChannelCode.Equals` ignores `Id`**
|
||||
Two codes with different IDs but identical `Code`, `Name`, and `CodeType` are considered equal. This may cause issues if IDs are expected to be unique in comparisons.
|
||||
|
||||
- **`~ChannelCode()` finalizer nulls fields but does not prevent GC of the object**
|
||||
This is a cleanup heuristic, not a disposal pattern. No `IDisposable` implementation is present.
|
||||
|
||||
- **Single-line paste with delimiters still triggers `TextPastedEvent`**
|
||||
Only *single-line, no-delimiter* text skips the event; multi-line or single-line with `,`, `;`, or `\t` always publish `TextPastedArgs`.
|
||||
|
||||
- **`PasteCommand.Execute` silently ignores invalid contexts**
|
||||
If `parameter` is not a `TextBox`, or `DataContext` is not an `IChannelCode`/builder, the method returns without error or logging (except via `PageErrorEvent` on exception).
|
||||
|
||||
- **`CoerceISOCodeDelegate` is declared but not implemented here**
|
||||
Its purpose is documented, but no concrete implementation is provided in this module.
|
||||
|
||||
- **`ChannelCode` constructor with `IDataReader` relies on column names and lookup dictionary**
|
||||
If `channelTypeLookup` lacks the key from `CodeTypeInt`, or columns are missing, behavior is undefined (no explicit validation is present).
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Connection/NotConnectedException.cs
|
||||
generated_at: "2026-04-16T02:39:10.292945+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "ebd03ba552c1193d"
|
||||
---
|
||||
|
||||
# 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 is established. It resides in the `DTS.Common.Classes.Connection` namespace, indicating its role in the common core infrastructure for managing connection state across the DTS system. Its purpose is to provide a semantically precise exception for connection-state violations, distinguishing them from generic `ApplicationException` or `InvalidOperationException` cases.
|
||||
|
||||
2. **Public Interface**
|
||||
- **`NotConnectedException(string message)`**
|
||||
Constructor that initializes the exception with a specified error message. It delegates to the base `ApplicationException` constructor. No additional properties or methods are exposed beyond those inherited from `Exception`.
|
||||
|
||||
3. **Invariants**
|
||||
- The exception inherits all standard `Exception` invariants (e.g., `Message`, `StackTrace`, `InnerException` behavior).
|
||||
- The exception is *only* intended for use when an operation requires an active connection but none exists; it is not a general-purpose connection error.
|
||||
- No validation or state management is performed by this class itself—it is a passive data carrier.
|
||||
|
||||
4. **Dependencies**
|
||||
- **Depends on**: `System.ApplicationException` (from `mscorlib`/`System.Runtime`).
|
||||
- **Used by**: Presumably connection-handling classes (e.g., `Connection`, `Client`, or `Session` types in the `DTS.Common.Classes.Connection` namespace or related modules), though these are not visible in this file.
|
||||
- **Not used by**: No other code in this file; this is a standalone type definition.
|
||||
|
||||
5. **Gotchas**
|
||||
- `ApplicationException` is deprecated in modern .NET best practices (replaced by `Exception` or more specific built-in exceptions like `InvalidOperationException`), suggesting this may be legacy code or part of an older design pattern.
|
||||
- The class provides no additional context (e.g., connection ID, endpoint, or timestamp), so callers must embed such details in the `message` string if needed for diagnostics.
|
||||
- No serialization support is explicitly implemented (e.g., `[Serializable]` attribute or custom `GetObjectData`), though `ApplicationException` itself is serializable by default in .NET Framework—behavior may differ in .NET Core/.NET 5+.
|
||||
- None identified from source alone.
|
||||
@@ -0,0 +1,201 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/DASFactory/TemperatureConfig.cs
|
||||
- Common/DTS.CommonCore/Classes/DASFactory/TMSNConfig.cs
|
||||
- Common/DTS.CommonCore/Classes/DASFactory/ATDStagger.cs
|
||||
generated_at: "2026-04-16T02:41:35.863754+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "b5e818821adb9531"
|
||||
---
|
||||
|
||||
# DASFactory
|
||||
|
||||
## Documentation: DASFactory Configuration Classes
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module provides strongly-typed configuration classes for DASFactory subsystems, encapsulating low-level data structures used for communication with hardware devices. Specifically, `TemperatureConfig` manages temperature/humidity logging channel selection and timing, `TMNSConfig` encapsulates TMNS (Telemetry Network Service) streaming parameters, and `ATDStagger` (currently commented out) was designed to serialize device command execution to avoid communication bottlenecks. These classes replace raw arrays with named fields and helper methods to improve maintainability, type safety, and clarity in configuration serialization/deserialization workflows.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `TemperatureConfig`
|
||||
|
||||
- **`public ushort LogEnable { get; set; }`**
|
||||
Enables/disables logging (non-zero = enabled).
|
||||
|
||||
- **`public ushort LogIntervalSec { get; set; }`**
|
||||
Logging interval in seconds.
|
||||
|
||||
- **`public ushort Channels { get; set; }`**
|
||||
Bitfield representing enabled channels (16-bit value). Setting updates internal `BitArray`; reading converts `BitArray` to `ushort`.
|
||||
|
||||
- **`public const ushort Reserved = 0;`**
|
||||
Reserved field value (always 0).
|
||||
|
||||
- **`public bool MCUTemp { get; set; }`**
|
||||
Gets/sets the On-Board MCU Temperature channel (bit 0 of `_channels`).
|
||||
|
||||
- **`public bool OnBoardHumidity { get; set; }`**
|
||||
Gets/sets the On-Board Humidity channel (bit 1 of `_channels`).
|
||||
|
||||
- **`public bool EnvironmentalCh1 { get; set; }`**
|
||||
Gets/sets Environmental Channel 1 (bit 2 of `_channels`).
|
||||
|
||||
- **`public bool EnvironmentalCh2 { get; set; }`**
|
||||
Gets/sets Environmental Channel 2 (bit 3 of `_channels`).
|
||||
|
||||
- **`public bool EnvironmentalCh3 { get; set; }`**
|
||||
Gets/sets Environmental Channel 3 (bit 4 of `_channels`).
|
||||
|
||||
- **`public bool EnvironmentalCh4 { get; set; }`**
|
||||
Gets/sets Environmental Channel 4 (bit 5 of `_channels`).
|
||||
|
||||
- **`public ushort[] ToUShortArray()`**
|
||||
Returns `[LogEnable, LogIntervalSec, Channels, Reserved]` in that order.
|
||||
|
||||
- **`public TemperatureConfig()`**
|
||||
Default constructor.
|
||||
|
||||
- **`public TemperatureConfig(ushort[] ushortArray)`**
|
||||
Constructor from `ushort[]`. Reads indices 0–2; missing indices default to `0`. Does *not* initialize `Reserved`.
|
||||
|
||||
- **`public int[] GetChannelsArray()`**
|
||||
Returns list of bit indices where `_channels` is set (e.g., `[0,2,4]` if MCUTemp, Ch1, Ch3 enabled).
|
||||
|
||||
- **`public S6DBDiagnosticChannelList[] GetMeasurementChannels()`**
|
||||
Maps enabled channels to corresponding `S6DBDiagnosticChannelList` enum values (e.g., `DiagMcuTemperature`, `DiagEnv_1_Temperature`, etc.).
|
||||
|
||||
- **`public TempLogChannelBits GetChannelBitForDiagChannel(S6DBDiagnosticChannelList ch)`**
|
||||
Maps a `S6DBDiagnosticChannelList` value to its corresponding `TempLogChannelBits` enum. Throws `NullReferenceException` if not found.
|
||||
|
||||
#### `TMNSConfig`
|
||||
|
||||
- **`public uint TMNS_PCMSubFrameId { get; set; }`**
|
||||
TMNS PCM sub-frame ID.
|
||||
|
||||
- **`public uint TMNS_MsgId { get; set; }`**
|
||||
TMNS message ID.
|
||||
|
||||
- **`public uint TMNS_PCMMinorPerMajor { get; set; }`**
|
||||
TMNS PCM minor-per-major setting.
|
||||
|
||||
- **`public uint TMNS_TMATSPortNumber { get; set; }`**
|
||||
TMNS TMATS port number.
|
||||
|
||||
- **`public uint IENAUDP_PortNumber { get; set; }`**
|
||||
IENA UDP source port number.
|
||||
|
||||
- **`public uint TMNS5, TMNS6, TMNS7 { get; set; }`**
|
||||
Reserved fields (5–7).
|
||||
|
||||
- **`public enum Fields { ... }`**
|
||||
Ordered list of field indices: `TMNS_PCMSubFrameID`, `TMNS_MsgId`, `TMNS_PCMMinorPerMajor`, `TMNS_TMATSPortNumber`, `IENAUDP_PortNumber`, `TMNS5`, `TMNS6`, `TMNS7`.
|
||||
|
||||
- **`public TMNSConfig()`**
|
||||
Default constructor; initializes `_values` array to length 8 with zeros.
|
||||
|
||||
- **`public TMNSConfig(uint[] parameters)`**
|
||||
Constructor from `uint[]`. Copies up to 8 values; missing indices default to `0`.
|
||||
|
||||
- **`public TMNSConfig(string parameters)`**
|
||||
Constructor from comma-separated string (e.g., `"(1,2,3)"`). Parses `uint` values; invalid tokens default to `0`.
|
||||
|
||||
- **`public void SetValue(Fields field, uint value)`**
|
||||
Sets `_values[(int)field]`.
|
||||
|
||||
- **`public uint GetValue(Fields field)`**
|
||||
Returns `_values[(int)field]`.
|
||||
|
||||
- **`public uint[] ToUintArray()`**
|
||||
Returns a copy of `_values`.
|
||||
|
||||
- **`public string ToCSVString()`**
|
||||
Returns string in format `"(x,y,z,...)"`.
|
||||
|
||||
- **`public static bool IsCh10(UDPStreamProfile profile)`**
|
||||
Returns `true` if `profile` is one of the CH10 variants.
|
||||
|
||||
- **`public static bool IsIENA(UDPStreamProfile profile)`**
|
||||
Returns `true` if `profile == UDPStreamProfile.IENA_PTYPE_STREAM`.
|
||||
|
||||
- **`public static bool IsTMNS(UDPStreamProfile profile)`**
|
||||
Returns `true` if `profile` is `TMNS_PCM_STANDARD` or `TMNS_PCM_SUPERCOM`.
|
||||
|
||||
- **`public static bool IsUART(UDPStreamProfile profile)`**
|
||||
Returns `true` if `profile == UDPStreamProfile.UART_STREAM`.
|
||||
|
||||
#### `ATDStagger` *(commented out)*
|
||||
|
||||
- **No public interface is active** — the entire class is commented out. The source includes only historical comments and implementation notes. No runtime behavior can be documented.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **`TemperatureConfig`**
|
||||
- `_channels` is always a 16-bit `BitArray` (2 bytes), initialized to `0x0000`.
|
||||
- `Channels` property setter always replaces `_channels` with a new `BitArray` constructed from the `ushort`’s bytes.
|
||||
- `LogEnable`, `LogIntervalSec`, and `Channels` are the only fields populated from `ushort[]` constructor; `Reserved` is ignored in constructor.
|
||||
- `GetChannelBitForDiagChannel` throws `NullReferenceException` (not `KeyNotFoundException`) if the key is missing — a bug in implementation.
|
||||
|
||||
- **`TMNSConfig`**
|
||||
- `_values` is always exactly 8 elements long (matching `Fields` enum count).
|
||||
- `ToUintArray()` returns a *copy*, not a reference.
|
||||
- `ToCSVString()` always includes parentheses and commas, even for empty/zero values.
|
||||
|
||||
- **`ATDStagger`**
|
||||
- *N/A* — class is commented out; no invariants apply.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
- **`TemperatureConfig`**
|
||||
- **Imports**: `DTS.Common.Enums.DASFactory` (for `DFConstantsAndEnums`, `TempLogChannelBits`), `System`, `System.Collections`, `System.Collections.Generic`.
|
||||
- **Uses**: `BitConverter`, `BitArray`.
|
||||
- **Depends on**: `TempLogChannelBits` and `S6DBDiagnosticChannelList` enums (defined in `DTS.Common.Enums.DASFactory` and `DTS.Common.Enums`, respectively — not shown).
|
||||
- **Used by**: Likely consumed by firmware/hardware communication layers to configure logging; inferred from usage of `ToUShortArray()` and `GetMeasurementChannels()`.
|
||||
|
||||
- **`TMNSConfig`**
|
||||
- **Imports**: `DTS.Common.Enums`, `System`, `System.Linq`, `System.Text`.
|
||||
- **Uses**: `UDPStreamProfile` enum (from `DTS.Common.Enums` — not shown).
|
||||
- **Depends on**: `UDPStreamProfile` for `IsCh10`, `IsIENA`, `IsTMNS`, `IsUART` methods.
|
||||
- **Used by**: Likely used by telemetry configuration modules (e.g., FWTU, DP — mentioned in summary).
|
||||
|
||||
- **`ATDStagger`**
|
||||
- **Imports**: `DTS.Common.Interface.DASFactory`, `DTS.Common.Utilities.Logging`, `System`, `System.Collections.Generic`, `System.Data`, `System.Linq`.
|
||||
- **Uses**: `IDASCommunication`, `ICommunication`, `APILogger`, `IDbCommand`.
|
||||
- **Depends on**: Database schema (`[DataPro].[dbo].[DAS]` table with columns `SerialNumber`, `PositionOnDistributor`, `PositionOnChain`, `Port`, `ParentDAS`), and `IsSlice6Distributor()` extension method.
|
||||
- **Used by**: Service execution logic (not visible in source).
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`TemperatureConfig`**
|
||||
- `Reserved` is a `const`, but the `ushort[]` constructor does *not* read index 3 — `Reserved` is always `0` regardless of input.
|
||||
- `GetChannelBitForDiagChannel` throws `NullReferenceException` instead of `KeyNotFoundException` — misleading and non-idiomatic.
|
||||
- `Channels` setter uses `BitConverter.ToUInt16(bytes, 0)` — assumes little-endian platform (standard on .NET, but not guaranteed by spec).
|
||||
- `GetUShort` silently defaults to `0` for out-of-bounds indices — may hide configuration errors.
|
||||
|
||||
- **`TMNSConfig`**
|
||||
- `ToCSVString()` always includes parentheses — callers expecting bare comma-separated values may need to strip them.
|
||||
- String constructor allows `(1,2,3)` but does *not* validate length — extra tokens are ignored, missing tokens default to `0`.
|
||||
- `IsCh10`, `IsIENA`, etc., are `static` and operate on `UDPStreamProfile` — not directly tied to `TMNSConfig` instance state.
|
||||
|
||||
- **`ATDStagger`**
|
||||
- Entire class is commented out — do not use. Historical comments suggest it was intended for ATD device sequencing but was never enabled.
|
||||
- Logic for assigning devices to ports (e.g., "even if we end up talking to 4 devices on one port it’ll be better...") is heuristic and not guaranteed optimal.
|
||||
|
||||
- **All Classes**
|
||||
- No validation on `LogIntervalSec` (e.g., no minimum/maximum checks).
|
||||
- No thread-safety guarantees beyond `lock` usage in `ATDStagger` (which is commented out). `TemperatureConfig` and `TMNSConfig` are not thread-safe.
|
||||
|
||||
- **None identified from source alone** for `ATDStagger` — class is inactive.
|
||||
|
||||
---
|
||||
@@ -0,0 +1,61 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/Commands/RelayCommand.cs
|
||||
generated_at: "2026-04-16T02:42:33.604683+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "63672ade54ed35d0"
|
||||
---
|
||||
|
||||
# Commands
|
||||
|
||||
### **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 serves as a lightweight command adapter that forwards `Execute` and `CanExecute` calls to user-provided delegates, supporting both mandatory execution logic and optional, parameterized execution guards. This pattern is foundational for implementing MVVM-style command binding in WPF.
|
||||
|
||||
---
|
||||
|
||||
### **Public Interface**
|
||||
All members are public and part of the `RelayCommand` class.
|
||||
|
||||
- **`RelayCommand(Action<object> execute)`**
|
||||
Constructor. Initializes the command with an execution delegate and no `CanExecute` guard (i.e., `CanExecute` always returns `true`). Throws `ArgumentNullException` if `execute` is `null`.
|
||||
|
||||
- **`RelayCommand(Action<object> execute, Predicate<object> canExecute)`**
|
||||
Constructor. Initializes the command with both execution and guard delegates. Throws `ArgumentNullException` if `execute` is `null`. The `canExecute` parameter may be `null`, in which case `CanExecute` defaults to `true`.
|
||||
|
||||
- **`bool CanExecute(object parameter)`**
|
||||
Implements `ICommand.CanExecute`. Invokes the stored `_canExecute` predicate (if non-null) with `parameter`; otherwise returns `true`.
|
||||
|
||||
- **`void Execute(object parameter)`**
|
||||
Implements `ICommand.Execute`. Invokes the stored `_execute` action with `parameter`. No validation is performed on `parameter` beyond null-safety of the delegate itself.
|
||||
|
||||
- **`event EventHandler CanExecuteChanged`**
|
||||
Implements `ICommand.CanExecuteChanged`. Subscribes/unsubscribes to `CommandManager.RequerySuggested`, enabling automatic re-evaluation of `CanExecute` when WPF detects relevant state changes (e.g., keyboard/mouse input, focus changes).
|
||||
|
||||
---
|
||||
|
||||
### **Invariants**
|
||||
- `_execute` is **never null** after construction (enforced via `ArgumentNullException` in both constructors).
|
||||
- `_canExecute` may be `null`; if so, `CanExecute` always returns `true`.
|
||||
- `CanExecuteChanged` event handlers are **always** attached to `CommandManager.RequerySuggested`, ensuring WPF’s command system triggers requery logic.
|
||||
- No explicit validation is performed on the `parameter` passed to `Execute` or `CanExecute`; nulls are passed directly to the delegates.
|
||||
|
||||
---
|
||||
|
||||
### **Dependencies**
|
||||
- **External Dependencies**:
|
||||
- `System` (for `Action<T>`, `Predicate<T>`, `ArgumentNullException`)
|
||||
- `System.Windows.Input` (for `ICommand`, `CommandManager`)
|
||||
- **Internal Dependencies**:
|
||||
- No other modules in the codebase are referenced (self-contained).
|
||||
- **Depended Upon**:
|
||||
- Likely consumed by WPF UI layers (e.g., `Button.Command` bindings) and view models throughout the `DTS.Viewer` subsystem.
|
||||
|
||||
---
|
||||
|
||||
### **Gotchas**
|
||||
- **No manual `CanExecuteChanged` raising**: The class relies solely on `CommandManager.RequerySuggested` to trigger `CanExecute` re-evaluation. If the command’s executability depends on non-UI state changes (e.g., background thread updates), callers must manually invoke `CommandManager.InvalidateRequerySuggested()` (or similar) to force updates.
|
||||
- **Parameter handling**: The `parameter` passed to `Execute`/`CanExecute` is unvalidated. Passing `null` is permitted and will be forwarded to the delegates—consumers must handle `null` parameters explicitly if needed.
|
||||
- **Thread affinity**: `CommandManager.RequerySuggested` is raised on the UI thread. If `CanExecute` delegates access non-UI-thread resources, thread-safety must be ensured by the caller.
|
||||
- **No disposal pattern**: The class does not implement `IDisposable`, and event subscriptions (via `CanExecuteChanged`) are not explicitly cleaned up—relying on WPF’s lifetime management. This is acceptable for typical view model lifetimes but may cause leaks in long-lived command instances.
|
||||
- **No async support**: `Execute` is synchronous; asynchronous operations require manual wrapping (e.g., `async void` or fire-and-forget), which is error-prone.
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/Reports/ChannelGRMSSummary.cs
|
||||
generated_at: "2026-04-16T02:42:43.162304+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "7b6bc8e72ad59bb8"
|
||||
---
|
||||
|
||||
# Reports
|
||||
|
||||
### **Purpose**
|
||||
This module defines the `ChannelGRMSSummary` class, a data container for summarizing GRMS (Gaussian Root Mean Square) vibration metrics for a single channel in a test or analysis report. It implements `INotifyPropertyChanged` to support data binding scenarios (e.g., UI views), enabling reactive updates when property values change. The class serves as a lightweight, observable model for reporting tools that visualize or export channel-level GRMS results.
|
||||
|
||||
---
|
||||
|
||||
### **Public Interface**
|
||||
|
||||
- **`ChannelName`** (`string` property)
|
||||
Gets or sets the human-readable name of the channel (e.g., `"Ch1-Accel-X"`).
|
||||
|
||||
- **`SampleRate`** (`int` property)
|
||||
Gets or sets the sample rate (in Hz) associated with the channel’s data.
|
||||
|
||||
- **`GRMS`** (`double` property)
|
||||
Gets or sets the computed GRMS value (a scalar vibration intensity metric) for the channel.
|
||||
|
||||
- **`PropertyChanged`** (`event PropertyChangedEventHandler`)
|
||||
Event raised when a property value changes. Used by data-binding frameworks (e.g., WPF, WinForms) to refresh UI elements.
|
||||
|
||||
- **`OnPropertyChanged(string propertyName)`** (`void` method)
|
||||
Invokes the `PropertyChanged` event with the specified property name. Callers must ensure `propertyName` matches the actual property name (e.g., `"GRMS"`) to maintain binding correctness.
|
||||
|
||||
---
|
||||
|
||||
### **Invariants**
|
||||
- `ChannelName` may be `null` or empty; no validation is enforced in the class itself.
|
||||
- `SampleRate` is an `int`, but no constraints (e.g., positive values) are enforced.
|
||||
- `GRMS` is a `double`; negative values are *not* logically invalid at the type level but may be semantically nonsensical (GRMS is typically ≥0).
|
||||
- The `OnPropertyChanged` method does **not** validate whether `propertyName` corresponds to a real property; invalid names will still trigger the event.
|
||||
- Thread safety is **not** guaranteed; `PropertyChanged` invocation is not synchronized.
|
||||
|
||||
---
|
||||
|
||||
### **Dependencies**
|
||||
- **Depends on**:
|
||||
- `System.ComponentModel` (for `INotifyPropertyChanged` via `PropertyChangedEventHandler` and `PropertyChangedEventArgs`).
|
||||
- `DTS.Common.Interface` (for the `IChannelGRMSSummary` interface—implementation is implicit via class declaration).
|
||||
- **Implements**:
|
||||
- `IChannelGRMSSummary` (from `DTS.Common.Interface`), though the interface definition is not provided here.
|
||||
- **Used by**:
|
||||
- Presumably UI components (e.g., data grids, charts) that bind to GRMS summary reports.
|
||||
- Report-generation logic that aggregates or filters channel-level results.
|
||||
|
||||
---
|
||||
|
||||
### **Gotchas**
|
||||
- **No null-safety for `PropertyChanged`**: The null-conditional operator (`?.`) is used in `OnPropertyChanged`, but callers must still ensure `propertyName` is non-null to avoid runtime issues (though `null` would only cause no event to fire, not an exception).
|
||||
- **No validation on `GRMS`**: Negative or `NaN` values are permitted; consumers must handle invalid values appropriately.
|
||||
- **No explicit interface implementation**: The class declares `public event PropertyChangedEventHandler PropertyChanged` rather than explicit `INotifyPropertyChanged.PropertyChanged`, which may expose the event unnecessarily in some contexts.
|
||||
- **No documentation of `IChannelGRMSSummary`**: Without the interface definition, it is unclear whether `IChannelGRMSSummary` enforces additional members (e.g., `ToString()`, comparison logic).
|
||||
- **No constructor**: Relies on auto-implemented properties and default initialization; callers must explicitly set all properties post-instantiation.
|
||||
@@ -0,0 +1,300 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestMetadata.cs
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestGraphs.cs
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestSetupMetadata.cs
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestRunMetadata.cs
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestSummary.cs
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestModule.cs
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestChannel.cs
|
||||
- Common/DTS.CommonCore/Classes/DTS.Viewer/TestMetadata/TestMetadataList.cs
|
||||
generated_at: "2026-04-16T02:42:52.937741+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "c38901448183a71b"
|
||||
---
|
||||
|
||||
# Documentation: TestMetadata Module
|
||||
|
||||
## 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 XML metadata files into strongly-typed objects and constructing `TestSummary` instances for UI consumption, including timestamp resolution using PTP1588 timing data when available.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `TestMetadataList`
|
||||
|
||||
#### `GetTestSummaryListAsync(IBaseViewModel parent, string path, string file, string pattern = "")`
|
||||
- **Behavior**: Asynchronous wrapper (currently synchronous implementation) that returns an `ObservableCollection<ITestSummary>` by parsing `.dts` files in the specified directory. Uses `pattern` to filter files (default: `.dts`). Requires `parent` for view model hierarchy.
|
||||
|
||||
#### `GetTestSummaryList(IBaseViewModel parent, string path, string file = "", string pattern = "")`
|
||||
- **Behavior**: Synchronously returns an `ObservableCollection<ITestSummary>` by parsing `.dts` files. Uses `parent` to set `TestSummary.Parent`.
|
||||
|
||||
#### `GetTestSummaryList(string path, string file = "", string pattern = "")`
|
||||
- **Behavior**: Same as above but without a `parent` parameter (used when parent is not applicable or set later).
|
||||
|
||||
#### `GetTestMetadataList(XDocument xDoc, string path, string file)`
|
||||
- **Behavior**: Parses an `XDocument` (loaded `.dts` XML) into a `List<ITestMetadata>`. Handles channel array initialization and publishes errors via `IEventAggregator` on failure. Returns empty list on exception.
|
||||
|
||||
### `TestMetadata`
|
||||
|
||||
- **Properties**:
|
||||
- `ITestRunMetadata TestRun { get; set; }`
|
||||
- `ITestSetupMetadata TestSetup { get; set; }`
|
||||
- **Behavior**: Simple container for test run and setup metadata.
|
||||
|
||||
### `TestRunMetadata`
|
||||
|
||||
- **Properties**:
|
||||
- `string Name { get; set; }` — Logical test name (from XML `@Id` attribute).
|
||||
- `string Id { get; set; }` — File name without extension (derived from `@FilePath`).
|
||||
- `string Description { get; set; }`
|
||||
- `bool InlineSerializedData { get; set; }`
|
||||
- `string TestGuid { get; set; }`
|
||||
- `int FaultFlags { get; set; }`
|
||||
- `string Software { get; set; }`
|
||||
- `string SoftwareVersion { get; set; }`
|
||||
- `string DataType { get; set; }`
|
||||
- `DateTime FileDate { get; set; }`
|
||||
- `string FilePath { get; set; }`
|
||||
- `List<ITestModule> Modules { get; set; }`
|
||||
- `List<ITestChannel> Channels { get; set; }`
|
||||
- `List<ITestChannel> CalculatedChannels { get; set; }`
|
||||
- `bool IsSelected { get; set; }`
|
||||
- **Events**:
|
||||
- `event PropertyChangedEventHandler PropertyChanged` — Implements `INotifyPropertyChanged`.
|
||||
|
||||
### `TestSetupMetadata`
|
||||
|
||||
- **Properties**:
|
||||
- `string SetupName { get; set; }`
|
||||
- `DateTime TimeStamp { get; set; }`
|
||||
- `List<ITestGraphs> TestGraphs { get; set; }`
|
||||
- `CalibrationBehaviors CalibrationBehavior { get; set; }`
|
||||
|
||||
### `TestGraphs`
|
||||
|
||||
- **Properties**:
|
||||
- `string Name { get; set; }`
|
||||
- `string HardwareChannelName { get; set; }`
|
||||
- `List<string> ChannelIds { get; set; }`
|
||||
- `List<ITestChannel> Channels { get; set; }`
|
||||
|
||||
### `TestModule`
|
||||
|
||||
- **Properties**:
|
||||
- `string SerialNumber { get; set; }`
|
||||
- `string BaseSerialNumber { get; set; }`
|
||||
- `int AaFilterRateHz { get; set; }`
|
||||
- `int Number { get; set; }`
|
||||
- `int NumberOfSamples { get; set; }`
|
||||
- `int UnsubsampledNumberOfSamples { get; set; }`
|
||||
- `double RequestedPostTriggerSeconds { get; set; }`
|
||||
- `double RequestedPreTriggerSeconds { get; set; }`
|
||||
- `double PostTriggerSeconds { get; set; }`
|
||||
- `double PreTriggerSeconds { get; set; }`
|
||||
- `string RecordingMode { get; set; }`
|
||||
- `int SampleRateHz { get; set; }`
|
||||
- `int StartRecordSampleNumber { get; set; }`
|
||||
- `int NumberOfChannels { get; set; }`
|
||||
- `bool InlineSerializedData { get; set; }`
|
||||
- `int StartRecordTimestampSec { get; set; }`
|
||||
- `int StartRecordTimestampNanoSec { get; set; }`
|
||||
- `int TriggerTimestampSec { get; set; }`
|
||||
- `int TriggerTimestampNanoSec { get; set; }`
|
||||
- `List<ulong> TriggerSampleNumbers { get; set; }` — *Always empty* (see *Gotchas*).
|
||||
- `bool PTPMasterSync { get; set; }`
|
||||
- `int TiltSensorAxisX/Y/ZDegreesPre/Post { get; set; }`
|
||||
- `int TemperatureLocation1/2/3/4Pre/Post { get; set; }`
|
||||
- `List<ITestChannel> Channels { get; set; }`
|
||||
- `List<ITestChannel> CalculatedChannels { get; set; }`
|
||||
- `bool IsSelected { get; set; }`
|
||||
- **Events**:
|
||||
- `event PropertyChangedEventHandler PropertyChanged`
|
||||
|
||||
### `TestChannel`
|
||||
|
||||
- **Properties**:
|
||||
- `string Group { get; set; }`
|
||||
- `string SubGroup { get; set; }`
|
||||
- `bool IsGraphChannel { get; set; }`
|
||||
- `string GraphName { get; set; }`
|
||||
- `string TestId { get; set; }`
|
||||
- `string TestSetupName { get; set; }`
|
||||
- `string ModuleSerialNumber { get; set; }`
|
||||
- `string SerialNumber { get; set; }`
|
||||
- `string ChannelId { get; set; }`
|
||||
- `string ChannelDisplayName { get; set; }`
|
||||
- `string Description { get; set; }`
|
||||
- `string IsoCode { get; set; }`
|
||||
- `string IsoChannelName { get; set; }`
|
||||
- `string UserCode { get; set; }`
|
||||
- `string UserChannelName { get; set; }`
|
||||
- `string ChannelGroupName { get; set; }`
|
||||
- `string ChannelType { get; set; }`
|
||||
- `bool IsCalculatedChannel { get; set; }`
|
||||
- `int Number { get; set; }`
|
||||
- `string DigitalMultiplier { get; set; }`
|
||||
- `string DigitalMode { get; set; }`
|
||||
- `DateTime Start { get; set; }`
|
||||
- `string Bridge { get; set; }`
|
||||
- `double BridgeResistanceOhms { get; set; }`
|
||||
- `double ZeroPoint { get; set; }`
|
||||
- `string ChannelDescriptionString { get; set; }`
|
||||
- `string ChannelName2 { get; set; }`
|
||||
- `string HardwareChannelName { get; set; }`
|
||||
- `double DesiredRange { get; set; }`
|
||||
- `double ActualMaxRangeEu { get; set; }`
|
||||
- `double ActualMinRangeEu { get; set; }`
|
||||
- `double ActualMaxRangeAdc { get; set; }` — Always `short.MaxValue`
|
||||
- `double ActualMinRangeAdc { get; set; }` — Always `short.MinValue`
|
||||
- `double ActualMaxRangeMv { get; set; }`
|
||||
- `double ActualMinRangeMv { get; set; }`
|
||||
- `double Sensitivity { get; set; }`
|
||||
- `string SoftwareFilter { get; set; }`
|
||||
- `bool ProportionalToExcitation { get; set; }`
|
||||
- `bool IsInverted { get; set; }`
|
||||
- `string LinearizationFormula { get; set; }`
|
||||
- `bool IsSubsampled { get; set; }`
|
||||
- `int AbsoluteDisplayOrder { get; set; }`
|
||||
- `DateTime LastCalibrationDate { get; set; }`
|
||||
- `string SensorId { get; set; }`
|
||||
- `int OffsetToleranceLowMv { get; set; }`
|
||||
- `int OffsetToleranceHighMv { get; set; }`
|
||||
- `int DataFlag { get; set; }`
|
||||
- `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; }`
|
||||
- `int InitialEu { get; set; }`
|
||||
- `string InitialOffset { get; set; }`
|
||||
- `int UnsubsampledSampleRateHz { get; set; }`
|
||||
- `double MeasuredShuntDeflectionMv { get; set; }`
|
||||
- `double TargetShuntDeflectionMv { get; set; }`
|
||||
- `double MeasuredExcitationVoltage { get; set; }`
|
||||
- `double FactoryExcitationVoltage { get; set; }`
|
||||
- `double TimeOfFirstSample { get; set; }`
|
||||
- `double Multiplier { get; set; }`
|
||||
- `double UserOffsetEu { get; set; }`
|
||||
- `int UnitConversion { get; set; }`
|
||||
- `bool AtCapacity { get; set; }`
|
||||
- `int CapacityOutputIsBasedOn { get; set; }`
|
||||
- `string SourceChannelNumber { get; set; }`
|
||||
- `string SourceModuleNumber { get; set; }`
|
||||
- `string SourceModuleSerialNumber { get; set; }`
|
||||
- `string Calculation { get; set; }`
|
||||
- `int SampleRateHz { get; set; }`
|
||||
- `string SensitivityUnits { get; set; }`
|
||||
- `int SensorCapacity { get; set; }`
|
||||
- `string SensorPolarity { get; set; }`
|
||||
- `int ChannelNumber { get; set; }`
|
||||
- `string BinaryFileName { get; set; }`
|
||||
- `string BinaryFilePath { get; set; }`
|
||||
- `double Xmax { get; set; }`
|
||||
- `double Xmin { get; set; }`
|
||||
- `int SequentialNumbers { get; set; }`
|
||||
- `ITestSetupMetadata ParentTestSetup { get; set; }`
|
||||
- `ITestModule ParentModule { get; set; }`
|
||||
- `IBaseViewModel Parent { get; set; }`
|
||||
- `Color ChannelColor { get; set; }`
|
||||
- `string ErrorMessage { get; set; }`
|
||||
- `bool IsError { get; set; }`
|
||||
- `Color? ErrorColor { get; set; }` — Derived from `IsError`.
|
||||
- `bool IsLocked { get; set; }`
|
||||
- `bool CanLock { get; set; }`
|
||||
- `bool CanSelectChannel { get; set; }`
|
||||
- `bool IsExpanded { get; set; }`
|
||||
- `bool IsSelected { get; set; }`
|
||||
- `double MinADC/MaxADC/AveADC/StdDevADC/T0ADC { get; set; }`
|
||||
- `double MinMV/MaxMV/AveMV/StdDevMV/T0MV { get; set; }`
|
||||
- `double MinEU/MaxEU/AveEU/StdDevEU/T0EU { get; set; }`
|
||||
- `double MinY/MaxY/AveY/StdDevY/T0Value { get; set; }`
|
||||
- **Methods**:
|
||||
- `void SetChannelDescriptionAndDisplayName(string channelDescription)` — Sets `ChannelDescriptionString` and `ChannelDisplayName`.
|
||||
- `ITestChannel Copy()` — Shallow copy via `MemberwiseClone()`.
|
||||
- `override string ToString()` — Returns `ChannelDescriptionString` or `"N/A"` if test-specific embedded.
|
||||
- **Events**:
|
||||
- `event PropertyChangedEventHandler PropertyChanged` — Inherited from `BasePropertyChanged`.
|
||||
|
||||
### `TestSummary`
|
||||
|
||||
- **Properties**:
|
||||
- `string Id { get; set; }` — Concatenation of `TestRun.Id` and event number from `FilePath`.
|
||||
- `string SetupName { get; set; }`
|
||||
- `string Description { get; set; }`
|
||||
- `int ChannelCount { get; set; }`
|
||||
- `DateTime FileDate { get; set; }`
|
||||
- `DateTime TimeStamp { get; set; }` — Derived from module PTP timestamps if valid, else `TestSetup.TimeStamp`.
|
||||
- `string DataType { get; set; }`
|
||||
- `bool IsSelected { get; set; }`
|
||||
- `List<ITestGraphs> Graphs { get; set; }`
|
||||
- `List<ITestChannel> Channels { get; set; }`
|
||||
- `List<ITestChannel> CalculatedChannels { get; set; }`
|
||||
- `IBaseViewModel Parent { get; set; }`
|
||||
- `CalibrationBehaviors CalibrationBehavior { get; set; }` — Default: `NonLinearIfAvailable`.
|
||||
- `ITestMetadata TestMetadata { get; set; }`
|
||||
- **Commands**:
|
||||
- `DelegateCommand IsSelectedCommand { get; }` — Toggles selection and updates `Parent.SelectedTestSummaryList`.
|
||||
- **Methods**:
|
||||
- `void SelectionChanged()` — Adds/removes `this` from `Parent.SelectedTestSummaryList` and calls `PublishSelectedTestSummaryList()` on parent.
|
||||
- `void OnPropertyChanged(string propertyName)` — Raises `PropertyChanged`.
|
||||
- **Events**:
|
||||
- `event PropertyChangedEventHandler PropertyChanged`
|
||||
- **Constants**:
|
||||
- `public const string ROI_SUFFIX = @"_ROI Period";`
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`TestMetadata`**: Must contain non-null `TestRun` and `TestSetup` references after successful parsing.
|
||||
- **`TestRunMetadata.Channels` and `TestRunMetadata.CalculatedChannels`**: Initialized as empty lists during parsing if missing in XML.
|
||||
- **`TestModule.TriggerSampleNumbers`**: Always initialized as an empty list; never populated (see *Gotchas*).
|
||||
- **`TestChannel.ChannelId`**: If missing or `-1` in XML, defaults to `m.GetHashCode().ToString()` (non-deterministic).
|
||||
- **`TestChannel.HardwareChannelName`**: For calculated channels, always set to `"N/A"` (via `Strings.Strings.Table_NA`).
|
||||
- **`TestChannel.SerialNumber`**: For calculated channels, always set to `"N/A"`.
|
||||
- **`TestSummary.TimeStamp`**: Falls back to `TestSetup.TimeStamp` if PTP timestamps are invalid or unavailable.
|
||||
- **`TestSummary.Id`**: Always includes event number extracted from `FilePath` via `ParseEventNumber`.
|
||||
- **`TestChannel.IsCalculatedChannel`**: Must be `true` for channels loaded via `LoadTestCalculatedChannels`.
|
||||
- **`TestSummary.IsSelected`**: Setter enforces selection logic via `SelectionChanged()` and `Parent` interaction.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Internal Dependencies (from source):
|
||||
- **Interfaces**:
|
||||
- `DTS.Common.Interface.ITestMetadata`, `ITestRunMetadata`, `ITestSetupMetadata`, `ITestGraphs`, `ITestModule`, `ITestChannel`, `ITestSummary`, `IBaseViewModel`, `IGraphMainViewModel`
|
||||
- **Enums**:
|
||||
- `DTS.Common.Enums.Sensors.CalibrationBehaviors`
|
||||
- **Utilities**:
|
||||
- `DTS.Common.XMLUtils.TestMetadataXml`
|
||||
- `DTS.Common.Base.BasePropertyChanged`
|
||||
- `DTS.Common.Constants.EventNumber`
|
||||
- `DTS.Common.Utils.TestUtils`, `PTP1588Timestamps`
|
||||
- `DTS.Common.XMLUtils.TestMetadataFields`, `TestSetupMetadataFields`, `TestGraphsFields`, `TestModuleFields`, `TestChannelFields`
|
||||
- `DTS.Common.Strings.Strings`
|
||||
- **Prism Framework**:
|
||||
- `Microsoft.Practices.Prism.Commands.DelegateCommand`
|
||||
- `Microsoft.Practices.Prism.Events.IEventAggregator`, `Events.PageErrorEvent`
|
||||
- `Microsoft.Practices.ServiceLocation.ServiceLocator`
|
||||
|
||||
### External Dependencies:
|
||||
- `System.Xml.Linq`
|
||||
- `System.Collections.ObjectModel`
|
||||
- `System.ComponentModel`
|
||||
- `System.Windows.Media` (for `Color`)
|
||||
|
||||
### Inferred Consumers:
|
||||
- UI view models (`ITestSummaryListViewModel`, `IGraphMainViewModel`) that interact with `TestSummary` and `TestChannel`.
|
||||
- XML loading utilities (`TestMetadataXml`) for parsing `.dts` files.
|
||||
- Event aggregation system for error reporting.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`TestModule.TriggerSampleNumbers` is always empty**: The `LoadTriggerSampleNumbers` method ignores its input and returns `new List<ulong>()`. This field is likely unused or deprecated.
|
||||
- **Non-deterministic `ChannelId` for missing IDs**: If `ChannelId` attribute is missing or `-1`, `m.GetHashCode().ToString()` is used, which is not stable across runs or app restarts.
|
||||
- **Calculated channel data loss**: For calculated channels, many fields (e.g., `IsoCode`, `IsoChannelName`, `UserCode`, `UserChannelName`, `HardwareChannelName`, `SerialNumber`) are hardcoded to `"N/A"`. Some fields like `FactoryExcitationVoltage` and `TimeOfFirstSample` are incorrectly assigned values from unrelated attributes (e.g., `UnsubsampledSampleRateHz` → `FactoryExcitationVoltage`).
|
||||
- **`TestRunMetadata.Id` vs `Name` confusion**: `Id` is derived from file name (`Path.GetFileNameWithoutExtension(FilePath)`), while `Name` comes from XML `@Id` attribute. This may be counterintuitive.
|
||||
- **`TestSummary.TimeStamp` fallback behavior**: Uses `TestSetup.TimeStamp`
|
||||
@@ -0,0 +1,42 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/GroupTemplates/Constants.cs
|
||||
generated_at: "2026-04-16T02:39:55.206044+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "2540e3fb9c96a388"
|
||||
---
|
||||
|
||||
# GroupTemplates
|
||||
|
||||
### 1. Purpose
|
||||
This module defines a集中 set of string constants used to identify and reference non-ISO test object types and naming conventions within the `DTS.Common.Classes.GroupTemplates` namespace. It serves as a centralized source of truth for special-case identifiers—likely used during test configuration, template processing, or data mapping—where standard ISO-compliant naming or channel types are not applicable. Its existence prevents hard-coded string duplication and reduces the risk of typos or inconsistencies across the codebase when handling non-standard test objects.
|
||||
|
||||
### 2. Public Interface
|
||||
The module exposes only a single `public static class` with three `public const string` fields:
|
||||
|
||||
- `public const string NON_ISO_TESTOBJECT_CHANNEL_TYPE = "x_NonISOTestObjectType_x";`
|
||||
A constant string used to represent the channel type identifier for non-ISO test objects. Appears to be a placeholder or marker value (note the surrounding `x_` delimiters).
|
||||
|
||||
- `public const string NON_ISO_TESTOBJECT_NAME = "x_NonISOTestObjectName_x";`
|
||||
A constant string used as a placeholder or default name for non-ISO test objects, similarly wrapped in `x_` delimiters.
|
||||
|
||||
- `public const string NON_ISO_TESTOBJECT_CHANNEL_TYPE2 = "NONISO_x_";`
|
||||
A second, distinct constant for non-ISO channel type identification, likely representing an alternative or legacy variant (note the trailing underscore and lack of leading `x_`).
|
||||
|
||||
### 3. Invariants
|
||||
- All three constants are compile-time constants (`const`) and thus immutable at runtime.
|
||||
- The values are fixed strings and must not be modified programmatically.
|
||||
- The naming convention (`x_..._x` vs. `NONISO_x_`) suggests intentional structural differences: the first two are likely *delimited placeholders*, while the third may be a *prefix* for derived identifiers.
|
||||
- No runtime validation or enforcement is present in this module; correctness relies on consistent usage elsewhere.
|
||||
|
||||
### 4. Dependencies
|
||||
- **Internal**: This module resides in `DTS.Common.Classes.GroupTemplates`, implying it is part of a shared/common library (`DTS.CommonCore`). It is likely consumed by other modules in the `DTS.Common` assembly or downstream projects that handle test group templates or configuration.
|
||||
- **External**: No external dependencies are declared (no `using` statements or references beyond the namespace).
|
||||
- **Consumers**: Based on naming, classes such as `GroupTemplate`, `TestObject`, or configuration parsers (e.g., in `DTS.TestFramework` or `DTS.Configuration`) are probable consumers, though not evident from this file alone.
|
||||
|
||||
### 5. Gotchas
|
||||
- The `x_` prefix/suffix in `NON_ISO_TESTOBJECT_CHANNEL_TYPE` and `NON_ISO_TESTOBJECT_NAME` may be misinterpreted as part of the actual value rather than a marker—developers might accidentally include them in output or comparisons.
|
||||
- `NON_ISO_TESTOBJECT_CHANNEL_TYPE2` uses a different pattern (`NONISO_x_`), suggesting possible historical evolution or a distinct use case (e.g., a prefix for auto-generated IDs). Confusing it with `NON_ISO_TESTOBJECT_CHANNEL_TYPE` could lead to mismatches.
|
||||
- No documentation comments (e.g., XML doc comments) are present in the source, so the intended semantics (e.g., whether these are *exact matches*, *prefixes*, or *wildcards*) are ambiguous without external context.
|
||||
- None identified from source alone.
|
||||
@@ -0,0 +1,248 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Groups/GroupGRPImportError.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/GroupGRPImportGroup.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/GroupHardwareDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/TestSetupGroupRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/GroupDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/GroupGRPImportChannel.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/ChannelDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/GroupHelper.cs
|
||||
generated_at: "2026-04-16T02:40:36.766589+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "2f1b395f0369a2ed"
|
||||
---
|
||||
|
||||
# Documentation: Group Import and Database Record Classes
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides data structures and helper utilities for importing, representing, and managing group-based test configurations—specifically for `.GRP` files (TDC group files)—and their corresponding database records. It enables parsing of `.GRP` files into structured in-memory objects (`GroupGRPImportGroup`, `GroupGRPImportChannel`), tracking import errors (`GroupGRPImportError`), and mapping between in-memory group/channel representations and database entities (`GroupDbRecord`, `ChannelDbRecord`, `GroupHardwareDbRecord`, `TestSetupGroupRecord`). The module serves as the foundational data layer for group import workflows, supporting validation, error reporting, and persistence of group configurations in the DTS system.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `GroupGRPImportError`
|
||||
- **`Errors` enum**
|
||||
Defines all possible error types during `.GRP` file import:
|
||||
- `FileEmpty`, `InvalidISOCodeInput`, `InvalidFullScaleInput`, `InvalidSensorInput`, `InvalidInvertInput`, `SensorNotFound`, `InvalidInputMode`, `InvalidDefaultValue`, `InvalidActiveValue`, `InvalidFireMode`, `InvalidDelay`, `InvalidLimitDuration`, `InvalidDuration`, `InvalidCurrent`
|
||||
- **`ErrorCode` (property, `Errors`)**
|
||||
The specific error encountered during import.
|
||||
- **`File` (property, `string`)**
|
||||
Path or name of the file where the error occurred.
|
||||
- **`Line` (property, `int`)**
|
||||
Line number in the file where the error occurred.
|
||||
- **`ExtraInfo` (property, `string`)**
|
||||
Additional human-readable context for the error.
|
||||
- **`ToString()`**
|
||||
Returns `ExtraInfo`.
|
||||
|
||||
### `GroupGRPImportGroup`
|
||||
- **`Included` (property, `bool`, default `true`)**
|
||||
Indicates whether the group should be included in the import operation.
|
||||
- **`Overwrite` (property, `bool`, default `true`)**
|
||||
Indicates whether existing group data should be overwritten during import.
|
||||
- **`GroupName` (property, `string`)**
|
||||
Name of the group (from the `.GRP` file).
|
||||
- **`GroupTags` (property, `string`)**
|
||||
Tags associated with the group.
|
||||
- **`ImportingUserTags` (property, `string`)**
|
||||
User-provided tags during import.
|
||||
- **`SourceFile` (property, `string`)**
|
||||
Path to the source `.GRP` file.
|
||||
- **`Channels` (property, `GroupGRPImportChannel[]`, default empty array)**
|
||||
Array of channels parsed from the `.GRP` file.
|
||||
- **`GroupErrors` (property, `GroupGRPImportError[]`, default `null`)**
|
||||
List of errors encountered during import of the group (e.g., file-level errors).
|
||||
- **`GroupNameHasError` (property, `bool`)**
|
||||
Indicates whether the group name itself has an error; used for UI validation (e.g., red border on textbox).
|
||||
|
||||
### `GroupGRPImportChannel`
|
||||
- **Field index constants** (`public const uint`)
|
||||
`SerialNumberField`, `DisplayNameField`, `ISOCodeField`, `InvertField`, `CapacityField`, `InputModeField`, `DefaultValueField`, `ActiveValueField`, `FireModeField`, `DelayField`, `LimitDurationField`, `DurationField`, `CurrentField`
|
||||
Represent column indices in `.GRP` file rows.
|
||||
- **`SensorSerialNumber` (property, `string`)**
|
||||
Serial number of the sensor associated with this channel.
|
||||
- **`DisplayName` (property, `string`)**
|
||||
Human-readable name for the channel.
|
||||
- **`ISOCode` (property, `string`)**
|
||||
ISO-compliant code for the channel.
|
||||
- **`Invert` (property, `bool`)**
|
||||
Whether the channel signal should be inverted.
|
||||
- **`FullScale` (property, `double`)**
|
||||
Full-scale value for analog channels.
|
||||
- **`InputMode` (property, `InputModes?`, default `null`)**
|
||||
Input mode for digital channels; enum values: `na`, `TLH`, `THL`, `CCNO`, `CCNC`. Default: `InputModes.CCNO`.
|
||||
- **`DefaultValue`, `ActiveValue`, `Delay`, `Duration`, `Current` (properties, `double?`, defaults `0.0`, `1.0`, `0.0`, `10.0`, `1.5` respectively)**
|
||||
Optional numeric parameters for channel configuration.
|
||||
- **`FireMode` (property, `FireModes?`, default `null`)**
|
||||
Fire mode for squib channels; enum values: `na`, `CD`, `CC`. Default: `FireModes.CD`.
|
||||
- **`LimitDuration` (property, `bool?`, default `null`)**
|
||||
Whether duration limiting is enabled. Default: `true`.
|
||||
- **`Error` (property, `GroupGRPImportError`, default `null`)**
|
||||
Channel-specific import error (if any).
|
||||
- **`ParentGroup` (property, `GroupGRPImportGroup`)**
|
||||
Reference to the parent group.
|
||||
- **`GroupName` (property, `string`)**
|
||||
Returns `ParentGroup.GroupName` or `"---"` if `ParentGroup` is `null`.
|
||||
- **`GroupNameInvalidate()`**
|
||||
Raises `PropertyChanged` for `GroupName` to force UI refresh.
|
||||
|
||||
### `GroupHardwareDbRecord`
|
||||
- **`Id` (property, `int`, `[Key]`)**
|
||||
Primary key in `GroupHardware` table.
|
||||
- **`GroupId` (property, `int`)**
|
||||
Foreign key to group.
|
||||
- **`DASId` (property, `int`)**
|
||||
Foreign key to DAS (Data Acquisition System).
|
||||
- **`SerialNumber` (property, `string`)**
|
||||
Serial number of hardware device.
|
||||
- **Constructors**
|
||||
- `GroupHardwareDbRecord()`
|
||||
- `GroupHardwareDbRecord(IGroupHardwareDbRecord copy)`
|
||||
- `GroupHardwareDbRecord(IDataReader reader)` — populates from database reader.
|
||||
|
||||
### `TestSetupGroupRecord`
|
||||
- **`GroupId` (property, `int`)**
|
||||
Database ID of the group.
|
||||
- **`DisplayOrder` (property, `int`)**
|
||||
Order in which the group appears in UI/test setup.
|
||||
- **`Position` (property, `string`)**
|
||||
ISO 13499 position field (may be mixed across channels).
|
||||
- **`TestObjectType` (property, `string`)**
|
||||
ISO 13499 test object field (may be mixed across channels).
|
||||
- **`TestSetupId` (property, `int`)**
|
||||
Database ID of the test setup.
|
||||
- **Constructors**
|
||||
- `TestSetupGroupRecord()`
|
||||
- `TestSetupGroupRecord(ITestSetupGroupRecord copy)`
|
||||
- `TestSetupGroupRecord(IDataReader reader)` — populates from database reader.
|
||||
|
||||
### `GroupDbRecord`
|
||||
- **`Id` (property, `int`, `[Key]`)**
|
||||
Primary key in group table.
|
||||
- **`SerialNumber` (property, `string`)**
|
||||
Serial number of the group (often derived from group name).
|
||||
- **`Picture` (property, `string`)**
|
||||
Path or identifier for group image.
|
||||
- **`DisplayName` (property, `string`)**
|
||||
Human-readable name.
|
||||
- **`Description` (property, `string`)**
|
||||
Optional description.
|
||||
- **`Embedded` (property, `bool`)**
|
||||
Whether the group is embedded (e.g., system-provided).
|
||||
- **`LastModified` (property, `DateTime`)**
|
||||
Timestamp of last modification.
|
||||
- **`LastModifiedBy` (property, `string`)**
|
||||
User who last modified the group.
|
||||
- **`StaticGroupId` (property, `int?`)**
|
||||
Optional ID for static groups.
|
||||
- **`ExtraProperties` (property, `string`)**
|
||||
JSON-serialized dictionary of additional properties.
|
||||
- **Constructors**
|
||||
- `GroupDbRecord()`
|
||||
- `GroupDbRecord(IGroupDbRecord copy)`
|
||||
- `GroupDbRecord(IGroup copy, List<KeyValuePair<string,string>> extraProperties)`
|
||||
- `GroupDbRecord(IDataReader reader)` — populates from database reader.
|
||||
|
||||
### `ChannelDbRecord`
|
||||
- **`Id` (property, `long`, `[Key]`)**
|
||||
Primary key in channel table.
|
||||
- **`GroupId` (property, `int`)**
|
||||
Foreign key to group.
|
||||
- **`IsoCode`, `IsoChannelName` (properties, `string`)**
|
||||
ISO-compliant identifiers.
|
||||
- **`UserCode`, `UserChannelName` (properties, `string`)**
|
||||
User-defined identifiers.
|
||||
- **`DASId`, `DASChannelIndex` (properties, `int`)**
|
||||
DAS device and channel index.
|
||||
- **`GroupChannelOrder`, `TestSetupOrder` (properties, `int`)**
|
||||
Ordering within group and test setup.
|
||||
- **`SensorId` (property, `int`)**
|
||||
Foreign key to sensor.
|
||||
- **`Disabled` (property, `bool`)**
|
||||
Whether channel is disabled.
|
||||
- **`IsDisabled` (property, `bool`)**
|
||||
Backward-compatible alias for `Disabled`.
|
||||
- **`LastModified`, `LastModifiedBy` (properties, `DateTime`, `string`)**
|
||||
Timestamp and user of last modification.
|
||||
- **Constructors**
|
||||
- `ChannelDbRecord()`
|
||||
- `ChannelDbRecord(IChannelDbRecord copy)`
|
||||
- `ChannelDbRecord(IDataReader reader)` — populates from database reader.
|
||||
|
||||
### `GroupHelper` (abstract class)
|
||||
- **Static group metadata caches**
|
||||
All methods are static and operate on internal static dictionaries.
|
||||
- `ClearStaticGroupNames()`, `SetStaticGroupName(int, string)`, `GetStaticGroupName(int)`
|
||||
- `ClearEmbeddedGroupIdList()`, `SetEmbeddedGroupId(int)`, `IsGroupEmbedded(int)`
|
||||
- `ClearTestSetupGroupIds()`, `SetTestSetupGroupId(int, int)`, `GetTestSetupGroupId(int)`
|
||||
- `ClearGroupChannelIds()`, `AddGroupChannelId(int, int)`, `GetGroupIdsFromChannels(int)`
|
||||
- `ClearDASIds()`, `SetDASId(string, int)`, `GetDASId(string)`
|
||||
- `ClearBaseModuleChannelIndexList()`, `SetBaseModuleChannelIndexList(...)`, `GetChannelIndexes(string, string)`
|
||||
- `ClearDASIdChannelIndexGroupIdList()`, `SetDASIdChannelIndexGroupIdList(...)`, `GetGroupIds(int, List<int>)`
|
||||
- `ClearTestSetupHardwareIds()`, `AddTestSetupHardwareId(int, int)`, `GetTestSetupHardwareIds(int)`
|
||||
- `ClearGroupHardwareIds()`, `AddGroupHardwareId(int, int)`, `GetGroupHardwareIds(int)`
|
||||
*Note: These are caching utilities for runtime lookups, not persistent storage.*
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`GroupGRPImportChannel.InputMode`**
|
||||
Must be `null` or one of `na`, `TLH`, `THL`, `CCNO`, `CCNC`. Default is `CCNO`.
|
||||
- **`GroupGRPImportChannel.FireMode`**
|
||||
Must be `null` or one of `na`, `CD`, `CC`. Default is `CD`.
|
||||
- **`GroupGRPImportChannel.LimitDuration`**
|
||||
Must be `null` or `true`/`false`. Default is `true`.
|
||||
- **`GroupGRPImportChannel.DefaultValue`, `ActiveValue`, `Delay`, `Duration`, `Current`**
|
||||
Must be `null` or a non-negative `double`. Defaults are defined as `0.0`, `1.0`, `0.0`, `10.0`, `1.5` respectively.
|
||||
- **`GroupGRPImportChannel.Error`**
|
||||
If non-`null`, indicates a channel-level import error; if `null`, the channel is valid.
|
||||
- **`GroupGRPImportGroup.GroupErrors`**
|
||||
If non-`null`, contains group-level errors (e.g., file corruption, invalid header). If `null`, no group-level errors were recorded.
|
||||
- **`GroupDbRecord.ExtraProperties`**
|
||||
Must be valid JSON (serialized `List<KeyValuePair<string,string>>`).
|
||||
- **`ChannelDbRecord.IsDisabled`**
|
||||
Always mirrors `Disabled`; setting either updates both.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.Base`**
|
||||
Provides `BasePropertyChanged` (base class for `GroupGRPImportGroup`, `GroupGRPImportChannel`, `GroupHardwareDbRecord`, `TestSetupGroupRecord`, `GroupDbRecord`, `ChannelDbRecord`).
|
||||
- **`DTS.Common.Interface.Groups`**
|
||||
Defines interfaces: `IGroupHardwareDbRecord`, `ITestSetupGroupRecord`, `IGroupDbRecord`.
|
||||
- **`DTS.Common.Interface.Channels`**
|
||||
Defines interface: `IChannelDbRecord`.
|
||||
- **`System.Data`**
|
||||
Used for `IDataReader` in constructors.
|
||||
- **`Newtonsoft.Json`**
|
||||
Used in `GroupDbRecord` constructor to serialize `ExtraProperties`.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **Import/Export logic** (not shown)
|
||||
Likely uses `GroupGRPImportGroup`, `GroupGRPImportChannel`, and `GroupGRPImportError` to parse `.GRP` files.
|
||||
- **Database persistence layer**
|
||||
Uses `GroupDbRecord`, `ChannelDbRecord`, `GroupHardwareDbRecord`, `TestSetupGroupRecord` for CRUD operations.
|
||||
- **UI layer**
|
||||
Binds to `GroupGRPImportGroup.GroupNameHasError`, `GroupGRPImportChannel.GroupName`, and `GroupGRPImportChannel.GroupNameInvalidate()` for validation and refresh.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`GroupGRPImportChannel.GroupName` is a computed property**
|
||||
Returns `ParentGroup.GroupName` or `"---"`. UI bindings must call `GroupNameInvalidate()` after `ParentGroup` changes to refresh.
|
||||
- **`ChannelDbRecord.IsDisabled` is a legacy alias**
|
||||
Directly reads/writes `Disabled`; new code should use `Disabled` for clarity.
|
||||
- **`GroupDbRecord.SerialNumber` is derived from `IGroup.Name`**
|
||||
In the constructor `GroupDbRecord(IGroup, ...)`, `SerialNumber` is set to `copy.Name`, not a separate serial field.
|
||||
- **`GroupHelper` caches are static and global**
|
||||
State persists across operations; callers must explicitly clear caches (e.g., `ClearStaticGroupNames()`) to avoid stale data.
|
||||
- **`GroupHardwareDbRecord.Id` uses `int` (not `long`)**
|
||||
Contrasts with `ChannelDbRecord.Id`, which uses `long`.
|
||||
- **`GroupGRPImportChannel.InputMode`, `FireMode`, etc., are nullable**
|
||||
`null` indicates "not set" or "N/A", not a default value. Validation must handle `null` explicitly.
|
||||
- **`GroupGRPImportGroup.Channels` defaults to empty array (not `null`)**
|
||||
Safe to enumerate without null checks.
|
||||
- **`GroupGRPImportGroup.GroupErrors` defaults to `null`**
|
||||
Not an empty array—must check for `null` before enumeration.
|
||||
- **`GroupHelper.GetChannelIndexes` and `GetGroupIds` use substring matching**
|
||||
`GetChannelIndexes` matches `baseSerialNumberSubstring` exactly (not a substring search), despite the parameter name suggesting partial matching. Similarly, `GetGroupIds` requires exact `dasId` and `channelIndex` matches.
|
||||
@@ -0,0 +1,122 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Groups/ChannelSettings/ChannelSettingRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/ChannelSettings/GroupChannelSettingRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Groups/ChannelSettings/ChannelSettingBase.cs
|
||||
generated_at: "2026-04-16T02:42:22.673078+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "f67a48400fa70da5"
|
||||
---
|
||||
|
||||
# ChannelSettings
|
||||
|
||||
## Documentation: Channel Settings Module
|
||||
|
||||
### 1. Purpose
|
||||
This module defines core data structures for modeling channel configuration settings in the DTS system. It provides three key classes: `ChannelSettingRecord` (a metadata record describing a *type* of setting), `GroupChannelSettingRecord` (an *instance* of a setting applied to a specific channel), and `ChannelSettingBase` (a concrete implementation of `IChannelSetting` that supports typed value accessors and constant-based setting name definitions). Together, they enable storage, retrieval, and manipulation of channel-specific configuration values, with support for multiple channel types (analog, digital, squib, UART, etc.) and versioned database interactions.
|
||||
|
||||
---
|
||||
|
||||
### 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`**
|
||||
Gets/sets the unique identifier for this setting definition.
|
||||
- **`string SettingName`**
|
||||
Gets/sets the canonical name of the setting (e.g., `"Range"`, `"SquibCurrent"`).
|
||||
- **`string DefaultValue`**
|
||||
Gets/sets the default value string for this setting.
|
||||
|
||||
#### `GroupChannelSettingRecord`
|
||||
- **`GroupChannelSettingRecord()`**
|
||||
Default constructor; initializes an empty record.
|
||||
- **`GroupChannelSettingRecord(IDataReader reader, int storedProcedureVersionUsed)`**
|
||||
Populates the record from an `IDataReader`. Behavior depends on `storedProcedureVersionUsed`:
|
||||
- If `>= Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`, reads `"ChannelId"` via `Utility.GetLong`; otherwise sets `ChannelId = 0`.
|
||||
- Always reads `"SettingId"` (via `Utility.GetInt`) and `"SettingValue"` (via `Utility.GetString`).
|
||||
- **`GroupChannelSettingRecord(long channelId, int settingId, string settingValue)`**
|
||||
Constructor for programmatic creation; directly assigns `ChannelId`, `SettingId`, and `SettingValue`.
|
||||
- **`long ChannelId`**
|
||||
Gets/sets the channel identifier the setting applies to.
|
||||
- **`int SettingId`**
|
||||
Gets/sets the foreign key referencing `ChannelSettingRecord.Id`.
|
||||
- **`string SettingValue`**
|
||||
Gets/sets the actual value string for this channel’s setting instance.
|
||||
|
||||
#### `ChannelSettingBase`
|
||||
- **`ChannelSettingBase(int settingType, string name, string defaultValue)`**
|
||||
Constructor initializing `SettingTypeId`, `SettingName`, and `DefaultValue`.
|
||||
- **`IChannelSetting Clone()`**
|
||||
Returns a new `ChannelSettingBase` instance with all properties copied from the current instance.
|
||||
- **`long ChannelId { get; set; }`**
|
||||
Channel ID the setting applies to.
|
||||
- **`int SettingTypeId { get; protected set; }`**
|
||||
Type identifier for the setting (e.g., analog, digital).
|
||||
- **`string SettingName { get; protected set; }`**
|
||||
Name of the setting (e.g., `"Range"`).
|
||||
- **`string DefaultValue { get; protected set; }`**
|
||||
Default value string for this setting.
|
||||
- **`string Value { get; set; }`**
|
||||
Current value string for this setting instance.
|
||||
- **`double DoubleValue { get; set; }`**
|
||||
Gets/sets `Value` as a `double`. Falls back to `DoubleDefaultValue` on parse failure.
|
||||
- **`double DoubleDefaultValue { get; }`**
|
||||
Parses `DefaultValue` as a `double` using `CultureInfo.InvariantCulture`.
|
||||
- **`int IntValue { get; set; }`**
|
||||
Gets/sets `Value` as an `int`. Falls back to `IntDefaultValue` on parse failure.
|
||||
- **`int IntDefaultValue { get; }`**
|
||||
Parses `DefaultValue` as an `int` using `CultureInfo.InvariantCulture`.
|
||||
- **`bool BoolValue { get; set; }`**
|
||||
Gets/sets `Value` as a `bool`. Falls back to `BoolDefaultValue` on parse failure.
|
||||
- **`bool BoolDefaultValue { get; }`**
|
||||
Parses `DefaultValue` as a `bool` (uses default `bool.Parse` behavior).
|
||||
|
||||
#### Constants (public static fields in `ChannelSettingBase`)
|
||||
- **Analog**: `RANGE`, `CFC`, `FilterClass`, `POLARITY`, `POSITION`, `ZEROMETHOD`, `ZEROMETHODSTART`, `ZEROMETHODEND`, `USERVALUE1`, `USERVALUE2`, `USERVALUE3`, `INITIAL_OFFSET`, `ACCouplingEnabled`
|
||||
- **Deprecated**: `LIMIT_DURATION`, `DURATION`, `DELAY` (commented out)
|
||||
- **Bridge/Insertion**: `BRIDGE_TYPE`
|
||||
- **Squib**: `SQUIB_CURRENT`, `SQUIB_LIMIT_DURATION`, `SQUIB_DURATION`, `SQUIB_DELAY`, `SQMODE`
|
||||
- **Digital Out**: `DIGITALOUT_LIMIT_DURATION`, `DIGITALOUT_DURATION`, `DIGITALOUT_DELAY`, `OUTPUT_MODE`
|
||||
- **Digital In**: `DIMODE`, `DEFAULT_VALUE`, `ACTIVE_VALUE`
|
||||
- **UART**: `BAUD_RATE`, `DATA_BITS`, `STOP_BITS`, `PARITY`, `FLOW_CONTROL`, `DATA_FORMAT`
|
||||
- **Stream Out**: `UDP_PROFILE`, `UDP_ADDRESS`, `UDP_TIME_CHID`, `UDP_DATA_CHID`, `UDP_TMNS_CONFIG`, `IRIG_TDP_INTERVAL_MS`, `TMATS_INTERVAL_MS`
|
||||
- **Stream In**: `UDP_ADDRESS_IN`
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
- **`ChannelSettingRecord.Id`** must be non-negative (implied by `int` type and database usage).
|
||||
- **`GroupChannelSettingRecord.SettingId`** must correspond to a valid `ChannelSettingRecord.Id` in the database (enforced by foreign key at persistence layer, not here).
|
||||
- **`GroupChannelSettingRecord.ChannelId`** may be `0` *only* when constructed from `IDataReader` with `storedProcedureVersionUsed < Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`. Otherwise, it must be positive.
|
||||
- **`ChannelSettingBase.Value`** is stored as a string; numeric/boolean accessors (`DoubleValue`, `IntValue`, `BoolValue`) parse it at runtime and fall back to defaults on failure.
|
||||
- **`ChannelSettingBase.DefaultValue`** must be parseable as the corresponding type (`double`, `int`, `bool`) for `DoubleDefaultValue`, `IntDefaultValue`, and `BoolDefaultValue` to succeed; otherwise, runtime exceptions may occur during parsing.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
- **Internal Dependencies**:
|
||||
- `DTS.Common.Interface.Channels` (interfaces `IChannelSettingRecord`, `IGroupChannelSettingRecord`, `IChannelSetting`)
|
||||
- `DTS.Common.Base.BasePropertyChanged` (base class for `ChannelSettingRecord`)
|
||||
- `DTS.Common.Base.BasePropertyChanged` (base class for `GroupChannelSettingRecord`)
|
||||
- `DTS.Common.Interface.Channels` (interface `IChannelSetting`)
|
||||
- `System.Data` (`IDataReader`)
|
||||
- `Utility` class (static methods: `GetInt`, `GetString`, `GetLong`)
|
||||
- `Constants` class (reference to `BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`)
|
||||
- **External Dependencies**:
|
||||
- `System` (core types, `CultureInfo`, `NumberStyles`)
|
||||
- `DTS.Common.Interface.Channels` (consumed by other modules for channel configuration management)
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
- **`GroupChannelSettingRecord` constructor with `IDataReader` silently sets `ChannelId = 0`** when `storedProcedureVersionUsed < Constants.BULK_GROUPCHANNELSETTINGS_GET_DB_VERSION`. This may mask missing data if the stored procedure version is misconfigured.
|
||||
- **`ChannelSettingBase` parsing methods (`DoubleValue`, `IntValue`, `BoolValue`) do not distinguish between parse failure and a valid default value**—e.g., if `Value = "0"` and `DefaultValue = "1"`, `IntValue` returns `0`, not `1`. The fallback only occurs on *parse failure* (e.g., `Value = "abc"`).
|
||||
- **`BoolDefaultValue` uses `bool.Parse(DefaultValue)` without `CultureInfo.InvariantCulture`**, unlike numeric defaults. This may cause culture-dependent failures if `DefaultValue` is not `"True"`/`"False"` (case-sensitive).
|
||||
- **`ChannelSettingBase` is mutable** (`Value`, `ChannelId`, etc., have public setters). Cloning via `Clone()` is shallow but may be insufficient if consumers modify nested objects (none present here, but worth noting).
|
||||
- **`ChannelSettingBase` has no validation on `SettingName` or `DefaultValue`**—invalid names or unparseable defaults may only surface at runtime during type conversion.
|
||||
- **`ChannelSettingBase` constants are string literals**; typos in usage (e.g., `"Rang"` instead of `"Range"`) will compile but cause runtime mismatches with database or UI expectations.
|
||||
@@ -0,0 +1,172 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Hardware/ExternalTilt.cs
|
||||
- Common/DTS.CommonCore/Classes/Hardware/DragAndDropPayload.cs
|
||||
- Common/DTS.CommonCore/Classes/Hardware/SerializableAAF.cs
|
||||
- Common/DTS.CommonCore/Classes/Hardware/DASDBRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Hardware/DASChannelDBRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Hardware/DASMonitorInfo.cs
|
||||
generated_at: "2026-04-16T02:39:04.354265+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "ae82d579176b397b"
|
||||
---
|
||||
|
||||
# Hardware Data Models Documentation
|
||||
|
||||
## 1. Purpose
|
||||
This module defines core data models for representing hardware devices, channels, and associated metadata within the DTS (Data Acquisition System) ecosystem. It provides structured classes for serializing/deserializing hardware configuration data to/from databases (via `DASDBRecord`, `DASChannelDBRecord`), file-based monitoring state (`DASMonitorInfo`), and lightweight data transfer objects (`ExternalTilt`, `DragAndDropPayload`). These models serve as the canonical in-memory representation of hardware state for configuration, persistence, and UI binding, enabling consistent handling of DAS (Data Acquisition System) units, modules, channels, and tilt sensors across the system.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `ExternalTilt`
|
||||
- **`ExternalTilt()`**
|
||||
Parameterless constructor.
|
||||
- **`SerialNumber`** (`string`, public get/set)
|
||||
Serial number of the external tilt sensor.
|
||||
- **`TiltID`** (`byte`, public get/set)
|
||||
Identifier for the tilt sensor.
|
||||
- **`SystemID`** (`string`, public get/set)
|
||||
Identifier of the system the tilt sensor belongs to.
|
||||
- **`SystemLocation`** (`string`, public get/set)
|
||||
Physical or logical location of the tilt sensor within the system.
|
||||
|
||||
### `DragAndDropPayload`
|
||||
- **`FORMAT`** (`const string`)
|
||||
`"RESOLVECHANNELS_HARDWARETABLE"` — Primary clipboard/data transfer format identifier.
|
||||
- **`ALT_FORMAT`** (`const string`)
|
||||
`"ALT_RESOLVECHANNELS_HARDWARETABLE"` — Alternate format identifier.
|
||||
- **`CTRL_FORMAT`** (`const string`)
|
||||
`"CTRL_RESOLVECHANNELS_HARDWARETABLE"` — Control-modifier variant format identifier.
|
||||
|
||||
### `SerializableAAF`
|
||||
- **`DAS_TYPE`** (`enum`)
|
||||
- `TDAS = 0`
|
||||
- `SLICE = 1`
|
||||
- **`GetSerializedKey()`** (`string`)
|
||||
Returns a string key in the format `"{DAS_TYPE}_{SampleRate}"` (e.g., `"0_10000"`).
|
||||
- **`GetSerializedValue()`** (`string`)
|
||||
Returns the AAF value as a culture-invariant string.
|
||||
- **`FromSerializedStrings(string key, string value)`**
|
||||
Parses `key` and `value` to populate internal fields. Throws `NotSupportedException` if the key format is invalid (must contain exactly two tokens separated by `"_x_"`).
|
||||
*Note: All properties (`DasType`, `SampleRate`, `AAF`) are currently commented out in the source and not active.*
|
||||
|
||||
### `DASDBRecord`
|
||||
- **`INVALID_DATE`** (`static DateTime`)
|
||||
`new DateTime(1970, 1, 1)` — Sentinel value for unset date fields.
|
||||
- **Constructors**
|
||||
- `DASDBRecord()` — Default constructor.
|
||||
- `DASDBRecord(IDASDBRecord copy)` — Deep copy constructor.
|
||||
- `DASDBRecord(IDataReader reader)` — Populates fields from database reader. Handles `DBNull` and special date parsing (e.g., `FIRST_USE_DATE_NOT_SET`).
|
||||
- **Key Properties**
|
||||
- `DASId` (`int`, `[Key]`, `[Column("DASId")]`) — Primary key.
|
||||
- `SerialNumber` (`string`, `[Required]`, `[StringLength(50)]`) — Unique hardware identifier.
|
||||
- `DASType` (`int`) — Numeric type code (e.g., `0` = TDAS, `1` = SLICE).
|
||||
- `MaxSampleRate`, `MinSampleRate` (`double`, `[Column(TypeName = "decimal(18, 0)")]`) — Hardware sample rate limits.
|
||||
- `CalDate` (`DateTime`, defaults to `INVALID_DATE`) — Calibration date.
|
||||
- `ChannelTypes` (`int[]`, `[StringLength(255)]`) — Array of channel type codes. Parsed from comma-separated string.
|
||||
- `FirstUseDate` (`DateTime?`) — Nullable first-use date. `IsFirstUseValid` indicates if it is set and valid.
|
||||
- `MaxAAFRate` (`double`, `[Column("MaxAAFRate", TypeName = "decimal(18, 0)")]`) — Maximum analog anti-aliasing filter rate.
|
||||
- `IsFirstUseValid` (`bool`) — Indicates whether `FirstUseDate` is supported and set.
|
||||
- `StandIn`, `IsModule`, `IsProgrammable`, `IsReconfigurable` (`bool`) — Hardware capability flags.
|
||||
- `Position`, `Connection`, `FirmwareVersion`, `LastModifiedBy`, `LastUsedBy` (`string`) — Metadata strings.
|
||||
- `PositionOnChain`, `PositionOnDistributor`, `Port`, `ProtocolVersion`, `Version`, `Channels`, `MaxModules`, `MaxMemory` (`int`/`long`) — Configuration parameters.
|
||||
- `ParentDAS` (`string`, `[Column("ParentDAS")]`) — Serial number of parent DAS (for modules).
|
||||
- `TestId`, `GroupId` (`int?`) — Nullable foreign keys.
|
||||
|
||||
### `DASChannelDBRecord`
|
||||
- **`HardwareId`** (`string`) — Identifier for the parent hardware (`serialnumber_dastype`).
|
||||
- **`DaschannelId`** (`int`, `[Key]`, `[Column("DASChannelId")]`) — Primary key.
|
||||
- **`Dasid`** (`int?`) — Foreign key to `DASDBRecord.DASId`.
|
||||
- **`ChannelIdx`** (`int`, with `SetProperty` change notification) — Physical channel index on the DAS.
|
||||
- **`SupportedBridges`** (`int`, default `DEFAULT_SUPPORTED_BRIDGES = 12`)
|
||||
Bitmask:
|
||||
- Bit 1 (value 2): Quarter bridge
|
||||
- Bit 2 (value 4): Half bridge
|
||||
- Bit 3 (value 8): Full bridge
|
||||
*(IEPE, digital input, squib fire, etc., are defined in other bitmasks below)*
|
||||
- **`SupportedExcitations`** (`int`, default `DEFAULT_SUPPORTED_EXCITATIONS = 16`)
|
||||
Bitmask:
|
||||
- Bit 4 (value 16): 5V (default)
|
||||
- Bits 0–6: Invalid, 2V, 2.5V, 3V, 5V, 10V, 1V
|
||||
- **`DASDisplayOrder`** (`int`) — Display order (may differ from physical order).
|
||||
- **`SupportedDigitalInputModes`** (`int`, default `16`)
|
||||
Bitmask for digital input modes (e.g., CCNC, TLH, THL).
|
||||
- **`SupportedSquibFireModes`** (`int`, default `16`)
|
||||
Bitmask for squib fire modes (capacitor discharge, constant current, AC discharge).
|
||||
- **`SupportedDigitalOutputModes`** (`int`, default `16`)
|
||||
Bitmask for digital output modes (FVLH, FVHL, CCNO, CCNC).
|
||||
- **`ModuleSerialNumber`** (`string`) — Serial number of the module this channel belongs to.
|
||||
- **`ModuleArrayIndex`** (`int`) — Array index of the module among modules on the DAS/rack.
|
||||
- **Constructors**
|
||||
- `DASChannelDBRecord()` — Default.
|
||||
- `DASChannelDBRecord(IDataReader reader)` — Populates from database.
|
||||
- `DASChannelDBRecord(IDASChannelDBRecord copy)` — Copy constructor.
|
||||
|
||||
### `DASMonitorInfo`
|
||||
- **`ReadFromFile(string path)`**
|
||||
Reads monitor info from a text file (one field per line, in `Fields` enum order). Silently returns on file not found or parse errors (logs via `APILogger`).
|
||||
- **`WriteToFile(string path)`**
|
||||
Writes monitor info to a text file. Logs exceptions via `APILogger`.
|
||||
- **`GetChannelName(int index)`** (`string`)
|
||||
Returns channel name (format: `"Ch#XX"` if not set). Uses `_channelNames` array.
|
||||
- **`GetOffsetTolerancemVHigh(int index)` / `GetOffsetTolerancemVLow(int index)`** (`double`)
|
||||
Returns tolerance values (0 if index out of bounds).
|
||||
- **Constructors**
|
||||
- `DASMonitorInfo(string path)` — Loads from file.
|
||||
- `DASMonitorInfo(IDASCommunication das, IsoViewMode mode)` — Populates from live DAS communication object.
|
||||
- **Properties**
|
||||
- `SerialNumber` (`string`)
|
||||
- `TiltSensorCals` (`double[18]`) — Calibration coefficients.
|
||||
- `TiltSensorDataPre` (`short[3]`) — Pre-processed tilt sensor data.
|
||||
- `TiltAxes` (`DFConstantsAndEnums.TiltAxes`) — Axis configuration (default `IXIYIZ`).
|
||||
- `AxisIgnored` (`int`) — Bitmask of ignored axes.
|
||||
- `MountOffsetAxisOne`, `MountOffsetAxisTwo` (`double`) — Mounting offsets (default `NaN`).
|
||||
- `_channelNames` (`string[]`) — Channel names (private).
|
||||
- `_offsetTolerancesHigh`, `_offsetTolerancesLow` (`double[6]`) — Tolerance arrays (private).
|
||||
- **`Fields`** (`enum`) — Defines ordered file fields:
|
||||
`SerialNumber`, `TiltSensorCals`, `TiltSensorDataPre`, `TiltAxes`, `AxesIgnored`, `MountOffsetAxisOne`, `MountOffsetAxisTwo`, `ChannelNames`, `OffsetTolerancesLow`, `OffsetTolerancesHigh`.
|
||||
|
||||
## 3. Invariants
|
||||
- **`DASDBRecord`**
|
||||
- `SerialNumber` is required and non-empty (enforced by `[Required]`).
|
||||
- `Position` is required and non-empty (enforced by `[Required]`).
|
||||
- `CalDate` defaults to `INVALID_DATE` (1970-01-01) if unset.
|
||||
- `FirstUseDate` is nullable; `IsFirstUseValid` must be `true` for it to be considered valid.
|
||||
- `ChannelTypes` is parsed from a comma-separated string; invalid tokens are silently skipped.
|
||||
- `IsProgrammable` is mapped from database column `"Reprogramable"` (note the typo).
|
||||
- **`DASChannelDBRecord`**
|
||||
- `SupportedBridges`, `SupportedExcitations`, etc., use default bitmasks (e.g., `12` for bridges, `16` for excitations).
|
||||
- `ChannelIdx` uses `SetProperty` for change notifications (implements `INotifyPropertyChanged`).
|
||||
- **`DASMonitorInfo`**
|
||||
- File format is strictly ordered by `Fields` enum values (10 lines).
|
||||
- Parsing uses `CultureInfo.InvariantCulture` for numeric values.
|
||||
- `TiltSensorCals` is fixed-length (`double[18]`); arrays from file are truncated/padded to this length.
|
||||
- `NoModules(das)` check returns empty arrays/`NaN` if `das.ConfigData` or `das.ConfigData.Modules` is null/empty.
|
||||
|
||||
## 4. Dependencies
|
||||
- **Imports/Usings**
|
||||
- `DTS.Common.Base` (`BasePropertyChanged`)
|
||||
- `DTS.Common.Enums`, `DTS.Common.Enums.DASFactory` (e.g., `TiltAxes`, `IsoViewMode`)
|
||||
- `DTS.Common.Interface.DataRecorders` (`IDASDBRecord`, `IDASChannelDBRecord`)
|
||||
- `DTS.Common.Interface.Hardware` (`IDASCommunication`, `ITiltSensorCalAware`)
|
||||
- `System.Data` (`IDataReader`)
|
||||
- `System.ComponentModel.DataAnnotations` (EF Core attributes)
|
||||
- `DTS.Common.Utilities.Logging` (`APILogger`)
|
||||
- **External Dependencies**
|
||||
- `Utility` class (static helper for `GetDateTime`, `GetString`, `GetInt`, etc.).
|
||||
- `DFConstantsAndEnums.FIRST_USE_DATE_NOT_SET` (for date validation).
|
||||
- `Strings.Strings.Ch` (for default channel names).
|
||||
- **Depended Upon**
|
||||
- `DASDBRecord` and `DASChannelDBRecord` implement `IDASDBRecord`/`IDASChannelDBRecord` interfaces, likely consumed by data access layers.
|
||||
- `DASMonitorInfo` depends on `IDASCommunication` and `IsoViewMode` (from `DTS.Common.Enums`).
|
||||
|
||||
## 5. Gotchas
|
||||
- **`SerializableAAF`** is **non-functional** in the current source: All properties and the constructor are commented out. The class is effectively a stub.
|
||||
- **`DASDBRecord.IsProgrammable`** maps to database column `"Reprogramable"` (misspelled).
|
||||
- **`DASChannelDBRecord.SupportedBridges`** defaults to `12` (half + full bridge), but the summary comments incorrectly state "half (4) + full (8)" — this sums to `12`, but bit positions are 2 and 3 (values 4 and 8), not 4 and 8.
|
||||
- **`DASMonitorInfo`** uses `float.NaN` in `GetMountOffsetAxisOne/Two` but assigns to `double` properties (implicit conversion).
|
||||
- **`DASMonitorInfo.ToShortArray`** has a bug: It parses `line` instead of `token` in `short.TryParse`.
|
||||
- **`DASMonitorInfo`** file format assumes exactly 10 fields in `Fields` order; extra/missing lines are ignored or cause misalignment.
|
||||
- **`DASDBRecord.ChannelTypes`** is stored as a comma-separated string in the DB but mapped to `int[]` in code; parsing silently drops invalid tokens.
|
||||
- **`DASMonitorInfo`** uses `double[]` arrays of fixed size (e.g., `TiltSensorCals[18]`), but file parsing may produce arrays of arbitrary length (truncated to size in code? Not explicitly handled).
|
||||
@@ -0,0 +1,91 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/ISO/IsoCode.cs
|
||||
generated_at: "2026-04-16T02:39:28.985647+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e833a8924b8a2f43"
|
||||
---
|
||||
|
||||
# ISO
|
||||
|
||||
## Documentation: `IsoCode` Class
|
||||
|
||||
### 1. Purpose
|
||||
The `IsoCode` class encapsulates a fixed-length 16-character ISO-standard location code, representing hierarchical spatial and physical metadata (e.g., for document or object tracking). It provides structured access to semantically meaningful substrings—such as test object, position, main/fine locations, physical dimension, direction, and filter class—while enforcing a strict 16-character internal representation. The class ensures consistent formatting (e.g., padding with `'?'` or truncating) and serves as a domain-specific abstraction over raw string manipulation for ISO-compliant codes.
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
- **`public IsoCode(string isoCode)`**
|
||||
Constructor. Initializes the 16-character internal buffer `_isoCodeFull`. If `isoCode` is `null`, treats it as `""`. Truncates to 16 characters if longer; pads with `'?'` if shorter. Assigns each character directly to `_isoCodeFull[i]`.
|
||||
|
||||
- **`public string StringRepresentation { get; set; }`**
|
||||
Gets/sets the full 16-character ISO code as a string.
|
||||
- **Getter**: Returns `_isoCodeFull` concatenated into a string.
|
||||
- **Setter**: Assigns characters from `value` to `_isoCodeFull`. If `value` is shorter than 16 chars, pads remaining positions with `'0'`. Does *not* use `'?'` padding in setter.
|
||||
|
||||
- **`public string TestObject { get; set; }`**
|
||||
Gets/sets the first character (`_isoCodeFull[0]`).
|
||||
- **Setter**: If `value` is `null` or empty, sets to `'?'`; otherwise uses `value[0]`.
|
||||
|
||||
- **`public string Position { get; set; }`**
|
||||
Gets/sets the second character (`_isoCodeFull[1]`).
|
||||
- **Setter**: Same behavior as `TestObject`.
|
||||
|
||||
- **`public string MainLocation { get; set; }`**
|
||||
Gets/sets characters at indices 2–5 (4 chars).
|
||||
- **Setter**: Truncates to 4 chars if longer; pads right with `'?'` if shorter.
|
||||
|
||||
- **`public string FineLocation1 { get; set; }`**
|
||||
Gets/sets characters at indices 6–7 (2 chars).
|
||||
- **Setter**: Pads right with `'?'` if shorter than 2; truncates if longer (implicitly via `ToCharArray(0, 2)`).
|
||||
|
||||
- **`public string FineLocation2 { get; set; }`**
|
||||
Gets/sets characters at indices 8–9 (2 chars).
|
||||
- **Setter**: Same padding/truncation behavior as `FineLocation1`.
|
||||
|
||||
- **`public string FineLocation3 { get; set; }`**
|
||||
Gets/sets characters at indices 10–11 (2 chars).
|
||||
- **Setter**: Same padding/truncation behavior as `FineLocation1`.
|
||||
|
||||
- **`public string PhysicalDimension { get; set; }`**
|
||||
Gets/sets characters at indices 12–13 (2 chars).
|
||||
- **Setter**: Truncates to 2 chars if longer; pads right with `'?'` if shorter.
|
||||
|
||||
- **`public string Direction { get; set; }`**
|
||||
Gets/sets character at index 14 (1 char).
|
||||
- **Setter**: If `value` is `null` or empty, sets to `'?'`; otherwise uses `value[0]`.
|
||||
|
||||
- **`public string FilterClass { get; set; }`**
|
||||
Gets/sets character at index 15 (1 char).
|
||||
- **Setter**: Same behavior as `Direction`.
|
||||
|
||||
### 3. Invariants
|
||||
- `_isoCodeFull` is *always* exactly 16 characters long.
|
||||
- For all public properties (`TestObject`, `Position`, `FineLocation*`, `PhysicalDimension`, `Direction`, `FilterClass`), the setter ensures the underlying character(s) are set to `'?'` when input is `null`/empty (except `StringRepresentation`, which uses `'0'` in setter).
|
||||
- `MainLocation` and `PhysicalDimension` truncate to 4 and 2 chars respectively if input exceeds length; all fine location fields truncate to 2 chars.
|
||||
- The constructor *always* produces a 16-character buffer (via truncation or `'?'` padding).
|
||||
- `StringRepresentation` setter does *not* use `'?'` padding—uses `'0'` for missing characters.
|
||||
|
||||
### 4. Dependencies
|
||||
- **Internal**: Uses `System.Text.StringBuilder` (for `StringRepresentation` getter).
|
||||
- **External**: No external dependencies beyond `System` (no third-party or framework-specific APIs beyond core types).
|
||||
- **Consumers**: Presumably used by other modules in `DTS.Common` namespace (e.g., parsing/serialization logic, UI binding, or ISO code validation services), though not explicit in this file.
|
||||
|
||||
### 5. Gotchas
|
||||
- **Inconsistent padding in setters**:
|
||||
- Public property setters (`TestObject`, `Position`, etc.) use `'?'` for missing/empty input.
|
||||
- `StringRepresentation` setter uses `'0'` for missing characters. This discrepancy may cause unexpected behavior if `StringRepresentation` is set directly after using property setters (or vice versa).
|
||||
- **Off-by-one error in `_fineLocation*` setters**:
|
||||
In `_fineLocation1`, `_fineLocation2`, and `_fineLocation3` private setters, the condition `value.Length < i` should be `value.Length <= i` to correctly handle `i == value.Length - 1`. As written, `value[i]` will throw `ArgumentOutOfRangeException` when `value.Length == i`.
|
||||
Example: For `value = "A"` (length 1), when `i = 1`, `value.Length (1) < i (1)` is false, so it attempts `value[1]` → invalid.
|
||||
- **Redundant `string.IsNullOrEmpty` checks**:
|
||||
Properties like `TestObject` and `Position` check `string.IsNullOrEmpty(value)` before accessing `value[0]`, but `value[0]` would throw `IndexOutOfRangeException` for empty strings anyway—so the check is defensive but not strictly necessary.
|
||||
- **No validation of character content**:
|
||||
The class accepts any character (including non-alphanumeric) without validation. ISO compliance (e.g., allowed character set) is not enforced.
|
||||
- **`_mainLocation` setter has inconsistent padding**:
|
||||
Uses `'0'` if `value.Length <= i`, but public `MainLocation` setter pads with `'?'`. This mismatch is hidden by the public setter, but could cause confusion if private setter is used directly (unlikely, but possible in reflection scenarios).
|
||||
- **No immutability guarantees**:
|
||||
Though `_isoCodeFull` is `readonly`, its *contents* are mutable via public setters. The class is not thread-safe.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/ISO/ExtraProperties/TextPastedArgs.cs
|
||||
generated_at: "2026-04-16T02:41:57.941514+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "0e778602f67f4f38"
|
||||
---
|
||||
|
||||
# ExtraProperties
|
||||
|
||||
### 1. Purpose
|
||||
`TextPastedArgs` is a concrete implementation of the `ITextPastedEventArgs` interface, used to encapsulate event data for text-paste operations within the ISO Extra Properties subsystem. It carries contextual information—including the pasted text, the originating `IExtraProperty` instance (as `Sender`), a unique identifier (`Id`), and an arbitrary user-defined object (`Tag`)—to event handlers subscribed to text-paste events. This class enables decoupled communication between components that trigger text paste actions and those that consume or react to them.
|
||||
|
||||
### 2. Public Interface
|
||||
- **`TextPastedArgs(string text, IExtraProperty extraProperty, string id, object tag)`**
|
||||
Constructor initializing all properties. Assigns `text` to `Text`, `extraProperty` to `Sender`, `id` to `Id`, and `tag` to `Tag`. All assignments are direct and unvalidated (no null checks or transformations are performed in the constructor).
|
||||
|
||||
- **`string Text { get; }`**
|
||||
Read-only property containing the text that was pasted. Value is set at construction and immutable thereafter.
|
||||
|
||||
- **`object Sender { get; }`**
|
||||
Read-only property referencing the `IExtraProperty` instance that triggered the paste event. Stored as `object` (not strongly typed) per interface contract.
|
||||
|
||||
- **`string Id { get; }`**
|
||||
Read-only property holding a string identifier associated with the paste operation. Likely used to correlate events or identify the source property.
|
||||
|
||||
- **`object Tag { get; }`**
|
||||
Read-only property for attaching arbitrary user-defined state or metadata to the event. Can be `null`.
|
||||
|
||||
### 3. Invariants
|
||||
- `Text`, `Sender`, `Id`, and `Tag` are immutable after construction (no setters beyond initialization).
|
||||
- `Sender` is *intended* to hold an instance implementing `IExtraProperty`, though the property type is `object`, allowing non-conforming values if passed incorrectly.
|
||||
- No validation is enforced on input arguments (e.g., `text` or `id` may be `null` or empty; `extraProperty` may be `null`).
|
||||
- The class itself is not thread-safe; concurrent access to instances is not guaranteed safe.
|
||||
|
||||
### 4. Dependencies
|
||||
- **Depends on**:
|
||||
- `System` (core types: `string`, `object`, `EventArgs` implied via interface)
|
||||
- `DTS.Common.Events` (likely contains `ITextPastedEventArgs` definition)
|
||||
- `DTS.Common.Interface.ISO.ExtraProperties` (contains `IExtraProperty` interface)
|
||||
- **Depended on by**:
|
||||
- Event publishers/consumers in the ISO Extra Properties subsystem that raise or handle `TextPasted` events (e.g., UI components or property editors invoking paste operations).
|
||||
- Any code expecting an `ITextPastedEventArgs` implementation (e.g., event handlers with signature `void OnTextPasted(object sender, ITextPastedEventArgs e)`).
|
||||
|
||||
### 5. Gotchas
|
||||
- `Sender` is stored as `object` despite being initialized from an `IExtraProperty`; callers must cast it back to `IExtraProperty` to access its members, risking `InvalidCastException` if misused.
|
||||
- No null-safety: passing `null` for `text`, `extraProperty`, `id`, or `tag` is permitted and will result in `null` property values—handlers must defensively check for null.
|
||||
- The `Id` and `Tag` parameters are not validated for uniqueness or type; misuse (e.g., passing mutable objects as `Tag`) could lead to unexpected side effects.
|
||||
- The class name `TextPastedArgs` (with past-tense "Pasted") may be inconsistent with naming conventions (e.g., `TextPasteEventArgs`), potentially causing confusion during discovery or search.
|
||||
- No documentation comments are present in the source; behavioral assumptions (e.g., semantics of `Id` or `Tag`) are inferred solely from usage context.
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Locking/LockRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Locking/LockError.cs
|
||||
generated_at: "2026-04-16T02:40:09.269029+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "ee1fc4660f405448"
|
||||
---
|
||||
|
||||
# Locking
|
||||
|
||||
### **Purpose**
|
||||
This module defines core data structures for representing and handling locking state and errors within the DTS system. Specifically, `LockRecord` encapsulates the metadata of an active lock (e.g., who holds it, when it was created, and what resource it pertains to), while `LockError` provides a structured way to represent lock-related error conditions—including recoverable states like lock theft or loss—enabling callers to programmatically respond to specific failure modes. Together, they serve as the foundational data models for a locking service, likely used in distributed or multi-user scenarios where resource contention must be managed.
|
||||
|
||||
---
|
||||
|
||||
### **Public Interface**
|
||||
|
||||
#### `LockRecord`
|
||||
A read-only data class representing the state of a lock.
|
||||
- **Constructor**:
|
||||
```csharp
|
||||
public LockRecord(string user, string machine, DateTime createTime, DateTime lastUpdate, string itemKey, int itemCategory, int itemId)
|
||||
```
|
||||
Initializes a new instance with the specified lock metadata. All properties are set once at construction and immutable thereafter.
|
||||
|
||||
- **Properties**:
|
||||
- `string LockingUserName` – The username of the entity holding the lock.
|
||||
- `string LockingMachineName` – The machine name of the entity holding the lock.
|
||||
- `DateTime CreationTime` – Timestamp when the lock was first acquired.
|
||||
- `DateTime LastUpdated` – Timestamp of the last lock maintenance (e.g., heartbeat or renewal).
|
||||
- `string ItemKey` – A string-based identifier for the locked item (e.g., a unique key or path).
|
||||
- `int ItemCategory` – An integer category code (corresponding to `LockCategories` in the database) classifying the type of item being locked.
|
||||
- `int ItemId` – A numeric identifier for the locked item (likely a primary key in a database table).
|
||||
|
||||
#### `LockError`
|
||||
A read-only data class representing an error condition in lock operations.
|
||||
- **Constructor**:
|
||||
```csharp
|
||||
public LockError(int error, string message, string user = null, string machine = null)
|
||||
```
|
||||
Initializes a new instance with an error code, descriptive message, and optional context about the locking user/machine.
|
||||
|
||||
- **Properties**:
|
||||
- `int ErrorCode` – The numeric error code (read-only after construction).
|
||||
- `string Message` – Human-readable error description (read-only after construction).
|
||||
- `string LockingUser` – Username associated with the error (defaults to `string.Empty` if `null`).
|
||||
- `string LockingMachine` – Machine name associated with the error (defaults to `string.Empty` if `null`).
|
||||
- `bool LockStolen` – `true` if `ErrorCode == LOCKSTOLEN_ERROR` (i.e., `998`).
|
||||
- `bool LockLost` – `true` if `ErrorCode == LOCKDOESNTEXIST_ERROR` (i.e., `997`).
|
||||
|
||||
- **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 does not exist.
|
||||
- `LOCKDOESNTEXIST_ERROR = 997` – Lock record no longer exists (e.g., expired or deleted).
|
||||
- `LOCKSTOLEN_ERROR = 998` – Lock was forcibly released by another party.
|
||||
- `UNKNOWN_ERROR = 999` – Generic/unspecified error.
|
||||
|
||||
---
|
||||
|
||||
### **Invariants**
|
||||
- `LockRecord` instances are **immutable** after construction: all properties are `readonly` (via auto-properties with `private set` implied by lack of setters) and initialized only in the constructor.
|
||||
- `LockError.ErrorCode`, `Message`, `LockingUser`, and `LockingMachine` are immutable after construction (via `private set`).
|
||||
- `LockingUser` and `LockingMachine` in `LockError` are never `null`; if `null` is passed to the constructor, they default to `string.Empty`.
|
||||
- `LockStolen` and `LockLost` are derived solely from `ErrorCode` and are guaranteed to be consistent with the defined constants.
|
||||
|
||||
---
|
||||
|
||||
### **Dependencies**
|
||||
- **Internal dependencies**:
|
||||
- `System` (for `DateTime`, `string`, `object`, etc.).
|
||||
- `System.Data` (imported but unused in these files; may indicate legacy or future use).
|
||||
- **External dependencies (inferred)**:
|
||||
- Likely consumed by other modules in `DTS.CommonCore` (e.g., a locking service or database persistence layer).
|
||||
- `ItemCategory` suggests integration with a database-defined `LockCategories` table (not present in source, but referenced in XML doc).
|
||||
- Error constants (`994`–`999`) imply coupling to SQL Server or ADO.NET error handling (per comments referencing `SqlClient`).
|
||||
|
||||
---
|
||||
|
||||
### **Gotchas**
|
||||
- **`System.Data` import is unused**: The `using System.Data;` statement in `LockRecord.cs` serves no purpose in the current implementation and may be legacy or placeholder.
|
||||
- **`LockingUser`/`LockingMachine` null-safety**: While `LockError` constructor normalizes `null` inputs to `string.Empty`, callers must be aware that `null` is *not* preserved—this may mask missing context if not handled explicitly.
|
||||
- **No validation in constructor**: Neither `LockRecord` nor `LockError` validates inputs (e.g., empty strings, negative `ItemId`/`ItemCategory`). Callers must ensure data integrity externally.
|
||||
- **`LockLost` vs. `LockStolen` semantics**: The distinction between `LOCKDOESNTEXIST_ERROR` (`LockLost`) and `LOCKSTOLEN_ERROR` (`LockStolen`) is subtle:
|
||||
- `LockLost` implies the lock vanished *without* explicit release (e.g., timeout, crash).
|
||||
- `LockStolen` implies another party *intentionally* released the lock (e.g., admin override).
|
||||
This distinction may be critical for retry or conflict-resolution logic but is not enforced programmatically.
|
||||
- **No versioning or extensibility mechanism**: The classes are simple DTOs with no support for forward/backward compatibility (e.g., new fields would require breaking changes).
|
||||
@@ -0,0 +1,225 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Sensors/DisplayedCalibrationBehavior.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/SensorDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/ZeroRef.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/CalMode.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/StreamInputRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/UARTRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/ParseParameters.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/DigitalInputScaleMultiplier.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/DigitalOutDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/SensorCalDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/StreamOutputRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/Sensors/ZeroMethod.cs
|
||||
generated_at: "2026-04-16T02:39:12.436129+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "f64af1453db763cc"
|
||||
---
|
||||
|
||||
# Sensor Data Model Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module defines core data structures for representing sensor metadata, calibration, and configuration within the DTS system. It provides concrete implementations of interfaces for database persistence (`SensorDbRecord`, `StreamInputRecord`, `UARTRecord`, `StreamOutputRecord`, `DigitalOutDbRecord`, `SensorCalDbRecord`), helper classes for parsing and serializing configuration strings (`ZeroRef`, `CalMode`, `DigitalInputScaleMultiplier`), and supporting infrastructure for calibration and zeroing behavior (`ZeroMethod`, `ZeroMethods`, `DisplayedCalibrationBehavior`). These classes serve as the foundational data layer for sensor management, enabling consistent representation of sensor properties across database operations, CSV import/export workflows, and UI binding contexts.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `DisplayedCalibrationBehavior`
|
||||
- **`CalibrationBehavior`** (`DTS.Common.Enums.Sensors.CalibrationBehaviors`): Stores the underlying calibration behavior enum value.
|
||||
- **`DisplayString`** (`string`): Human-readable string representation of the calibration behavior.
|
||||
- **`ToString()`** (`override string`): Returns `DisplayString`.
|
||||
|
||||
### `SensorDbRecord`
|
||||
- **`id`** (`int`): Database ID of the sensor model record.
|
||||
- **`SensorType`** (`short`): Sensor type identifier.
|
||||
- **`SerialNumber`** (`string`): Serial number of the sensor model.
|
||||
- **`TagType`** (`override TagTypes`): Returns `TagTypes.SensorModels`.
|
||||
- **Constructor `SensorDbRecord(IDataReader reader)`**: Initializes fields from database reader using `Utility.GetInt`, `Utility.GetShort`, and `Utility.GetString`.
|
||||
|
||||
### `ZeroRef`
|
||||
- **`ZeroType`** (`enum`): Defines zeroing methods:
|
||||
- `AverageOverTime` (serialized as `"0"`)
|
||||
- `UsePreEventDiagnostics` (serialized as `"1"`)
|
||||
- `UseZeroMv` (serialized as `"2"`)
|
||||
- **`ZeroMethod`** (`ZeroType`): The selected zeroing method.
|
||||
- **Constructor `ZeroRef(string zeroref)`**: Parses string (`"0"`, `"1"`, or `"2"`) into `ZeroMethod`; throws `NotSupportedException` for invalid input.
|
||||
- **Constructor `ZeroRef(ZeroType type)`**: Initializes `ZeroMethod` directly.
|
||||
- **`ToString()`** (`override string`): Returns `"0"`, `"1"`, or `"2"` based on `ZeroMethod`.
|
||||
|
||||
### `CalMode`
|
||||
- **`ShuntCheck`** (`bool`): `true` if shunt check enabled (`'S'` in position 0), `false` otherwise (`'I'`).
|
||||
- **`FullBridge`** (`bool`): `true` if full bridge mode (`'D'` in position 1), `false` otherwise (`'S'`).
|
||||
- **`Filter`** (`bool`): `true` if filter enabled (`'F'` in position 2), `false` otherwise (`'B'`).
|
||||
- **Constructor `CalMode(string value)`**: Parses 3-character string (e.g., `"SDF"`) into properties; throws `NotSupportedException` for invalid characters at any position.
|
||||
- **Constructor `CalMode()`**: Default constructor initializes all properties to `false`.
|
||||
- **`ToString()`** (`override string`): Serializes to 3-character string (e.g., `"SDF"`).
|
||||
|
||||
### `StreamInputRecord`
|
||||
- **`Id`** (`int`): Database ID of the sensor.
|
||||
- **`SerialNumber`** (`string`): Sensor serial number.
|
||||
- **`LastModified`** (`DateTime`): Timestamp of last modification.
|
||||
- **`LastUpdatedBy`** (`string`): User who last modified the record.
|
||||
- **`DoNotUse`** (`bool`): Flag indicating sensor should be excluded from use.
|
||||
- **`Broken`** (`bool`): Flag indicating sensor is broken.
|
||||
- **`StreamInUDPAddress`** (`string`): UDP address for streaming input; defaults to `"UDP://239.1.2.10:8400"`.
|
||||
- **`TagType`** (`override TagTypes`): Returns `TagTypes.Sensors`.
|
||||
- **Constructor `StreamInputRecord(ISensorData sd)`**: Initializes from `ISensorData` interface; logs exceptions via `APILogger`.
|
||||
- **Constructor `StreamInputRecord(IDataReader reader)`**: Initializes from database reader; logs exceptions via `APILogger`.
|
||||
|
||||
### `UARTRecord`
|
||||
- **`Id`** (`int`): Database ID.
|
||||
- **`SerialNumber`** (`string`): Serial number.
|
||||
- **`UartBaudRate`** (`uint`): Baud rate; default `57600`.
|
||||
- **`UartDataBits`** (`uint`): Data bits; default `8`.
|
||||
- **`UartStopBits`** (`StopBits`): Stop bits; default `StopBits.None`.
|
||||
- **`UartParity`** (`Parity`): Parity; default `Parity.None`.
|
||||
- **`UartFlowControl`** (`Handshake`): Flow control; default `Handshake.None`.
|
||||
- **`UartDataFormat`** (`UartDataFormat`): Data format; default `UartDataFormat.Binary`.
|
||||
- **`LastModified`** (`DateTime`): Last modification timestamp.
|
||||
- **`LastUpdatedBy`** (`string`): Last modifier.
|
||||
- **`DoNotUse`** (`bool`): Exclusion flag.
|
||||
- **`Broken`** (`bool`): Broken flag.
|
||||
- **`TagType`** (`TagTypes`): Returns `TagTypes.Sensors`.
|
||||
- **Constructor `UARTRecord(ISensorData sensor)`**: Initializes from `ISensorData`.
|
||||
- **Constructor `UARTRecord(IDataReader reader)`**: Initializes from database reader; parses enum fields via `Enum.Parse`; logs exceptions.
|
||||
|
||||
### `ParseParameters`
|
||||
- **`SensorData`** (`ISensorData`): Sensor data source.
|
||||
- **`ImportCulture`** (`IFormatProvider`): Culture for parsing during import.
|
||||
- **`Errors`** (`List<string>`): Accumulated errors during parsing.
|
||||
- **`IrtraccExponent`** (`double`): Exponent for IrTracc scaling.
|
||||
- **`SensorCal`** (`ISensorCalibration`): Calibration data.
|
||||
- **`Sensitivity`** (`double`): Sensitivity value.
|
||||
- **`SavedIsProportional`** (`bool`): Proportional flag.
|
||||
- **`SavedRemoveOffset`** (`bool`): Remove offset flag.
|
||||
- **`StripBackslash`** (`bool`): Backslash stripping flag.
|
||||
- **`OriginalOffset`** (`double`): Original offset value.
|
||||
- **`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`**, **`SensorGroupTypeLookup`**, etc.: Multiple `Dictionary<string, string>` fields for mapping group names, ISO codes, user codes, DAS serial numbers, and channel indices.
|
||||
- **`SensorTestObject`** (`string`): Test object identifier.
|
||||
- **`UseISOCodeFilterMapping`**, **`UseZeroForUnfiltered`** (`bool`): Filtering flags.
|
||||
- **`SensorISOCode`**, **`SensorUserCode`**, etc.: Dictionaries for channel mappings.
|
||||
|
||||
### `DigitalInputScaleMultiplier`
|
||||
- **`Form`** (`Forms`): Scaling form; defaults to `Forms.ArbitraryLowAndHigh`.
|
||||
- **`DefaultValue`** (`double`): Value displayed for digital input `0` (OFF); defaults to `0`.
|
||||
- **`ActiveValue`** (`double`): Value displayed for digital input `1` (ON); defaults to `1`.
|
||||
- **`SimpleEquals(IDigitalInputScaleMultiplier rhs)`** (`bool`): Compares `Form`, `DefaultValue`, and `ActiveValue`.
|
||||
- **`Equals(object obj)`** (`override bool`): Deep equality check.
|
||||
- **`GetHashCode()`** (`override int`): Hash code using primes `31` and `79`.
|
||||
- **Constructor `DigitalInputScaleMultiplier()`**: Initializes `DefaultValue = 0`.
|
||||
- **Constructor `DigitalInputScaleMultiplier(DigitalInputScaleMultiplier copy)`**: Copy constructor.
|
||||
- **`ToSerializeDbString()`** (`string`): Serializes to format `"ArbitraryLowAndHigh,defaultValue,activeValue"`.
|
||||
- **`FromDbSerializeString(string s)`** (`void`): Deserializes from string; throws `NotSupportedException` on invalid format.
|
||||
|
||||
### `DigitalOutDbRecord`
|
||||
- **`SerialNumber`** (`string`): Serial number.
|
||||
- **`DODelay`** (`double`): Digital output delay in ms; default `0`.
|
||||
- **`DODuration`** (`double`): Digital output duration in ms; default `0`.
|
||||
- **`ModifiedBy`** (`string`): Last modifier.
|
||||
- **`LastModified`** (`DateTime`): Last modification timestamp.
|
||||
- **`DatabaseId`** (`int`): Database ID; default `-1`.
|
||||
- **`ISOCode`**, **`ISOChannelName`**, **`UserCode`**, **`UserChannelName`** (`string`): Channel identification fields.
|
||||
- **`Broken`** (`bool`): Broken flag; default `false`.
|
||||
- **`DoNotUse`** (`bool`): Exclusion flag; default `false`.
|
||||
- **`DOMode`** (`DigitalOutputModes`): Output mode; default `DigitalOutputModes.CCNC`.
|
||||
- **`LimitDuration`** (`bool`): Duration limit flag; default `true`.
|
||||
- **`Version`** (`int`): Record version; default `0`.
|
||||
- **`TagsBlobBytes`** (`byte[]`): Binary tags blob.
|
||||
- **Constructor `DigitalOutDbRecord()`**: Default constructor.
|
||||
- **Constructor `DigitalOutDbRecord(ISensorData copy, byte[] tagsBlobBytes)`**: Initializes from `ISensorData` and tags blob.
|
||||
- **Constructor `DigitalOutDbRecord(IDigitalOutDbRecord copy)`**: Copy constructor.
|
||||
- **Constructor `DigitalOutDbRecord(IDataReader reader)`**: Initializes from database reader.
|
||||
|
||||
### `SensorCalDbRecord`
|
||||
- **`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`): Local-only flag.
|
||||
- **`NonLinear`** (`bool`): Non-linear calibration flag; setting to `true` sets `RemoveOffset = false`.
|
||||
- **`Records`** (`ICalibrationRecords`): Calibration records.
|
||||
- **`ModifyDate`** (`DateTime`): Last modification date.
|
||||
- **`IsProportional`** (`bool`): Proportional calibration flag.
|
||||
- **`RemoveOffset`** (`bool`): Remove offset flag.
|
||||
- **`ZeroMethods`** (`ZeroMethods`): Zeroing method definitions.
|
||||
- **`CertificationDocuments`** (`string[]`): Array of certification document paths.
|
||||
- **`InitialOffsets`** (`InitialOffsets`): Initial offset definitions.
|
||||
- **`LinearAdded`** (`bool`): Indicates if linear calibration is added (requires non-linear, polynomial, and multiple zero methods).
|
||||
- **Constructor `SensorCalDbRecord()`**: Default constructor.
|
||||
- **Constructor `SensorCalDbRecord(ISensorCalDbRecord copy)`**: Copy constructor; deep copies arrays and marks linearization valid.
|
||||
- **Constructor `SensorCalDbRecord(IDataReader reader)`**: Initializes from database reader; logs exceptions.
|
||||
|
||||
### `StreamOutputRecord`
|
||||
- **`Id`** (`int`): Database ID.
|
||||
- **`SerialNumber`** (`string`): Serial number.
|
||||
- **`LastModified`** (`DateTime`): Last modification timestamp.
|
||||
- **`LastUpdatedBy`** (`string`): Last modifier.
|
||||
- **`DoNotUse`** (`bool`): Exclusion flag.
|
||||
- **`Broken`** (`bool`): Broken flag.
|
||||
- **`StreamOutUDPProfile`** (`UDPStreamProfile`): Stream profile; default `UDPStreamProfile.CH10_ANALOG_2HDR`.
|
||||
- **`StreamOutUDPAddress`** (`string`): UDP address; defaults to `"UDP://239.1.2.10:8400"`.
|
||||
- **`StreamOutUDPTimeChannelId`** (`ushort`): Time channel ID; range `[10, 100]`, default `1`.
|
||||
- **`StreamOutUDPDataChannelId`** (`ushort`): Data channel ID; range `[10, 100]`, default `3`.
|
||||
- **`StreamOutUDPTmNSConfig`** (`string`): TMNS configuration; default `"(1,6,60,0,0,0,0,0)"`.
|
||||
- **`StreamOutIRIGTimeDataPacketIntervalMs`** (`ushort`): IRIG time data packet interval; range `[10, 1000]`, default `500`.
|
||||
- **`StreamOutTMATSIntervalMs`** (`ushort`): TMATS interval; range `[0, 65535]`, default `1000`.
|
||||
- **`TagType`** (`override TagTypes`): Returns `TagTypes.Sensors`.
|
||||
- **`AvailableUDPStreamProfiles(int ConnectionDbVersion, bool UseAdvancedStreamingProfiles)`** (`static UDPStreamProfile[]`): Returns list of supported profiles based on version and profile type.
|
||||
- **Constructor `StreamOutputRecord(ISensorData sd)`**: Initializes from `ISensorData`.
|
||||
- **Constructor `StreamOutputRecord(IDataReader reader, int ClientDbVersion, int ConnectionDbVersion)`**: Initializes from database reader; conditionally reads `TMATS_IntervalMS` if versions permit.
|
||||
|
||||
### `ZeroMethod`
|
||||
- **`Method`** (`ZeroMethodType`): Zeroing method type; defaults to `SensorConstants.DefaultZeroMethodType`.
|
||||
- **`Start`** (`double`): Start value for zeroing window; defaults to `SensorConstants.DefaultZeroMethodStart`.
|
||||
- **`End`** (`double`): End value for zeroing window; defaults to `SensorConstants.DefaultZeroMethodEnd`.
|
||||
- **`PropertyChanged`** (`event PropertyChangedEventHandler`): Implements `INotifyPropertyChanged`.
|
||||
- **Constructor `ZeroMethod(ZeroMethodType zm, double start, double end)`**: Initializes all fields.
|
||||
- **Constructor `ZeroMethod(string zm, CultureInfo culture)`**: Parses `"Method,Start,End"` string.
|
||||
- **Constructor `ZeroMethod(ZeroMethod copy)`**: Deep copy constructor.
|
||||
- **`ToDbString()`** (`string`): Serializes to `"Method,Start,End"`.
|
||||
- **`ToXElement(string prefix)`** (`XElement`): Serializes to XML element.
|
||||
- **`Update(XElement elem, string prefix)`** (`void`): Updates XML element in-place.
|
||||
- **`ToSerializeString()`** (`string`): Same as `ToDbString()`.
|
||||
- **`ToDisplayString(...)`** (`string`): Human-readable display string based on `Method`.
|
||||
|
||||
### `ZeroMethods`
|
||||
- **`Methods`** (`ZeroMethod[]`): Array of zero methods.
|
||||
- **Constructor `ZeroMethods()`**: Default (empty array).
|
||||
- **Constructor `ZeroMethods(string methods)`**: Parses serialized string using `"__x__"` separator.
|
||||
- **Constructor `ZeroMethods(ZeroMethod[] copyMethods)`**: Deep copy constructor.
|
||||
- **`FromSerializedString(string s)`** (`void`): Parses serialized string.
|
||||
- **`ToSerializedString()`** (`string`): Serializes using `"__x__"` separator; escapes separator characters.
|
||||
- **`ToDisplayString(...)`** (`string`): Human-readable display string for all methods.
|
||||
- **`ToString()`** (`override string`): Calls `ToDisplayString` with localized format strings.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`ZeroRef`**: String serialization is strictly `"0"`, `"1"`, or `"2"`; invalid inputs throw `NotSupportedException`.
|
||||
- **`CalMode`**: String serialization is exactly 3 characters; positions 0, 1, 2 must be `S/I`, `D/S`, and `F/B` respectively; invalid inputs throw `NotSupportedException`.
|
||||
- **`DigitalInputScaleMultiplier`**: Serialization format is `"Form,DefaultValue,ActiveValue"`; only `Forms.ArbitraryLowAndHigh` is supported; invalid formats throw `NotSupportedException`.
|
||||
- **`ZeroMethod`**: Serialization format is `"Method,Start,End"`; XML serialization uses `"UsePreCalZero"` as legacy alias for `UsePreEventDiagnosticsZero`.
|
||||
- **`ZeroMethods`**: Serialization uses `"__x__"` as primary separator and `"___xx___"` as backup escape sequence; `ToString()` uses localized format strings.
|
||||
- **`SensorCalDbRecord.NonLinear`**: Setting to `true` forces `RemoveOffset = false`.
|
||||
- **`StreamOutputRecord.StreamOutUDPTimeChannelId`** and **`StreamOutUDPDataChannelId`**: Valid range is `[10, 100]`.
|
||||
- **`StreamOutputRecord.StreamOutIRIGTimeDataPacketIntervalMs`**: Valid range is `[10, 1000]`.
|
||||
- **`UARTRecord`**: All UART configuration fields have defined default values (`UartBaudRate=57600`, `UartDataBits=8`, `UartStopBits=None`, `UartParity=None`, `UartFlowControl=None`, `UartDataFormat=Binary`).
|
||||
- **`StreamInputRecord.StreamInUDPAddress`**: Defaults to `"UDP://239.1.2.10:8400"`.
|
||||
- **`StreamOutputRecord.StreamOutUDPAddress`**: Defaults to `"UDP://239.1.2.10:8400"`.
|
||||
- **`DigitalOutDbRecord.DatabaseId`**: Default is `-1` (indicating no database assignment).
|
||||
- **`DigitalOutDbRecord.LimitDuration`**: Defaults to `true`.
|
||||
- **`DigitalOutDbRecord.DOMode`**: Defaults to `DigitalOutputModes.CCNC`.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.Base`**: Provides `BasePropertyChanged` (used by `DigitalOutDbRecord`, `SensorCalDbRecord`, `ZeroMethod`).
|
||||
- **`DTS.Common.Interface.Tags`**: Provides `TagAwareBase` (base class for `SensorDbRecord`, `StreamInputRecord`, `StreamOutputRecord`).
|
||||
- **`DTS.Common.Interface.Sensors`**: Provides core interfaces (`ISensorData`, `ISensorCalDbRecord`, `IDigitalOutDbRecord`, `IDigitalInputScaleMultiplier`, `IUARTRecord`, `IStreamInputRecord`, `IStreamOutputRecord`, `ISensorCalibration`, `ISquibSettingDefaults`, `IDigitalOutDefaults`).
|
||||
- **`
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Sensors/SensorsList/DragAndDropPayload.cs
|
||||
generated_at: "2026-04-16T02:41:47.536416+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "c4ab033f3383cdef"
|
||||
---
|
||||
|
||||
# SensorsList
|
||||
|
||||
### 1. **Purpose**
|
||||
The `DragAndDropPayload` class encapsulates data transferred during drag-and-drop operations involving sensor items in the UI. It serves as a serializable container that wraps an array of `IDragAndDropItem` objects, enabling consistent handling of drag-and-drop payloads across components that interact with sensors (e.g., reordering, copying, or moving sensors in a list). Its inclusion of multiple format strings supports different drag contexts (e.g., standard, Alt-modified, Ctrl-modified operations), facilitating platform-agnostic or framework-specific drag-and-drop mechanisms.
|
||||
|
||||
### 2. **Public Interface**
|
||||
- **`public IDragAndDropItem[] Items { get; }`**
|
||||
A read-only property exposing the array of drag-and-drop items contained in the payload. The array is set at construction and cannot be modified afterward.
|
||||
|
||||
- **`public DragAndDropPayload(IDragAndDropItem[] items)`**
|
||||
Constructor that initializes the payload with the provided array of `IDragAndDropItem` instances. The array is stored directly (no defensive copy is made, per source).
|
||||
|
||||
- **`public const string FORMAT`**
|
||||
A constant string `"DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload"` representing the primary data format identifier for the payload.
|
||||
|
||||
- **`public const string ALT_FORMAT`**
|
||||
A constant string `"ALT_DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload"` representing an alternative format, likely used when the Alt key is held during drag.
|
||||
|
||||
- **`public const string CTRL_FORMAT`**
|
||||
A constant string `"CTRL_DTS.Common.Classes.Sensors.SensorsList.DragAndDropPayload"` representing a format used when the Ctrl key is held during drag (e.g., for copy vs. move semantics).
|
||||
|
||||
### 3. **Invariants**
|
||||
- `Items` is non-null and initialized to the exact array passed to the constructor (no validation or defensive copying is performed in the constructor).
|
||||
- The `FORMAT`, `ALT_FORMAT`, and `CTRL_FORMAT` constants are immutable and uniquely identify the payload type in drag-and-drop operations.
|
||||
- The class is immutable from the caller’s perspective after construction (only `Items` is exposed, and it is read-only via the property).
|
||||
|
||||
### 4. **Dependencies**
|
||||
- **Depends on**:
|
||||
- `DTS.Common.Interface.Sensors.SensorsList.IDragAndDropItem` (via the `Items` property type). This interface defines the contract for items that can be dragged/dropped in the sensors list context.
|
||||
- **Depended on by**:
|
||||
- UI components or services that handle drag-and-drop for sensors (e.g., drag source initiators, drop target handlers) would serialize/deserialize payloads using the `FORMAT`/`ALT_FORMAT`/`CTRL_FORMAT` strings.
|
||||
- Serialization logic (e.g., for clipboard or drag-drop operations) likely relies on these format strings to reconstruct `DragAndDropPayload` instances.
|
||||
|
||||
### 5. **Gotchas**
|
||||
- **No defensive copy**: The constructor assigns the `items` array directly to the `Items` property. Modifications to the array *after* construction (if the caller retains a reference) will mutate the payload’s contents, violating immutability expectations. Callers must not retain or modify the passed array.
|
||||
- **No null/empty validation**: The constructor does not validate that `items` is non-null or non-empty. Passing `null` or an empty array is allowed and may lead to downstream `NullReferenceException`s or unexpected behavior if not handled.
|
||||
- **Format string semantics are not self-documenting**: While the constants suggest context-specific behavior (e.g., `ALT_FORMAT`, `CTRL_FORMAT`), their exact usage (e.g., how they map to operations like copy vs. move) is not defined in this file and must be inferred from consumers.
|
||||
- **No serialization attributes**: The class lacks explicit serialization attributes (e.g., `[Serializable]`, `[DataContract]`), implying reliance on framework-specific drag-drop serialization (e.g., `DataObject` in WinForms or `DragEventArgs` in WPF). Compatibility may be fragile if used outside intended UI frameworks.
|
||||
- **No documentation on format string usage**: It is unclear how `ALT_FORMAT` and `CTRL_FORMAT` are registered or consumed—e.g., whether they are used as fallbacks or in parallel with `FORMAT`.
|
||||
@@ -0,0 +1,97 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/TMAT/TMTTemplate.cs
|
||||
generated_at: "2026-04-16T02:40:28.075233+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "759eebf6c2f0302e"
|
||||
---
|
||||
|
||||
# TMAT
|
||||
|
||||
## Documentation: `TMTTemplate` Module
|
||||
|
||||
### 1. Purpose
|
||||
This module provides infrastructure for processing template files (`.tmt` files) used in test configuration and reporting workflows. It enables programmatic substitution of predefined placeholders (e.g., `{NAME OF PROGRAM}`, `{{CHANNEL {0} NAME}}`) with runtime values. The module decouples template structure from data population, supporting both global metadata (e.g., test ID, serial number) and per-channel properties (e.g., hardware channel number, scaling factors). It is part of the `DTS.Common.Classes.TMAT` namespace and serves as a foundational component for generating or modifying test configuration files dynamically.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### Enums
|
||||
- **`TMTGlobalKeys`**
|
||||
Enumerates global placeholder keys used in templates. Each member is decorated with a `[TMTKey]` attribute specifying the literal pattern to search for.
|
||||
Examples:
|
||||
- `NameOfProgram` → pattern: `"{NAME OF PROGRAM}"`
|
||||
- `DASSerialNumber` → pattern: `"{DAS SERIAL NUMBER}"`
|
||||
- `UdpStreamTimeChannelId` → pattern: `"{UDP STREAM TIME CHANNEL ID}"`
|
||||
|
||||
- **`TMTChannelKeys`**
|
||||
Enumerates per-channel placeholder keys. Each pattern includes a format specifier `{0}` for the channel number.
|
||||
Examples:
|
||||
- `HardwareChannelNumber` → pattern: `"{{CHANNEL {0} HARDWARE CHANNEL NUMBER}}"`
|
||||
- `ChannelName` → pattern: `"{{CHANNEL {0} NAME}}"`
|
||||
- `ScaleFactorEU` → pattern: `"{{CHANNEL {0} SCALEFACTOR EU}}"`
|
||||
|
||||
#### Attribute
|
||||
- **`TMTKeyAttribute`**
|
||||
- `public string Key { get; }` – Stores the literal pattern string (e.g., `"{NAME OF PROGRAM}"`).
|
||||
- `public TMTKey(string key)` – Constructor initializing `Key`.
|
||||
- `public static string GetKey(TMTGlobalKeys key)` – Returns the pattern string for a global key.
|
||||
- `public static string GetKey(TMTChannelKeys key, int channelNumber)` – Returns the pattern string for a channel key, with `{0}` replaced by `channelNumber`.
|
||||
|
||||
#### Interface
|
||||
- **`ITMTTemplate`**
|
||||
- `void UpdateValue(TMTGlobalKeys key, string value)`
|
||||
Replaces all occurrences of the pattern associated with `key` in the template with `value`.
|
||||
- `void UpdateValue(TMTChannelKeys key, string value, int channelNumber)`
|
||||
Replaces all occurrences of the pattern associated with `key` (formatted with `channelNumber`) in the template with `value`.
|
||||
- `string[] GetAllLines()`
|
||||
Returns the current content of the template as an array of lines.
|
||||
|
||||
#### Class
|
||||
- **`TMTTemplate : ITMTTemplate`**
|
||||
- `public TMTTemplate(string templateLocation)`
|
||||
Loads all lines from the file at `templateLocation` into internal storage.
|
||||
- `public TMTTemplate(string[] lines)`
|
||||
Initializes the template with the provided `lines` (e.g., for in-memory templates).
|
||||
- `public void UpdateValue(TMTGlobalKeys key, string value)`
|
||||
Iterates through all lines; for each line containing the pattern for `key`, replaces the pattern with `value`.
|
||||
- `public void UpdateValue(TMTChannelKeys key, string value, int channelNumber)`
|
||||
Iterates through all lines; for each line containing the formatted pattern for `key` (with `channelNumber`), replaces the pattern with `value`.
|
||||
- `public string[] GetAllLines()`
|
||||
Returns a copy of the internal line list as an array.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
- **Template file existence is not enforced at construction**: If `templateLocation` is invalid or the file does not exist, `_allLines` remains empty (no exception thrown).
|
||||
- **Pattern replacement is literal and non-semantic**:
|
||||
- `Contains(pattern)` is used for matching, so partial matches (e.g., `"{NAME OF PROGRA}"` inside `"{NAME OF PROGRAM}"`) may cause unintended replacements.
|
||||
- Replacements are done via `string.Replace`, which replaces *all* occurrences of the pattern in a line (not just the first).
|
||||
- **Channel keys require exact formatting**: The pattern for channel keys includes double braces (`{{...}}`) to support `string.Format`, but the module does not validate that `channelNumber` produces a syntactically valid pattern (e.g., negative numbers are allowed).
|
||||
- **No deduplication or ordering guarantees**: Multiple updates to the same key in a single line will overwrite each other in sequence, but the final state depends on line order and replacement count.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
- **Internal dependencies**:
|
||||
- `System.Collections.Generic` (for `List<string>`)
|
||||
- `System.IO` (for `File.Exists`, `File.ReadAllLines`)
|
||||
- Reflection (`System.Type.GetMember`, `Attribute.GetCustomAttribute`) for pattern extraction from enums.
|
||||
- **External dependencies**:
|
||||
- Consumers must provide valid `.tmt` template files (or line arrays) to `TMTTemplate` constructors.
|
||||
- The module is used by other components (e.g., test execution or reporting systems) that populate template values.
|
||||
- **No external libraries or services** beyond core .NET types.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
- **Case sensitivity**: Pattern matching via `Contains` is case-sensitive. A template line `" {NAME OF PROGRAM} "` will match, but `" {name of program} "` will not.
|
||||
- **Brace escaping in channel keys**: The `{{CHANNEL {0} ...}}` pattern relies on `string.Format` semantics. If `channelNumber` is `0`, the pattern becomes `"{{CHANNEL 0 ...}}"`, which is correct. However, if `channelNumber` is negative (e.g., `-1`), the result is `"{{CHANNEL -1 ...}}"`—syntactically valid but semantically questionable.
|
||||
- **No validation of placeholder presence**: `UpdateValue` silently does nothing if the pattern is not found in any line.
|
||||
- **No thread safety**: The class is not thread-safe; concurrent calls to `UpdateValue` on the same instance may cause race conditions.
|
||||
- **Memory overhead**: All template lines are held in memory (`_allLines`) during processing. Large templates may consume significant memory.
|
||||
- **No error handling for malformed templates**: If a template line contains unbalanced braces or invalid `string.Format` syntax (e.g., `{{CHANNEL {0} NAME`), `string.Format` in `GetKey(TMTChannelKeys, int)` will throw an exception.
|
||||
- **Historical quirk (commented)**:
|
||||
- `UdpStreamTimeChannelId`/`UdpStreamDataChannelId` and `CreateDate` were added in fixes FB 26736 and FB 29996, respectively—suggesting these keys were added post-initial design.
|
||||
223
enriched-qwen3-coder-next/Common/DTS.CommonCore/Classes/Tags.md
Normal file
223
enriched-qwen3-coder-next/Common/DTS.CommonCore/Classes/Tags.md
Normal file
@@ -0,0 +1,223 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/Tags/TagAssignment.cs
|
||||
- Common/DTS.CommonCore/Classes/Tags/Tag.cs
|
||||
- Common/DTS.CommonCore/Classes/Tags/TagAwareBase.cs
|
||||
- Common/DTS.CommonCore/Classes/Tags/TagsInstance.cs
|
||||
generated_at: "2026-04-16T02:41:01.456676+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "3dfbd6a973f4cede"
|
||||
---
|
||||
|
||||
# Tags
|
||||
|
||||
## Documentation: Tagging Infrastructure (`DTS.Common.Classes.Tags`)
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module provides a tag-based metadata system for associating arbitrary textual labels with domain objects (e.g., assets, events, configurations). It enables objects to be tagged with human-readable strings (e.g., `"Urgent"`, `"Critical"`, `"Legacy"`) and persisted via database assignments. The system supports lazy caching of tag definitions in memory for fast lookup, and provides base infrastructure (`TagAwareBase`) for domain classes to integrate tagging functionality. Tags themselves are immutable (no edit/delete/obsolete operations), and new tags are auto-created on first use.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `TagAssignment` class
|
||||
Represents a database assignment record linking a tag to an object.
|
||||
|
||||
- **`TagAssignment()`**
|
||||
Default constructor.
|
||||
|
||||
- **`TagAssignment(IDataReader reader)`**
|
||||
Constructor that populates fields from a database reader. Reads `TagID`, `ObjectID`, and `ObjectType` (as `short` cast to `TagTypes`).
|
||||
|
||||
- **`int ObjectID`**
|
||||
Gets/sets the ID of the object being tagged.
|
||||
|
||||
- **`int TagID`**
|
||||
Gets/sets the ID of the tag being assigned.
|
||||
|
||||
- **`TagTypes ObjectType`**
|
||||
Gets/sets the *type* of the object being tagged (e.g., `TagTypes.Asset`, `TagTypes.Event`). *Note: Property name is `ObjectType`, not `TagType`.*
|
||||
|
||||
#### `Tag` class
|
||||
Represents a single tag: an immutable ID-text pair (text is mutable via property, but DB behavior is immutable per comment).
|
||||
|
||||
- **`Tag()`**
|
||||
Default constructor.
|
||||
|
||||
- **`Tag(string tagText, int tagId)`**
|
||||
Constructor with explicit ID and text.
|
||||
|
||||
- **`Tag(Tag copy)`**
|
||||
Copy constructor.
|
||||
|
||||
- **`Tag(IDataReader reader)`**
|
||||
Constructor that populates fields from DB reader: `TagId`, `Obsolete`, `TagText`.
|
||||
|
||||
- **`int ID`**
|
||||
Gets/sets the tag’s database ID.
|
||||
|
||||
- **`string Text`**
|
||||
Gets/sets the tag’s display text.
|
||||
|
||||
- **`bool IsObsolete`**
|
||||
Gets/sets whether the tag is obsolete (currently not enforced by UI logic per comment).
|
||||
|
||||
- **`const int INVALID_ID = -1`**
|
||||
Sentinel value for uninitialized or missing tag IDs.
|
||||
|
||||
- **`object Clone()`**
|
||||
Returns a new `Tag` instance with identical `ID`, `Text`, and `IsObsolete`.
|
||||
|
||||
#### `TagAwareBase` abstract class
|
||||
Base class for domain objects that support tagging.
|
||||
|
||||
- **`abstract TagTypes TagType { get; }`**
|
||||
Must be implemented by derived classes to specify the object’s tag type.
|
||||
|
||||
- **`int[] TagIDs`**
|
||||
Gets/sets the list of tag IDs associated with this object.
|
||||
|
||||
- **`byte[] TagsBlobBytes`**
|
||||
Gets/sets `TagIDs` as a binary blob (using `Buffer.BlockCopy`). Setter logs exceptions via `APILogger`.
|
||||
|
||||
- **`void SetTagsFromCommaSeparatedString(string tagText, ...)`**
|
||||
Parses comma-separated tag strings (e.g., `"Urgent, Critical"`), ensures tags exist in DB/cache, and updates `TagIDs`. Trims leading whitespace per implementation.
|
||||
|
||||
- **`virtual void SetTags(string[] tagsText, ...)`**
|
||||
Same as above, but accepts an array of tag strings.
|
||||
|
||||
- **`string GetTagsAsCommaSeparatedString(TagsGetDelegate tagsGet)`**
|
||||
Returns comma-separated tag *text* (e.g., `"Urgent,Critical"`), using `tagsGet` to resolve IDs to text.
|
||||
|
||||
- **`virtual string[] GetTagsArray(TagsGetDelegate tagsGet)`**
|
||||
Returns array of tag *text* values corresponding to `TagIDs`.
|
||||
|
||||
- **`virtual int[] GetTagIDs()`**
|
||||
Returns current `TagIDs`.
|
||||
|
||||
- **`virtual void RemoveTags(string[] tagsText)`**
|
||||
*Stub implementation only* — no-op. Comment says `// remove tags!!!`.
|
||||
|
||||
- **`bool TagCompatible(string tags, TagsGetDelegate tagsGet)`**
|
||||
Returns `true` if *any* tag in the input comma-separated string matches *any* tag currently assigned to this object.
|
||||
|
||||
- **`virtual bool TagCompatible(int[] tags)`**
|
||||
Returns `true` if `tags` array is empty *or* if there is any intersection with `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(id, tagType, ...)`. Used to persist tags after modification.
|
||||
|
||||
- **`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 a given `(tagType, objectId)` from DB, filters to match `objectId`, and returns list of unique `TagID`s.
|
||||
|
||||
#### `TagsInstance` class
|
||||
Singleton-like manager for tag metadata (cached in memory, populated on first use or explicit `UpdateList`).
|
||||
|
||||
- **`static TagsInstance GetTagsInstance(TagsGetDelegate tagsGet)`**
|
||||
Returns the singleton instance, initializing it with `tagsGet` if not already created.
|
||||
|
||||
- **`static bool AddTag(string tagText, ...)`**
|
||||
Adds `tagText` to DB if not already present (case-sensitive, per dictionary key). Returns `false` if tag already exists or input is null/empty.
|
||||
|
||||
- **`static bool MigrateTag(string tagText, ...)`**
|
||||
Adds/updates tag during DB migration (e.g., to reassign IDs). Does *not* check for existence before inserting.
|
||||
|
||||
- **`static bool[] AddRange(string[] tagText, ...)`**
|
||||
Adds multiple tags (trims leading whitespace per element). Returns array of `true`/`false` per tag.
|
||||
|
||||
- **`static int GetIDFromTagText(string tagText, TagsGetDelegate tagsGet, TagsGetIdDelegate tagsGetId)`**
|
||||
Looks up tag ID from DB using `tagsGetId`. Returns `Tag.INVALID_ID` (`-1`) if not found.
|
||||
|
||||
- **`static int[] GetIDsFromTagText(string[] tagText, ...)`**
|
||||
Returns array of tag IDs for input texts, skipping `INVALID_ID`s.
|
||||
|
||||
- **`static string GetTagTextFromID(int tagID, TagsGetDelegate tagsGet)`**
|
||||
Looks up tag text from in-memory cache. Returns `null` if ID is invalid or not found.
|
||||
|
||||
- **`static string[] GetTagTextFromIDs(int[] tagId, TagsGetDelegate tagsGet)`**
|
||||
Returns array of tag texts for IDs, skipping invalid/missing entries.
|
||||
|
||||
- **`void UpdateList(TagsGetDelegate tagsGet)`**
|
||||
Refreshes in-memory cache by calling `tagsGet(null, out tags)` and repopulating `_tagsLookup`.
|
||||
|
||||
- **`bool ContainsTag(string text)`**
|
||||
Returns `true` if `text` exists in in-memory cache.
|
||||
|
||||
#### Delegates (used for decoupling DB operations)
|
||||
|
||||
- `TagsGetDelegate(int? id, out ITag[] tags)`
|
||||
Retrieves tags by ID (or all if `id == null`).
|
||||
|
||||
- `TagsGetIdDelegate(string text, out int? id)`
|
||||
Retrieves tag ID by text.
|
||||
|
||||
- `TagsInsertDelegate(ref ITag tag)`
|
||||
Inserts a new tag (assigns `ID` on success).
|
||||
|
||||
- `GetSqlCommandDelegate(bool bNewConnection)`
|
||||
Returns a `SqlCommand` (likely for transactional operations).
|
||||
|
||||
- `TagAssignmentsGet(TagTypes? tagType, out ITagAssignment[] records)`
|
||||
Retrieves tag assignments (optionally filtered by `tagType`).
|
||||
|
||||
- `TagAssignmentsDelete(TagTypes objectType, int objectId)`
|
||||
Deletes all assignments for given object.
|
||||
|
||||
- `TagAssignmentsInsert(ITagAssignment tagAssignment)`
|
||||
Inserts a single assignment.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **Tag immutability (by design)**: The `Tag` class comment states: *“we don't currently let you obsolete, delete, or edit tags, just add”*. While `IsObsolete` and `Text` are settable, the `Commit` logic in `TagsInstance` only updates IDs (via `UpdateAll`), and no DB update path for text exists.
|
||||
- **`Tag.INVALID_ID == -1`** is the canonical sentinel for missing/invalid tag IDs.
|
||||
- **`TagsInstance` is a singleton per AppDomain**: Initialized only once via `GetTagsInstance`, with caching done in-memory on startup and updated only on explicit `AddTag`/`UpdateList`.
|
||||
- **`TagIDs` is never `null`**: The `TagIDs` setter in `TagAwareBase` replaces `null` with `new int[0]`.
|
||||
- **`TagsBlobBytes` size must be a multiple of `sizeof(int)`**: Setter silently returns if `value.Length < sizeof(int)`.
|
||||
- **Tag assignment deletion happens before insertion in `Commit`**: Ensures no stale assignments persist.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
- **Internal dependencies**:
|
||||
- `DTS.Common.Base.BasePropertyChanged` (base class for `INotifyPropertyChanged`).
|
||||
- `DTS.Common.Interface.Tags` (interfaces `ITag`, `ITagAssignment`, `ITagAware`).
|
||||
- `DTS.Common.Utilities.Logging.APILogger` (used for logging exceptions in `TagsBlobBytes` setter and `TagsInstance.Commit`).
|
||||
- `System.Data` (`IDataReader`, `SqlCommand`).
|
||||
- `System.Linq` (used in `TagAwareBase` and `TagsInstance`).
|
||||
|
||||
- **External dependencies**:
|
||||
- DB layer via delegates (`TagsGetDelegate`, `TagsGetIdDelegate`, etc.) — concrete implementations must be provided by the consuming application.
|
||||
- `Utility` class (static methods `GetInt`, `GetBool`, `GetString`, `GetShort`) — assumed to be in `DTS.Common.Base` or `DTS.Common.Utilities`.
|
||||
|
||||
- **Depended upon by**:
|
||||
- Any domain class inheriting from `TagAwareBase` (e.g., `Asset`, `Event`, `Configuration` — not shown here).
|
||||
- UI or service layers that need to parse/set tags via `SetTagsFromCommaSeparatedString`, `GetTagsAsCommaSeparatedString`, etc.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`ObjectType` vs `TagType`**: The `TagAssignment` class has a property named `ObjectType`, but the interface likely expects `TagType`. This mismatch may cause confusion.
|
||||
- **`TagTypes` enum usage**: `ObjectType` in `TagAssignment` is cast from a `short` (`Utility.GetShort`), implying `TagTypes` is a `short`-backed enum. Ensure alignment with DB schema.
|
||||
- **Leading whitespace trimming only**: `SetTagsFromCommaSeparatedString` and `AddRange` trim *leading* whitespace (`TrimStart`), but not trailing. `"tag1 , tag2 "` becomes `["tag1 ", "tag2 "]` — trailing spaces remain.
|
||||
- **`TagCompatible` semantics**: Returns `true` if *any* tag matches (logical OR), not *all* tags (logical AND). This may be counterintuitive for filtering.
|
||||
- **`RemoveTags` is a stub**: The method body is empty — calling it has no effect.
|
||||
- **`TagsInstance` is not thread-safe for writes**: While `_tagsLookup` is locked during updates, `AddTag`/`MigrateTag` do *not* use a lock around the entire operation (only inside `Commit`). Concurrent calls may result in duplicate DB inserts or cache inconsistencies.
|
||||
- **`TagsBlobBytes` setter silently fails**: If `value.Length` is not a multiple of `sizeof(int)`, only the full chunks are copied; remainder is discarded and no error is raised.
|
||||
- **`GetTagTextFromIDs` filters out `null`/empty strings**: Even if `GetTagTextFromID` returns `null`, it is excluded from the result array — but this may hide missing tag IDs.
|
||||
- **`TagAssignment` constructor from `IDataReader` uses `"ObjectType"` column name**, while `Tag` uses `"TagId"` and `"Obsolete"` — ensure DB schema matches exactly.
|
||||
|
||||
None identified beyond these.
|
||||
@@ -0,0 +1,172 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/TestMetaData/TestEngineerDetailsDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/TestMetaData/CustomerDetailsDbRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/TestMetaData/LabratoryDetailsDbRecord.cs
|
||||
generated_at: "2026-04-16T02:39:45.898460+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "7adaa8e0587cfc54"
|
||||
---
|
||||
|
||||
# Documentation: Test Metadata Database Record Classes
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
These three classes—`TestEngineerDetailsDbRecord`, `CustomerDetailsDbRecord`, and `LabratoryDetailsDbRecord`—represent immutable data transfer objects (DTOs) for loading and encapsulating metadata about test engineers, customers, and laboratories from a database. They implement the `INotifyPropertyChanged` pattern via inheritance from `Base.BasePropertyChanged`, enabling data binding in UI layers, and provide constructors to initialize from an `IDataReader` (for database hydration) or from another instance of the same interface type (for cloning). Each class serves as a strongly-typed, schema-bound representation of rows in corresponding database tables, used throughout the test execution and reporting pipeline to ensure consistent metadata access.
|
||||
|
||||
---
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
All three classes share a common structural pattern. Below, each class is documented individually.
|
||||
|
||||
### `TestEngineerDetailsDbRecord`
|
||||
|
||||
- **Namespace**: `DTS.Common.Classes.TestEngineerDetails`
|
||||
- **Interface**: `ITestEngineerDetailsDbRecord`
|
||||
- **Base Class**: `Base.BasePropertyChanged`
|
||||
|
||||
#### Constructors
|
||||
- `TestEngineerDetailsDbRecord()`
|
||||
Default constructor; initializes all fields to their default values (`-1` for IDs, `""` for strings, `false` for booleans, `DateTime.MinValue` for dates).
|
||||
- `TestEngineerDetailsDbRecord(ITestEngineerDetailsDbRecord testEngineerDetailsDbRecord)`
|
||||
Copy constructor; copies all property values from the provided interface instance.
|
||||
- `TestEngineerDetailsDbRecord(IDataReader reader)`
|
||||
Database constructor; reads values from an `IDataReader` using `Utility.GetString`, `Utility.GetInt`, `Utility.GetDateTime`, and `Utility.GetBool` helper methods.
|
||||
|
||||
#### Properties
|
||||
| Property | Type | Attributes | Description |
|
||||
|---------|------|------------|-------------|
|
||||
| `TestEngineerId` | `int` | `[Browsable(false)]`, `[ReadOnly(true)]` | Primary key identifier for the test engineer. Default: `-1`. |
|
||||
| `Name` | `string` | `[Browsable(false)]`, `[ReadOnly(true)]` | Internal/system name (e.g., login or DB key). Default: `""`. |
|
||||
| `TestEngineerName` | `string` | `[DisplayResource("TestEngineerName")]` | Display-friendly name (e.g., full name). Default: `"NOVALUE"`. |
|
||||
| `TestEngineerPhone` | `string` | `[DisplayResource("TestEngineerPhone")]` | Contact phone number. Default: `"NOVALUE"`. |
|
||||
| `TestEngineerFax` | `string` | `[DisplayResource("TestEngineerFax")]` | Contact fax number. Default: `"NOVALUE"`. |
|
||||
| `TestEngineerEmail` | `string` | `[DisplayResource("TestEngineerEmail")]` | Contact email address. Default: `"NOVALUE"`. |
|
||||
| `LocalOnly` | `bool` | `[Browsable(false)]`, `[ReadOnly(true)]` | Indicates if record is local-only (not synchronized). Default: `false`. |
|
||||
| `LastModified` | `DateTime` | `[Browsable(false)]`, `[ReadOnly(true)]` | Timestamp of last modification. Default: `DateTime.MinValue`. |
|
||||
| `LastModifiedBy` | `string` | `[Browsable(false)]`, `[ReadOnly(true)]` | User who last modified the record. Default: `""`. |
|
||||
| `Version` | `int` | `[Browsable(false)]`, `[ReadOnly(true)]` | Concurrency/version token. Default: `-1`. |
|
||||
|
||||
#### Methods
|
||||
- `bool IsInvalidBlank()`
|
||||
Returns `true` if `Name` is `null`, empty, or whitespace; otherwise `false`.
|
||||
|
||||
---
|
||||
|
||||
### `CustomerDetailsDbRecord`
|
||||
|
||||
- **Namespace**: `DTS.Common.Classes.CustomerDetails`
|
||||
- **Interface**: `ICustomerDetailsDbRecord`
|
||||
- **Base Class**: `Base.BasePropertyChanged`
|
||||
|
||||
#### Constructors
|
||||
- `CustomerDetailsDbRecord()`
|
||||
Default constructor.
|
||||
- `CustomerDetailsDbRecord(ICustomerDetailsDbRecord customerDetailsDbRecord)`
|
||||
Copy constructor.
|
||||
- `CustomerDetailsDbRecord(IDataReader reader)`
|
||||
Database constructor.
|
||||
|
||||
#### Properties
|
||||
| Property | Type | Attributes | Description |
|
||||
|---------|------|------------|-------------|
|
||||
| `CustomerId` | `int` | `[Browsable(false)]`, `[ReadOnly(true)]` | Primary key identifier. Default: `-1`. |
|
||||
| `Name` | `string` | `[Browsable(false)]`, `[ReadOnly(true)]` | Internal/system name. Default: `""`. |
|
||||
| `CustomerName` | `string` | `[DisplayResource("CustomerName")]` | Display name. Default: `""`. |
|
||||
| `CustomerTestRefNumber` | `string` | `[DisplayResource("CustomerTestRefNumber")]` | Customer-provided test reference number. Default: `""`. |
|
||||
| `ProjectRefNumber` | `string` | `[DisplayResource("ProjectRefNumber")]` | Project reference number. Default: `"NOVALUE"`. |
|
||||
| `CustomerOrderNumber` | `string` | `[DisplayResource("CustomerOrderNumber")]` | Customer order number. Default: `"NOVALUE"`. |
|
||||
| `CustomerCostUnit` | `string` | `[DisplayResource("CustomerCostUnit")]` | Cost center/unit. Default: `"NOVALUE"`. |
|
||||
| `LocalOnly` | `bool` | `[Browsable(false)]`, `[ReadOnly(true)]` | Local-only flag. Default: `false`. |
|
||||
| `LastModified` | `DateTime` | `[Browsable(false)]`, `[ReadOnly(true)]` | Last modification timestamp. Default: `DateTime.MinValue`. |
|
||||
| `LastModifiedBy` | `string` | `[Browsable(false)]`, `[ReadOnly(true)]` | Last modifier. Default: `""`. |
|
||||
| `Version` | `int` | `[Browsable(false)]`, `[ReadOnly(true)]` | Version token. Default: `-1`. |
|
||||
|
||||
#### Methods
|
||||
- `bool IsInvalidBlank()`
|
||||
Returns `true` if `Name` is `null`, empty, or whitespace.
|
||||
|
||||
---
|
||||
|
||||
### `LabratoryDetailsDbRecord`
|
||||
|
||||
- **Namespace**: `DTS.Common.Classes.LabratoryDetails`
|
||||
- **Interface**: `ILabratoryDetailsDbRecord`
|
||||
- **Base Class**: `Base.BasePropertyChanged`
|
||||
|
||||
#### Constructors
|
||||
- `LabratoryDetailsDbRecord()`
|
||||
Default constructor.
|
||||
- `LabratoryDetailsDbRecord(ILabratoryDetailsDbRecord labratoryDetailsDbRecord)`
|
||||
Copy constructor.
|
||||
- `LabratoryDetailsDbRecord(IDataReader reader)`
|
||||
Database constructor.
|
||||
|
||||
#### Properties
|
||||
| Property | Type | Attributes | Description |
|
||||
|---------|------|------------|-------------|
|
||||
| `LabratoryId` | `int` | `[Browsable(false)]`, `[ReadOnly(true)]` | Primary key identifier. Default: `-1`. |
|
||||
| `Name` | `string` | `[Browsable(false)]`, `[ReadOnly(true)]` | Internal/system name. Default: `""`. |
|
||||
| `LabratoryName` | `string` | `[DisplayResource("LabratoryName")]` | Display name of lab. Default: `""`. |
|
||||
| `LabratoryContactName` | `string` | `[DisplayResource("LabratoryContactName")]` | Primary contact name. Default: `""`. |
|
||||
| `LabratoryContactPhone` | `string` | `[DisplayResource("LabratoryContactPhone")]` | Contact phone. Default: `"NOVALUE"`. |
|
||||
| `LabratoryContactFax` | `string` | `[DisplayResource("LabratoryContactFax")]` | Contact fax. Default: `"NOVALUE"`. |
|
||||
| `LabratoryContactEmail` | `string` | `[DisplayResource("LabratoryContactEmail")]` | Contact email. Default: `"NOVALUE"`. |
|
||||
| `LabratoryTestRefNumber` | `string` | `[DisplayResource("LabratoryTestRefNumber")]` | Lab-provided test reference. Default: `""`. |
|
||||
| `LabratoryProjectRefNumber` | `string` | `[DisplayResource("LabratoryProjectRefNumber")]` | Lab project reference. Default: `""`. |
|
||||
| `LocalOnly` | `bool` | `[Browsable(false)]`, `[ReadOnly(true)]` | Local-only flag. Default: `false`. |
|
||||
| `LastModified` | `DateTime` | `[Browsable(false)]`, `[ReadOnly(true)]` | Last modification timestamp. Default: `DateTime.MinValue`. |
|
||||
| `LastModifiedBy` | `string` | `[Browsable(false)]`, `[ReadOnly(true)]` | Last modifier. Default: `""`. |
|
||||
| `Version` | `int` | `[Browsable(false)]`, `[ReadOnly(true)]` | Version token. Default: `-1`. |
|
||||
|
||||
#### Methods
|
||||
- `bool IsInvalidBlank()`
|
||||
Returns `true` if `Name` is `null`, empty, or whitespace.
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`Name` is required**: All classes enforce that `Name` must be non-null and non-whitespace for a record to be considered valid. This is validated by the `IsInvalidBlank()` method.
|
||||
- **Default sentinel values**: String properties not marked with `[DisplayResource]` default to `""` (e.g., `Name`, `LastModifiedBy`). String properties *with* `[DisplayResource]` default to `"NOVALUE"` (except `CustomerName` and `CustomerTestRefNumber`, which default to `""`).
|
||||
- **Numeric defaults**: `*Id` and `Version` fields default to `-1`; `LastModified` defaults to `DateTime.MinValue`.
|
||||
- **Read-only metadata fields**: Properties `*Id`, `Name`, `LocalOnly`, `LastModified`, `LastModifiedBy`, and `Version` are marked `[ReadOnly(true)]` and `[Browsable(false)]`, indicating they are not intended for user editing in UI contexts.
|
||||
- **Property change notification**: All properties use `SetProperty`, implying `INotifyPropertyChanged` events will fire on changes (via base class `Base.BasePropertyChanged`).
|
||||
|
||||
---
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Internal Dependencies
|
||||
- `DTS.Common.Base.Classes.BasePropertyChanged` — Base class providing `SetProperty` and `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` — Required for `IDataReader` constructor.
|
||||
- `System.ComponentModel` — Required for `[Browsable]`, `[ReadOnly]`, `[DisplayResource]` attributes.
|
||||
|
||||
### External Dependencies
|
||||
- `Utility` class (static/internal) — Provides helper methods: `GetString`, `GetInt`, `GetDateTime`, `GetBool`. These are assumed to be safe null-handling wrappers around `IDataReader` accessors.
|
||||
|
||||
### Inferred Usage
|
||||
- These classes are likely consumed by:
|
||||
- Data access layers (DALs) that populate them from database queries.
|
||||
- UI layers (e.g., WPF) via data binding (justified by `INotifyPropertyChanged` and `[DisplayResource]` attributes).
|
||||
- Serialization layers (e.g., XML via `XmlSerializer`, inferred from `using System.Xml.Serialization`).
|
||||
|
||||
---
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **Typo in namespace/class name**: The namespace and class `LabratoryDetailsDbRecord` uses the misspelled "Labratory" (should be "Laboratory"). This is consistent across files and may be intentional legacy, but is a potential source of confusion.
|
||||
- **Inconsistent default values for `[DisplayResource]` strings**:
|
||||
- `CustomerName` and `CustomerTestRefNumber` default to `""`, while other `[DisplayResource]` fields default to `"NOVALUE"`. This inconsistency may indicate incomplete refactoring or differing business semantics.
|
||||
- **`IsInvalidBlank()` only checks `Name`**: Validation is minimal and only considers the internal `Name` field. Other required fields (e.g., `TestEngineerName` for engineers) are not validated, potentially allowing partially populated records.
|
||||
- **`[DisplayResource]` attribute behavior unknown**: The `[DisplayResource("...")]` attribute is used, but its implementation and how it interacts with localization/resource loading are not visible here. Its effect is assumed to be runtime (e.g., via a custom `TypeConverter` or binding converter), but this is not documented in the source.
|
||||
- **No immutability enforcement**: Despite being used as DTOs, properties have public setters and are not immutable. The `Copy` constructor does not prevent mutation of the source object.
|
||||
- **No null-safety guarantees in `Utility` methods**: The behavior of `Utility.GetString`, `Utility.GetBool`, etc., on `DBNull` or missing columns is not visible. Assumed safe (e.g., returning defaults), but not guaranteed by this code.
|
||||
|
||||
None identified beyond the above.
|
||||
@@ -0,0 +1,320 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/SimpleHardware.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/TestSetupHelper.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/ROIPeriodChannelRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/ExtraProperties.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/TestSetupHardwareRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/TestSetupROIsRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/CalculatedChannelRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/ISFFile.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/GraphRecord.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/RegionOfInterest.cs
|
||||
- Common/DTS.CommonCore/Classes/TestSetups/ISFSensorRecord.cs
|
||||
generated_at: "2026-04-16T02:42:02.216397+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "b14dada51ccb8b95"
|
||||
---
|
||||
|
||||
# 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 record classes that model database entities (e.g., hardware assignments, ROIs, calculated channels, graphs) and supporting types for handling ISF sensor file I/O and test setup naming. The module serves as the data layer abstraction for test setup management, enabling persistence, serialization, and UI binding for test configuration data.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `SimpleHardware`
|
||||
- **`SimpleHardware(string serialNumber, string parentDAS, int dasId, int dasType)`**
|
||||
Constructor initializing a tuple-based record for hardware metadata.
|
||||
- **`SerialNumber` (string)**
|
||||
Gets the hardware serial number (from `Item1`).
|
||||
- **`ParentDAS` (string)**
|
||||
Gets the parent DAS identifier (from `Item2`).
|
||||
- **`DASId` (int)**
|
||||
Gets the DAS identifier (from `Item3`).
|
||||
- **`DASType` (int)**
|
||||
Gets the DAS type identifier (from `Item4`).
|
||||
|
||||
### `TestSetupHelper`
|
||||
- **`ClearTestSetupNames()`**
|
||||
Clears the internal dictionary mapping IDs to test setup names.
|
||||
- **`SetTestSetupName(int id, string name)`**
|
||||
Sets or updates the name for a given test setup ID.
|
||||
- **`GetTestSetupName(int Id)` → string**
|
||||
Returns the name associated with the given ID, or `string.Empty` if not found.
|
||||
|
||||
### `ROIPeriodChannelRecord`
|
||||
- **`TestSetupROIId` (int)**
|
||||
Gets/sets the foreign key to `TestSetupROIs.TestSetupROIId`.
|
||||
- **`ChannelName` (string)**
|
||||
Gets/sets the channel name assigned to this ROI period.
|
||||
- **`ROIPeriodChannelRecord(IDataReader reader)`**
|
||||
Constructor populating fields from a database reader using `Utility.GetInt`/`Utility.GetString`.
|
||||
|
||||
### `ExtraProperty`
|
||||
- **`Key` (string)**
|
||||
Gets/sets the property key; raises `PropertyChanged` on change.
|
||||
- **`Value` (string)**
|
||||
Gets/sets the property value; raises `PropertyChanged` on change.
|
||||
- **`PasteCommand` (ICommand)**
|
||||
Gets/sets the paste command; raises `PropertyChanged` on change.
|
||||
- **`ItemStatus` (UIItemStatus)**
|
||||
Gets/sets the UI item status; raises `PropertyChanged` on change.
|
||||
- **`ExtraProperty(IExtraProperty iep)` / `ExtraProperty(string key, string value)` / `ExtraProperty()`**
|
||||
Constructors for copying, initializing with key/value, or default initialization.
|
||||
|
||||
### `TestSetupHardwareRecord`
|
||||
- **`DASId` (int)**
|
||||
Gets/sets the DAS identifier.
|
||||
- **`TestSetupId` (int)**
|
||||
Gets/sets the test setup identifier.
|
||||
- **`AddDAS` (bool)**
|
||||
Gets/sets whether to add (true) or remove (false) the DAS.
|
||||
- **`SamplesPerSecond` (int)**
|
||||
Gets/sets the sampling rate.
|
||||
- **`IsClockMaster` (bool)**
|
||||
Gets/sets whether this DAS is the clock master.
|
||||
- **`PTPDomainId` (byte)**
|
||||
Gets/sets the PTP domain ID.
|
||||
- **`AntiAliasFilterRate` (int)**
|
||||
Gets/sets the anti-alias filter rate.
|
||||
- **`TestSetupHardwareRecord()`**
|
||||
Default constructor.
|
||||
- **`TestSetupHardwareRecord(IDataReader reader)`**
|
||||
Constructor populating fields from a database reader.
|
||||
- **`TestSetupHardwareRecord(ITestSetupHardwareRecord copy)`**
|
||||
Copy constructor.
|
||||
|
||||
### `TestSetupROIsRecord`
|
||||
- **`TestSetupROIId` (int)**
|
||||
Gets/sets the primary key.
|
||||
- **`TestSetupId` (int)**
|
||||
Gets/sets the foreign key to `TestSetups`.
|
||||
- **`Suffix` (string)**
|
||||
Gets/sets the ROI period suffix (e.g., `"_ROI Period 1"`).
|
||||
- **`ROIStart` (double)**
|
||||
Gets/sets the start time of the ROI period.
|
||||
- **`ROIEnd` (double)**
|
||||
Gets/sets the end time of the ROI period.
|
||||
- **`IsEnabled` (bool)**
|
||||
Gets/sets whether the ROI period is enabled.
|
||||
- **`IsDefault` (bool)**
|
||||
Gets/sets whether this is the default ROI period.
|
||||
- **`TestSetupROIsRecord(IDataReader reader)`**
|
||||
Constructor populating fields from a database reader.
|
||||
|
||||
### `CalculatedChannelRecord`
|
||||
- **`Name` (string)**
|
||||
Gets/sets the calculated channel name.
|
||||
- **`TestSetupName` (string)**
|
||||
Gets/sets the associated test setup name.
|
||||
- **`Id` (int)**
|
||||
Gets/sets the database record ID.
|
||||
- **`Operation` (Operations)**
|
||||
Gets/sets the operation to apply (e.g., `SUM`).
|
||||
- **`CalculatedValueCode` (string)**
|
||||
Gets/sets the ISO/user code associated with the calculated value.
|
||||
- **`InputChannelIds` (string[])**
|
||||
Gets/sets the array of input channel IDs (CSV-separated in DB).
|
||||
- **`CFCForInputChannels` (string)**
|
||||
Gets/sets the CFC to apply to input channels.
|
||||
- **`ChannelFilterClassForOutput` (string)**
|
||||
Gets/sets the CFC to apply to the output.
|
||||
- **`TestSetupId` (int)**
|
||||
Gets/sets the test setup database ID.
|
||||
- **`ViewInRealtime` (bool)**
|
||||
Gets/sets whether the channel is viewable in real-time.
|
||||
- **`ClipLength` (int)**
|
||||
Gets/sets the clip length for calculations (e.g., max over clip).
|
||||
- **`CalculatedChannelRecord()` / `CalculatedChannelRecord(ICalculatedChannelRecord record)` / `CalculatedChannelRecord(IDataReader reader)`**
|
||||
Constructors for default, copy, and database population.
|
||||
|
||||
### `ISFFile`
|
||||
- **`HeaderLine1` (char[])**
|
||||
Gets/sets the first header line (80 chars); padding with spaces.
|
||||
- **`TestSetupName` (char[8])**
|
||||
Gets/sets the test setup name at offset 7.
|
||||
- **`NumberOfRecords` (char[5])**
|
||||
Gets/sets the number of records at offset 15.
|
||||
- **`TestType` (char[22])**
|
||||
Gets/sets the test type at offset 20.
|
||||
- **`TestDivision` (char[30])**
|
||||
Gets/sets the test division at offset 42.
|
||||
- **`TCFile` (char[8])**
|
||||
Gets/sets the TC file name (without extension) at offset 72.
|
||||
- **`Records` (IISFSensorRecord[])**
|
||||
Gets the array of sensor records.
|
||||
- **`AddRecord(IISFSensorRecord record)`**
|
||||
Adds a record, sets its data channel number, and updates `NumberOfRecords`.
|
||||
- **`WriteToFile(string pathToFile)`**
|
||||
Writes the ISF file to disk (HeaderLine1–3 + all records).
|
||||
- **`AddSensors(ISensorData[] sensors)`**
|
||||
Converts `ISensorData` to `ISFSensorRecord`s and adds them.
|
||||
- **`ISFFile()`**
|
||||
Constructor initializing header with spaces.
|
||||
|
||||
### `GraphRecord`
|
||||
- **`GraphId` (int)**
|
||||
Gets/sets the graph database ID.
|
||||
- **`TestSetupId` (int)**
|
||||
Gets/sets the test setup database ID.
|
||||
- **`GraphName` (string)**
|
||||
Gets/sets the graph name (max 50 chars).
|
||||
- **`GraphDescription` (string)**
|
||||
Gets/sets the graph description (max 50 chars).
|
||||
- **`ChannelsString` (string)**
|
||||
Gets/sets the channel list (max 2048 chars).
|
||||
- **`UseDomainMin` / `DomainMin` (bool/double)**
|
||||
Gets/sets domain axis min constraints.
|
||||
- **`UseDomainMax` / `DomainMax` (bool/double)**
|
||||
Gets/sets domain axis max constraints.
|
||||
- **`UseRangeMin` / `RangeMin` (bool/double)**
|
||||
Gets/sets range axis min constraints.
|
||||
- **`UseRangeMax` / `RangeMax` (bool/double)**
|
||||
Gets/sets range axis max constraints.
|
||||
- **`ThresholdsString` (string)**
|
||||
Gets/sets threshold/line definitions (max 2048 chars).
|
||||
- **`LocalOnly` (bool)**
|
||||
Gets/sets whether to sync with central DB (deprecated).
|
||||
- **`GraphRecord()` / `GraphRecord(IGraphRecord copy)` / `GraphRecord(IDataReader reader)`**
|
||||
Constructors.
|
||||
|
||||
### `RegionOfInterest`
|
||||
- **`Deserializing` (static bool)**
|
||||
Flag to suppress notifications during deserialization.
|
||||
- **`Suffix` (string)**
|
||||
Gets/sets the ROI suffix (ensures leading underscore).
|
||||
- **`Start` (double)**
|
||||
Gets/sets ROI start time; clamps if ≥ `End`.
|
||||
- **`End` (double)**
|
||||
Gets/sets ROI end time; clamps if ≤ `Start`.
|
||||
- **`IsEnabled` (bool)**
|
||||
Gets/sets whether ROI is active.
|
||||
- **`IsDefault` (bool)**
|
||||
Gets/sets whether this is the default ROI.
|
||||
- **`ChannelNames` (string[])**
|
||||
Gets/sets channel names; raises `RegionOfInterestChangedEvent` on change (unless `Deserializing`).
|
||||
- **`RegionOfInterest(string suffix, bool isDefault, double start, double end)`**
|
||||
Constructor with parameters.
|
||||
- **`ResetSuffix()`**
|
||||
Clears the suffix.
|
||||
- **`SetChannelNamesNoNotify(string[] names)`**
|
||||
Sets channel names without raising notifications.
|
||||
- **`GetAnalogChanName(...)` / `GetChanName(...)` / `RemoveParentDASName(...)` / `RemoveAssignedByIDFromHardwareString(...)`**
|
||||
Static utility methods for channel name formatting and parsing.
|
||||
|
||||
### `ISFSensorRecord`
|
||||
- **`Record1`–`Record4` (char[80] each)**
|
||||
Raw ISF record buffers.
|
||||
- **`Tag` (char[2])**
|
||||
Sensor tag at offset 75 of Record1.
|
||||
- **`DataChannelNumber` (char[5])**
|
||||
Data channel number at offset 7 of Record1.
|
||||
- **`UserIdSensorIDIsNotSpecified` (bool)**
|
||||
Gets/sets bit at offset 15 of Record1.
|
||||
- **`CapacityCharacters` / `SetCapacity(...)` / `GetCapacity()`**
|
||||
Capacity field (offset 19) with conversion helpers.
|
||||
- **`SerialNumber` (char[12])**
|
||||
Serial number at offset 30 of Record1.
|
||||
- **`Sensitivity` / `SetSensitivity(...)` / `GetSensitivity()`**
|
||||
Sensitivity field (offset 42) with conversion helpers.
|
||||
- **`BridgeResistance` / `SetBridgeResistance(...)`**
|
||||
Bridge resistance field (offset 53).
|
||||
- **`EngineeringUnits` (char[12])**
|
||||
Engineering units at offset 7 of Record2.
|
||||
- **`C1` / `SetC1(...)` / `GetC1()`**
|
||||
Calibration coefficient C1 (offset 20 of Record2).
|
||||
- **`EID` (char[17])**
|
||||
EID at offset 31 of Record2.
|
||||
- **`TOMConfigurationName` (char[8])**
|
||||
TOM config name (default `"STANDARD"`).
|
||||
- **`FireDelay` / `SetFireDelay(...)`**
|
||||
Fire delay (offset 55 of Record2, TOM-only).
|
||||
- **`CommentPart1`–`CommentPart3` / `SetSensorComment(...)`**
|
||||
Comment fields across Records 3 & 4.
|
||||
- **`SensorType` (char[20])**
|
||||
Sensor type (offset 30 of Record4).
|
||||
- **`C2` / `SetC2(...)` / `C3` / `SetC3(...)`**
|
||||
Calibration coefficients C2/C3 (offsets 50/61 of Record4).
|
||||
- **`Write(BinaryWriter writer)`**
|
||||
Writes all four records to stream.
|
||||
- **`ISFSensorRecord()`**
|
||||
Constructor initializing all records with spaces.
|
||||
- **`SetSensor(ISensorData sensor)`**
|
||||
Populates record fields from `ISensorData`.
|
||||
|
||||
### Extension Methods (`ArrayExtensions`)
|
||||
- **`Fill<T>(this T[] source, T with)`**
|
||||
Fills entire array with value.
|
||||
- **`SubFill<T>(this T[] source, T with, int startIndex, int finalIndex)`**
|
||||
Fills from `startIndex` to `finalIndex` (exclusive).
|
||||
- **`SetValues<T>(this T[] source, T[] with, int startIndex, int length, T pad)`**
|
||||
Copies `with` into `source` starting at `startIndex`, padding remainder with `pad`.
|
||||
- **`GetValues<T>(this T[] source, int startIndex, int length)` → T[]**
|
||||
Returns a copy of `length` elements starting at `startIndex`.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`SimpleHardware`**: Inherits from `Tuple<string, string, int, int>`; fields are immutable after construction.
|
||||
- **`TestSetupROIsRecord.TestSetupId`**: In the constructor, the database column `"TestSetupROIId"` is used for *both* `TestSetupROIId` and `TestSetupId`. This is likely a bug (see *Gotchas*).
|
||||
- **`RegionOfInterest.Start` and `End`**: `Start` is clamped to be `< End`, and `End` is clamped to be `> Start` (with a 0.01 minimum gap).
|
||||
- **`RegionOfInterest.Suffix`**: Automatically prepends `"_"` if missing and not whitespace-only; ensures format `"_<name>"`.
|
||||
- **`ISFFile.NumberOfRecords`**: Updated to `Records.Length * 4` on each `AddRecord` call (4 physical records per logical record).
|
||||
- **`ISFSensorRecord.TOMConfigurationName`**: Defaults to `"STANDARD"` in constructor.
|
||||
- **`CalculatedChannelRecord.InputChannelIds`**: Stored as `string[]`; in DB, stored as CSV using `CultureInfo.InvariantCulture.ListSeparator`.
|
||||
- **`GraphRecord.ChannelsString` / `ThresholdsString`**: Max length enforced via `[MaxLength]` attribute (50 for name/description, 2048 for strings).
|
||||
- **`ExtraProperty`**: Implements `INotifyPropertyChanged`; all property setters raise `PropertyChanged`.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Internal Dependencies
|
||||
- **`DTS.Common.Base`**: Base classes (`BasePropertyChanged`) used by `ROIPeriodChannelRecord`, `TestSetupROIsRecord`, `CalculatedChannelRecord`, `GraphRecord`.
|
||||
- **`DTS.Common.Interface.*`**: Interfaces implemented by record classes (e.g., `ITestSetupHardwareRecord`, `IROIPeriodChannelRecord`, `ICalculatedChannelRecord`, `IGraphRecord`, `IISFSensorRecord`, `IExtraProperty`, `IRegionOfInterest`).
|
||||
- **`DTS.Common.Enums`**: `Operations` enum used by `CalculatedChannelRecord`.
|
||||
- **`DTS.Common.Enums.Sensors`**: `SensorConstants` used by `RegionOfInterest`.
|
||||
- **`DTS.Common.Events.RegionOfInterest`**: `IEventAggregator`, `RegionOfInterestChangedEvent` used for ROI change notifications.
|
||||
- **`Microsoft.Practices.Prism.Events`**: Prism event aggregator for ROI notifications.
|
||||
- **`Microsoft.Practices.ServiceLocation`**: `ServiceLocator` used in `RegionOfInterest.NotifyChanged`.
|
||||
- **`System.Data`**: `IDataReader` used in record constructors.
|
||||
- **`System.ComponentModel.DataAnnotations`**: `[MaxLength]` attributes on `GraphRecord`.
|
||||
- **`DTS.Common.Base`**: `Utility` class for safe DB value extraction (`GetInt`, `GetString`, `GetDouble`, `GetBool`, `GetStringArray`).
|
||||
|
||||
### External Dependencies
|
||||
- **`System`**: Core types (`string`, `Action`, `EventHandler`, etc.).
|
||||
- **`System.IO`**: `FileStream`, `BinaryWriter`, `FileMode`, `File.Exists` used in `ISFFile.WriteToFile`.
|
||||
- **`System.Linq`**: Used in `CalculatedChannelRecord` copy constructor (`Any()`).
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`TestSetupROIsRecord` constructor bug**:
|
||||
`TestSetupId = Utility.GetInt(reader, "TestSetupROIId");`
|
||||
Should likely be `"TestSetupId"` instead of `"TestSetupROIId"` (same as `TestSetupROIId`). This will cause incorrect `TestSetupId` values.
|
||||
|
||||
- **`ISFFile.NumberOfRecords` semantics**:
|
||||
`NumberOfRecords` is set to `Records.Length * 4`, implying it counts *physical* records (4 per logical sensor), not logical sensors. This may be non-intuitive.
|
||||
|
||||
- **`RegionOfInterest.Deserializing` static flag**:
|
||||
A global flag to suppress notifications during deserialization. This is fragile in multi-threaded or concurrent deserialization scenarios and may cause missed notifications.
|
||||
|
||||
- **`RegionOfInterest.GetAnalogChanName` logic**:
|
||||
The condition `!hardwareChannelName.StartsWith($"[{startOfHardware}")` is unusual and may be error-prone if `startOfHardware` changes or is not consistently formatted.
|
||||
|
||||
- **`ISFSensorRecord.GetCapacity()` / `GetSensitivity()` etc.**:
|
||||
Use `CapacityCharacters.ToString()` (which yields a `string` representation of the `char[]` array, *not* the string content). This is likely a bug; should use `new string(CapacityCharacters).Trim()`.
|
||||
|
||||
- **`ISFFile.HeaderLine1` setter**:
|
||||
Uses `Array.Copy(value, _HeaderLine1, Math.Min(...))` which may truncate or misalign if `value.Length` ≠ 80. Padding is only applied *before* copy via `Fill(' ')`, but copy may overwrite padding.
|
||||
|
||||
- **`CalculatedChannelRecord.InputChannelIds` copy constructor**:
|
||||
Uses `new string[record.InputChannelIds.Length]; record.InputChannelIds.CopyTo(_inputChannelIds, 0);` — but `_inputChannelIds` is initialized to `new[] { "-1" }`. This is safe, but the initial value is overwritten.
|
||||
|
||||
- **`ExtraProperty` paste command**:
|
||||
`_pasteCommand` is never initialized; consumers must set it explicitly.
|
||||
|
||||
- **`GraphRecord.LocalOnly`**:
|
||||
Marked as `[deprecated]` but still present in data model and copy constructor.
|
||||
|
||||
- **`RegionOfInterest` channel name formatting**:
|
||||
Methods like `GetChanName` and `RemoveParentDASName` assume specific formats (e.g
|
||||
@@ -0,0 +1,193 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/WinApi/WindowsAPIHelpers.cs
|
||||
generated_at: "2026-04-16T02:41:05.548844+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "74033c59308d77b1"
|
||||
---
|
||||
|
||||
# WinApi
|
||||
|
||||
## Documentation: `WindowsAPIHelpers.cs`
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
This module provides low-level Windows API interop helpers for managing window placement and sizing behavior, specifically to ensure that maximized windows align with the *work area* (i.e., excluding taskbar, docked toolbars) of the appropriate monitor in multi-monitor setups. It defines P/Invoke signatures and supporting structures (`POINT`, `RECT`, `MINMAXINFO`, `MONITORINFO`, `WINDOWPOS`) and exposes a helper method `GetMinMaxInfo` that adjusts the `ptMaxSize` and `ptMaxPosition` fields of a `MINMAXINFO` structure during a `WM_GETMINMAXINFO` message. This ensures windows maximize correctly to the visible screen area of the monitor containing the window, rather than the primary monitor’s full screen bounds.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### Structs & Classes
|
||||
|
||||
- **`POINT`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct POINT { public int x; public int y; public POINT(int x, int y); }
|
||||
```
|
||||
Represents a point in screen coordinates. Used as a field in `MINMAXINFO` and elsewhere.
|
||||
|
||||
- **`MINMAXINFO`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MINMAXINFO
|
||||
{
|
||||
public POINT ptReserved;
|
||||
public POINT ptMaxSize;
|
||||
public POINT ptMaxPosition;
|
||||
public POINT ptMinTrackSize;
|
||||
public POINT ptMaxTrackSize;
|
||||
}
|
||||
```
|
||||
Used in `WM_GETMINMAXINFO` to specify minimum/maximum tracking sizes and maximized window geometry. The `ptMaxSize` and `ptMaxPosition` fields are modified 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;
|
||||
}
|
||||
```
|
||||
Container for monitor-specific information. `cbSize` is auto-initialized to the correct size. `rcMonitor` holds the full monitor bounds; `rcWork` holds the work area (usable screen space).
|
||||
|
||||
- **`RECT`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 0)]
|
||||
public struct RECT
|
||||
{
|
||||
public int left, top, right, bottom;
|
||||
public static readonly RECT Empty;
|
||||
public int Width => Math.Abs(right - left);
|
||||
public int Height => bottom - top;
|
||||
public bool IsEmpty => left >= right || top >= bottom;
|
||||
// ... constructors, equality, operators ...
|
||||
}
|
||||
```
|
||||
Represents a rectangle in screen coordinates. Includes computed properties (`Width`, `Height`, `IsEmpty`) and value-based equality (`==`, `!=`, `Equals`, `GetHashCode`). Note: `Height` is computed as `bottom - top` (not `Math.Abs`), so negative heights are possible if `bottom < top`.
|
||||
|
||||
- **`WINDOWPOS`**
|
||||
```csharp
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct WINDOWPOS
|
||||
{
|
||||
public IntPtr hwnd;
|
||||
public IntPtr hwndInsertAfter;
|
||||
public int x, y, cx, cy;
|
||||
public int flags;
|
||||
}
|
||||
```
|
||||
Mirrors the Win32 `WINDOWPOS` structure used in `WM_WINDOWPOSCHANGING`/`WM_WINDOWPOSCHANGED`.
|
||||
|
||||
#### Enums
|
||||
|
||||
- **`WM`**
|
||||
```csharp
|
||||
public enum WM
|
||||
{
|
||||
WINDOWMAX = 0x0024,
|
||||
WINDOWPOSCHANGING = 0x0046
|
||||
}
|
||||
```
|
||||
Subset of Windows message constants. *Note:* `WINDOWMAX` is likely a typo/misnomer for `WM_WINDOWMAXIMIZED` (which does not exist); standard `WM_SYSCOMMAND` with `SC_MAXIMIZE` is more common. `WINDOWPOSCHANGING` is correctly `WM_WINDOWPOSCHANGING`.
|
||||
|
||||
- **`SWP`**
|
||||
```csharp
|
||||
public enum SWP
|
||||
{
|
||||
NOMOVE = 0x0002
|
||||
}
|
||||
```
|
||||
Subset of `SetWindowPos` flags. `NOMOVE` preserves current position when resizing.
|
||||
|
||||
#### Methods
|
||||
|
||||
- **`GetMinMaxInfo(IntPtr hwnd, IntPtr lParam)`**
|
||||
```csharp
|
||||
public static void GetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
|
||||
```
|
||||
Reads a `MINMAXINFO` structure from `lParam`, queries the monitor containing `hwnd`, retrieves its work area (`rcWork`) and full monitor area (`rcMonitor`), then updates `mmi.ptMaxPosition` and `mmi.ptMaxSize` to align the maximized window with the work area of the *current* monitor. Writes the modified structure back to `lParam`. This is intended to be called in response to `WM_GETMINMAXINFO` (0x0024).
|
||||
|
||||
- **`GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi)`**
|
||||
```csharp
|
||||
[DllImport("user32")]
|
||||
public static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
|
||||
```
|
||||
P/Invoke wrapper for `GetMonitorInfoW`. Fills `lpmi` with monitor data. Caller must set `lpmi.cbSize` (handled by `MONITORINFO`’s field initializer).
|
||||
|
||||
- **`MonitorFromWindow(IntPtr handle, int flags)`**
|
||||
```csharp
|
||||
[DllImport("User32")]
|
||||
public static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
|
||||
```
|
||||
P/Invoke wrapper for `MonitorFromWindow`. Returns `IntPtr.Zero` on failure. Used with `MONITOR_DEFAULTTONEAREST` (`0x00000002`).
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- **`MONITORINFO.cbSize` must be set correctly before calling `GetMonitorInfo`**:
|
||||
The `MONITORINFO` class initializes `cbSize` to `Marshal.SizeOf(typeof(MONITORINFO))` in its field initializer, ensuring correctness for P/Invoke.
|
||||
|
||||
- **`RECT` dimensions assume left ≤ right and top ≤ bottom**:
|
||||
`Width` uses `Math.Abs(right - left)`, but `Height` does *not* (`bottom - top`). If `bottom < top`, `Height` will be negative. No validation enforces non-negative dimensions.
|
||||
|
||||
- **`GetMinMaxInfo` modifies `ptMaxSize` and `ptMaxPosition` only**:
|
||||
Other `MINMAXINFO` fields (`ptReserved`, `ptMinTrackSize`, `ptMaxTrackSize`) are preserved as-is.
|
||||
|
||||
- **Monitor query uses `MONITOR_DEFAULTTONEAREST`**:
|
||||
If `hwnd` is invalid or no monitor contains it, `MonitorFromWindow` returns `IntPtr.Zero`, and `GetMinMaxInfo` skips modification (no crash, but no adjustment either).
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
- **Runtime Dependencies**:
|
||||
- `System.Runtime.InteropServices` (for `StructLayout`, `Marshal`, `DllImport`)
|
||||
- `System.Windows` (though no WPF types are used in this file—likely a legacy/unused reference)
|
||||
- Win32 `user32.dll` (for `GetMonitorInfo`, `MonitorFromWindow`)
|
||||
|
||||
- **Consumers (inferred)**:
|
||||
This module is designed to be used by code handling `WM_GETMINMAXINFO` (e.g., in a WPF/WinForms window procedure). The method `GetMinMaxInfo` is called with the window handle and `lParam` from the message. No other direct dependencies are visible in the source.
|
||||
|
||||
- **Missing Dependencies**:
|
||||
- `RECT` is used but not defined in this file—*this is a contradiction*. The source defines `RECT` here, but the `RECT` used in `MONITORINFO` is initialized as `new RECT()`. This implies `RECT` must be defined *here* (and it is), so no external dependency is needed.
|
||||
- No `using` for `System.Drawing` or other types—`RECT` is self-contained.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **`RECT.Height` is not absolute**:
|
||||
`Height => bottom - top` (not `Math.Abs`). If `bottom < top`, `Height` is negative. This may cause unexpected behavior if consumers assume non-negative height.
|
||||
|
||||
- **`MONITORINFO` is a `class`, not a `struct`**:
|
||||
This is unusual for P/Invoke marshaling (where `struct` is typical). While it works due to `cbSize` initialization and `Marshal.PtrToStructure`/`StructureToPtr`, using a `class` here risks reference-type semantics (e.g., accidental sharing). A `struct` would be safer and more conventional.
|
||||
|
||||
- **`GetMinMaxInfo` silently fails if monitor query fails**:
|
||||
If `MonitorFromWindow` returns `IntPtr.Zero` (e.g., invalid `hwnd`), no adjustment occurs. No error is logged or thrown—consumers must verify behavior.
|
||||
|
||||
- **`WM.WINDOWMAX` is likely incorrect**:
|
||||
`0x0024` is `WM_SYSCOMMAND`, not a maximization message. `WM_GETMINMAXINFO` is `0x0024`—*this is the same value*. The enum name `WINDOWMAX` is misleading; it should be `GETMINMAXINFO`. This is a naming bug.
|
||||
|
||||
- **`RECT.IsEmpty` uses `>=` (not `>`)**:
|
||||
`IsEmpty => left >= right || top >= bottom` correctly handles degenerate rectangles (e.g., `left == right`), but consumers may overlook that empty rectangles have zero area.
|
||||
|
||||
- **No thread-safety guarantees**:
|
||||
`GetMinMaxInfo` mutates a `MINMAXINFO` via `Marshal.PtrToStructure`/`StructureToPtr`. While the operation is read-modify-write on a *copy* (safe), the use of `MONITORINFO` as a `class` (reference type) could introduce issues if reused across threads without copying.
|
||||
|
||||
- **`MONITORINFO.rcMonitor` and `rcWork` are initialized to `new RECT()`**:
|
||||
`RECT()` sets all fields to `0`, so `rcMonitor` and `rcWork` start as `(0,0,0,0)`. This is safe for P/Invoke since `GetMonitorInfo` overwrites them.
|
||||
|
||||
- **No handling of DPI scaling**:
|
||||
All coordinates are in *physical* pixels (Win32 convention). If the application is DPI-aware, callers must ensure `hwnd` corresponds to the correct DPI context. No DPI scaling is applied in `GetMinMaxInfo`.
|
||||
|
||||
---
|
||||
|
||||
*No other issues are apparent from the source alone.*
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.CommonCore/Classes/WindowsFolder/WindowsFolder.cs
|
||||
generated_at: "2026-04-16T02:41:11.633722+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "643a986ef3dcd404"
|
||||
---
|
||||
|
||||
# WindowsFolder
|
||||
|
||||
## 1. Purpose
|
||||
This module provides a utility method to open the folder containing application manuals using the system’s default file explorer. It exists to abstract the platform-specific logic of launching `explorer.exe` with a path derived from a base directory and a constant folder name (`Constants.ManualsFolder`). The class assumes the `path` argument passed to `OpenManualsFolder` is a valid base directory (e.g., application installation root), and that the `Manuals` folder resides directly under it—this is guaranteed by the application’s deployment structure, as noted in the documentation.
|
||||
|
||||
## 2. Public Interface
|
||||
- **`OpenManualsFolder(string path)`**
|
||||
*Signature:* `public static void OpenManualsFolder(string path)`
|
||||
*Behavior:* Combines the input `path` with the constant `Constants.ManualsFolder` to form a full folder path, then launches Windows Explorer (`explorer.exe`) to open that folder. Throws if `path` is `null`, empty, or invalid, or if `Process.Start` fails (e.g., `explorer.exe` not found or path inaccessible). Does not return a value.
|
||||
|
||||
## 3. Invariants
|
||||
- `path` must be a valid directory path (though not validated explicitly in this method—reliance is on caller correctness and OS-level validation during `Process.Start`).
|
||||
- The `Manuals` folder must exist at `Path.Combine(path, Constants.ManualsFolder)` for the folder to open meaningfully; if missing, Explorer will open to the path but show an empty or error state.
|
||||
- The method assumes `Constants.ManualsFolder` and `Constants.WindowsExplorer` are non-null, non-empty strings defined elsewhere (in `Constants.cs` or similar).
|
||||
- The method is synchronous and blocks only during process launch (not while Explorer is open).
|
||||
|
||||
## 4. Dependencies
|
||||
- **Internal dependencies:**
|
||||
- `System.IO.Path` (for `Path.Combine`)
|
||||
- `System.Diagnostics.Process` (for launching Explorer)
|
||||
- `Constants.ManualsFolder` (string constant, e.g., `"Manuals"`)
|
||||
- `Constants.WindowsExplorer` (string constant, expected to be `"explorer.exe"`)
|
||||
- **External dependencies:**
|
||||
- Windows OS (due to use of `explorer.exe`)
|
||||
- The calling application must ensure `path` is set to a directory where `Manuals` is a subfolder (e.g., application root).
|
||||
- **Depended on by:** Unknown from this file alone—no references to callers are present.
|
||||
|
||||
## 5. Gotchas
|
||||
- **Path validation is absent**: The method does not validate that `path` exists or that `manualsPath` points to an existing directory. Failure occurs only at `Process.Start`, potentially with a generic OS error.
|
||||
- **Hardcoded assumption about `CurrentDirectory`**: The XML comment states the method assumes the `Manuals` folder is in `CurrentDirectory`, but the implementation uses the passed `path`, not `Environment.CurrentDirectory`. This is inconsistent and may cause confusion—likely a documentation artifact or legacy assumption.
|
||||
- **No error handling**: Exceptions from `Process.Start` (e.g., `Win32Exception`, `InvalidOperationException`) are not caught or logged, potentially crashing the caller if unhandled.
|
||||
- **Platform lock-in**: This method only works on Windows; will fail on Linux/macOS if ever ported.
|
||||
- **No cancellation or async support**: Not suitable for UI contexts where blocking the calling thread is undesirable.
|
||||
- **`Constants` type location unspecified**: The source does not show where `Constants.ManualsFolder` or `Constants.WindowsExplorer` are defined—caller must locate and verify their values.
|
||||
Reference in New Issue
Block a user