--- source_files: - Common/DTS.Common/Classes/Groups/GroupGRPImportError.cs - Common/DTS.Common/Classes/Groups/GroupGRPImportGroup.cs - Common/DTS.Common/Classes/Groups/GroupHardwareDbRecord.cs - Common/DTS.Common/Classes/Groups/TestSetupGroupRecord.cs - Common/DTS.Common/Classes/Groups/GroupDbRecord.cs - Common/DTS.Common/Classes/Groups/GroupGRPImportChannel.cs - Common/DTS.Common/Classes/Groups/ChannelDbRecord.cs - Common/DTS.Common/Classes/Groups/GroupHelper.cs generated_at: "2026-04-16T03:16:28.845582+00:00" model: "Qwen/Qwen3-Coder-Next-FP8" schema_version: 1 sha256: "b79a1cdde998f5b5" --- # Documentation: Groups Module ## 1. Purpose This module provides data structures and helper utilities for representing, importing, and managing group-based test configurations—specifically those sourced from `.GRP` files (TDC format)—and their persistence in the database. It defines import-time models (`GroupGRPImportGroup`, `GroupGRPImportChannel`, `GroupGRPImportError`) for parsing and validating `.GRP` files, database record models (`GroupDbRecord`, `GroupHardwareDbRecord`, `TestSetupGroupRecord`, `ChannelDbRecord`) for ORM-style data access, and a static `GroupHelper` class to cache and manage cross-referenced metadata (e.g., static group names, DAS IDs, channel-group mappings) during runtime. The module serves as the canonical data model layer for group-centric test setups in the DTS system. ## 2. Public Interface ### `GroupGRPImportError` - **`Errors` enum**: Defines all possible error codes during `.GRP` file import: - `FileEmpty`, `InvalidISOCodeInput`, `InvalidFullScaleInput`, `InvalidSensorInput`, `InvalidInvertInput`, `SensorNotFound`, `InvalidInputMode`, `InvalidDefaultValue`, `InvalidActiveValue`, `InvalidFireMode`, `InvalidDelay`, `InvalidLimitDuration`, `InvalidDuration`, `InvalidCurrent` - **Properties**: - `Errors ErrorCode { get; set; }`: The specific error encountered. - `string File { get; set; }`: Path or name of the `.GRP` file where the error occurred. - `int Line { get; set; }`: Line number in the file where the error occurred. - `string ExtraInfo { get; set; }`: Human-readable error details. - **`override string ToString()`**: Returns `ExtraInfo`. ### `GroupGRPImportGroup` - **Properties**: - `bool Included { get; set; } = true`: Whether the group is included in the current import operation. - `bool Overwrite { get; set; } = true`: Whether existing group data should be overwritten. - `string GroupName { get; set; }`: Name of the group. - `string GroupTags { get; set; }`: Tags associated with the group. - `string ImportingUserTags { get; set; }`: User-provided tags during import. - `string SourceFile { get; set; }`: Path to the source `.GRP` file. - `GroupGRPImportChannel[] Channels { get; set; } = { }`: Array of imported channels. - `GroupGRPImportError[] GroupErrors { get; set; } = null`: Array of errors encountered during import of the entire group. - `bool GroupNameHasError { get; set; }`: UI hint indicating if the group name field has an error (used for visual feedback). ### `GroupHardwareDbRecord` - **Implements**: `IGroupHardwareDbRecord` - **Properties**: - `int Id { get; set; }`: Primary key (database ID). - `int GroupId { get; set; }`: Foreign key to `Group` table. - `int DASId { get; set; }`: Foreign key to DAS (Data Acquisition System) record. - `string SerialNumber { get; set; }`: Serial number of hardware associated with the group. - **Constructors**: - `GroupHardwareDbRecord()`: Default constructor. - `GroupHardwareDbRecord(IGroupHardwareDbRecord copy)`: Copy constructor. - `GroupHardwareDbRecord(IDataReader reader)`: Populates from database reader. ### `TestSetupGroupRecord` - **Implements**: `ITestSetupGroupRecord` - **Properties**: - `int GroupId { get; set; }`: Foreign key to group. - `int DisplayOrder { get; set; }`: Order in which the group appears in a test setup UI. - `string Position { get; set; }`: ISO 13499 position field. - `string TestObjectType { get; set; }`: ISO 13499 test object field. - `int TestSetupId { get; set; }`: Foreign key to test setup. - **Constructors**: - `TestSetupGroupRecord()`: Default constructor. - `TestSetupGroupRecord(IDataReader reader)`: Populates from database reader. - `TestSetupGroupRecord(ITestSetupGroupRecord copy)`: Copy constructor. ### `GroupDbRecord` - **Implements**: `IGroupDbRecord` - **Properties**: - `int Id { get; set; }`: Primary key (database ID). - `string SerialNumber { get; set; }`: Serial number (used as group identifier). - `string Picture { get; set; }`: Path or identifier for group image. - `string DisplayName { get; set; }`: Human-readable name. - `string Description { get; set; }`: Group description. - `bool Embedded { get; set; }`: Whether the group is embedded (system-managed). - `DateTime LastModified { get; set; }`: Timestamp of last modification. - `string LastModifiedBy { get; set; }`: User who last modified the group. - `int? StaticGroupId { get; set; }`: Reference to static group ID if applicable. - `string ExtraProperties { get; set; }`: Serialized JSON of additional properties. - **Constructors**: - `GroupDbRecord()`: Default constructor. - `GroupDbRecord(IGroupDbRecord copy)`: Copy constructor. - `GroupDbRecord(IGroup copy, List> extraProperties)`: Converts from domain `IGroup` model. - `GroupDbRecord(IDataReader reader)`: Populates from database reader. ### `GroupGRPImportChannel` - **Constants**: - `SerialNumberField = 0`, `DisplayNameField = 1`, `ISOCodeField = 2`, `InvertField = 3`, `CapacityField = 4`, `InputModeField = 5`, `DefaultValueField = 6`, `ActiveValueField = 7`, `FireModeField = 8`, `DelayField = 9`, `LimitDurationField = 10`, `DurationField = 11`, `CurrentField = 12`: Field indices for parsing `.GRP` files. - **Properties**: - `string SensorSerialNumber { get; set; }`: Serial number of the sensor. - `string DisplayName { get; set; }`: Channel display name. - `string ISOCode { get; set; }`: ISO-compliant channel code. - `bool Invert { get; set; }`: Whether the channel signal is inverted. - `double FullScale { get; set; }`: Full-scale value (e.g., for analog channels). - `InputModes? InputMode { get; set; } = null`: Input mode (see enum below). - `FireModes? FireMode { get; set; } = null`: Fire mode (see enum below). - `double? DefaultValue { get; set; } = null`: Default value (e.g., for analog channels). - `double? ActiveValue { get; set; } = null`: Active value (e.g., trigger threshold). - `double? Delay { get; set; } = null`: Delay before firing (seconds). - `bool? LimitDuration { get; set; } = null`: Whether duration is limited. - `double? Duration { get; set; } = null`: Duration of fire pulse (seconds). - `double? Current { get; set; } = null`: Current limit for squib firing. - `GroupGRPImportError Error { get; set; } = null`: Channel-specific import error. - `GroupGRPImportGroup ParentGroup { get; set; }`: Parent group reference. - `string GroupName { get; }`: Derived from `ParentGroup.GroupName`; returns `"---"` if no parent. - **Nested Enums**: - `InputModes`: `na`, `TLH`, `THL`, `CCNO`, `CCNC` - `FireModes`: `na`, `CD`, `CC` - **Constants**: - `DefaultInputMode = InputModes.CCNO` - `DefaultFireMode = FireModes.CD` - `DefaultDefaultValue = 0.0`, `DefaultActiveValue = 1.0`, `DefaultDelay = 0.00`, `DefaultLimitDuration = true`, `DefaultDuration = 10.0`, `DefaultCurrent = 1.5` - **Methods**: - `void GroupNameInvalidate()`: Forces UI refresh for `GroupName` binding. ### `ChannelDbRecord` - **Implements**: `IChannelDbRecord` - **Properties**: - `long Id { get; set; }`: Primary key (database ID). - `int GroupId { get; set; }`: Foreign key to group. - `string IsoCode { get; set; }`: ISO channel code. - `string IsoChannelName { get; set; }`: ISO-compliant channel name. - `string UserCode { get; set; }`: User-defined channel code. - `string UserChannelName { get; set; }`: User-defined channel name. - `int DASId { get; set; }`: Foreign key to DAS. - `int DASChannelIndex { get; set; }`: Channel index on the DAS. - `int GroupChannelOrder { get; set; }`: Order within the group. - `int TestSetupOrder { get; set; }`: Order within a test setup. - `int SensorId { get; set; }`: Foreign key to sensor. - `bool Disabled { get; set; }`: Whether channel is disabled. - `bool IsDisabled { get; set; }`: Backward-compatible alias for `Disabled`. - `DateTime LastModified { get; set; }`: Timestamp of last modification. - `string LastModifiedBy { get; set; }`: User who last modified the channel. - **Constructors**: - `ChannelDbRecord()`: Default constructor. - `ChannelDbRecord(IChannelDbRecord copy)`: Copy constructor. - `ChannelDbRecord(IDataReader reader)`: Populates from database reader. ### `GroupHelper` - **Static utility class** (abstract, non-instantiable). - **Methods**: - `ClearStaticGroupNames()`, `SetStaticGroupName(int id, string name)`, `GetStaticGroupName(int id)`: Manage mapping of static group IDs to names. - `ClearEmbeddedGroupIdList()`, `SetEmbeddedGroupId(int id)`, `IsGroupEmbedded(int id)`: Manage list of embedded group IDs. - `ClearTestSetupGroupIds()`, `SetTestSetupGroupId(int groupId, int testSetupId)`, `GetTestSetupGroupId(int groupId)`: Map group IDs to test setup IDs. - `ClearGroupChannelIds()`, `AddGroupChannelId(int sensorId, int groupId)`, `GetGroupIdsFromChannels(int sensorId)`: Map sensor IDs to associated group IDs. - `ClearDASIds()`, `SetDASId(string serialNumber, int dasId)`, `GetDASId(string serialNumber)`: Map DAS serial numbers to database IDs. - `ClearBaseModuleChannelIndexList()`, `SetBaseModuleChannelIndexList(...)`, `GetChannelIndexes(...)`: Manage channel index mappings for base/module serial number pairs. - `ClearDASIdChannelIndexGroupIdList()`, `SetDASIdChannelIndexGroupIdList(...)`, `GetGroupIds(...)`: Map DAS ID + channel index → group ID. - `ClearTestSetupHardwareIds()`, `AddTestSetupHardwareId(int dasId, int testSetupId)`, `GetTestSetupHardwareIds(int DASId)`: Map DAS IDs to associated test setup IDs. - `ClearGroupHardwareIds()`, `AddGroupHardwareId(int dasId, int groupId)`, `GetGroupHardwareIds(int DASId)`: Map DAS IDs to associated group IDs. ## 3. Invariants - **`GroupGRPImportGroup.Channels`**: Always initialized to an empty array (`{ }`), never `null`. - **`GroupGRPImportGroup.GroupErrors`**: Initialized to `null` by default; non-null only if errors occurred during import. - **`GroupGRPImportChannel.*` nullable properties** (e.g., `InputMode`, `DefaultValue`, `FireMode`, etc.): May be `null` if not specified in the `.GRP` file; default values are defined as constants (e.g., `DefaultInputMode`, `DefaultFireMode`, etc.). - **`GroupDbRecord.ExtraProperties`**: Serialized as JSON using `JavaScriptSerializer`; deserialization responsibility lies with consumers. - **`ChannelDbRecord.IsDisabled`**: Redirects to `Disabled`; both properties must be kept in sync when set via `IsDisabled`. - **`GroupHelper` static caches**: Must be cleared between operations (e.g., import sessions) to avoid stale data; no automatic cleanup is provided. ## 4. Dependencies ### Dependencies *of* this module: - **`DTS.Common.Base`**: Base classes (`BasePropertyChanged`) used by `GroupGRPImportGroup`, `GroupGRPImportChannel`, `GroupHardwareDbRecord`, `TestSetupGroupRecord`, `GroupDbRecord`, `ChannelDbRecord`. - **`DTS.Common.Interface.Groups`**: Interfaces `IGroupHardwareDbRecord`, `ITestSetupGroupRecord`, `IGroupDbRecord`. - **`DTS.Common.Interface.Channels`**: Interface `IChannelDbRecord`. - **`System.Data`**: `IDataReader` used in record constructors. - **`System.ComponentModel.DataAnnotations`**: `[Key]` attribute on `Id` fields. - **`System.Web.Script.Serialization.JavaScriptSerializer`**: Used in `GroupDbRecord` constructor to serialize `ExtraProperties`. ### Dependencies *on* this module: - **Import/Export logic**: `.GRP` file parsing and validation (not included here, but inferred from `GroupGRPImport*` classes). - **Database layer**: `GroupDbRecord`, `ChannelDbRecord`, `GroupHardwareDbRecord`, `TestSetupGroupRecord` are used by data access layers. - **UI layer**: `GroupGRPImportGroup.GroupNameHasError` and `GroupGRPImportChannel.GroupName` suggest binding to UI controls (e.g., textboxes, error indicators). - **Runtime metadata management**: `GroupHelper` is used by other modules to resolve IDs, serial numbers, and mappings without repeated DB queries. ## 5. Gotchas - **`GroupGRPImportChannel.GroupName` is a computed property**: It returns `ParentGroup.GroupName` or `"---"` if `ParentGroup` is `null`. UI bindings must be manually invalidated via `GroupNameInvalidate()` if `ParentGroup` changes after construction. - **`IsDisabled` alias in `ChannelDbRecord`**: While `IsDisabled` redirects to `Disabled`, setting `IsDisabled` only raises `OnPropertyChanged("IsDisabled")`, not `"Disabled"`. This may cause UI binding inconsistencies if consumers bind to `"Disabled"` directly. - **`GroupDbRecord.ExtraProperties` serialization**: Uses legacy `JavaScriptSerializer`; not compatible with modern `System.Text.Json`. Consumers must use the same serializer for round-tripping. - **`GroupHelper` static state**: Caches are global and mutable; failure to call `Clear*()` methods between operations (e.g., import sessions) can lead to incorrect ID lookups or stale mappings. - **`GroupHardwareDbRecord.Id` vs `GroupDbRecord.Id`**: Both use `int Id`, but `ChannelDbRecord.Id` uses `long Id`. Ensure correct type usage in queries. - **`GroupGRPImportGroup.GroupErrors` is nullable**: Consumers must explicitly check for `null` before iterating (e.g., `?.Length` or `GroupErrors?.Any()`). - **`GroupHelper.GetChannelIndexes` and `GetGroupIds`**: Use exact string/ID matching on nested dictionaries; performance may degrade with large datasets due to nested loops. - **`GroupDbRecord.SerialNumber` vs `GroupName`**: In `GroupDbRecord(IGroup copy, ...)`, `SerialNumber` is set to `copy.Name`, but `DisplayName` is set separately. Ensure `Name` and `DisplayName` are distinct in the `IGroup` interface.