--- 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-17T15:30:52.784383+00:00" model: "zai-org/GLM-5-FP8" schema_version: 1 sha256: "ac650a057eb86250" --- # DTS.Common.Classes.TestSetups Module Documentation ## 1. Purpose This module provides data structures and utilities for managing test setup configurations in the DTS system. It defines entity classes for hardware records, Regions of Interest (ROI), calculated channels, graph configurations, and sensor records. The module supports both in-memory representation and database persistence through `IDataReader` constructors, and includes functionality for reading/writing ISF (Instrument Setup File) format files used for sensor configuration interchange. --- ## 2. Public Interface ### SimpleHardware ```csharp public class SimpleHardware : Tuple ``` A lightweight data container representing hardware association. **Constructor:** - `SimpleHardware(string serialNumber, string parentDAS, int dasId, int dasType)` **Properties:** - `string SerialNumber` — Returns `Item1` from the tuple - `string ParentDAS` — Returns `Item2` from the tuple - `int DASId` — Returns `Item3` from the tuple - `int DASType` — Returns `Item4` from the tuple --- ### TestSetupHelper ```csharp public abstract class TestSetupHelper ``` Static utility class for managing a process-wide cache of test setup names. **Static Methods:** - `void ClearTestSetupNames()` — Clears the internal dictionary - `void SetTestSetupName(int id, string name)` — Associates a name with an ID (overwrites if exists) - `string GetTestSetupName(int Id)` — Returns the name for the given ID, or `string.Empty` if not found --- ### ROIPeriodChannelRecord ```csharp public class ROIPeriodChannelRecord : BasePropertyChanged, IROIPeriodChannelRecord ``` Represents a record from the ROIPeriodChannels table. **Constructor:** - `ROIPeriodChannelRecord(IDataReader reader)` — Populates from a stored procedure result (`sp_ROIPeriodChannelsGet`) **Properties:** - `int TestSetupROIId` — Foreign key to TestSetupROIs table - `string ChannelName` — Name of a channel in an ROI period --- ### ExtraProperty ```csharp public class ExtraProperty : IExtraProperty ``` Represents a key-value property with UI support. **Constructors:** - `ExtraProperty()` - `ExtraProperty(string key, string value)` - `ExtraProperty(IExtraProperty iep)` — Copy constructor **Properties:** - `string Key` — Property identifier - `string Value` — Property value - `ICommand PasteCommand` — WPF command binding for paste operations - `UIItemStatus ItemStatus` — UI state tracking **Events:** - `PropertyChangedEventHandler PropertyChanged` --- ### TestSetupHardwareRecord ```csharp public class TestSetupHardwareRecord : BasePropertyChanged, ITestSetupHardwareRecord ``` Represents hardware configuration for a test setup. **Constructors:** - `TestSetupHardwareRecord()` - `TestSetupHardwareRecord(IDataReader reader)` — Populates from database query - `TestSetupHardwareRecord(ITestSetupHardwareRecord copy)` — Copy constructor **Properties:** - `int DASId` — Default: `-1` - `int TestSetupId` - `bool AddDAS` — Default: `true` - `int SamplesPerSecond` - `bool IsClockMaster` — Default: `false` - `byte PTPDomainId` — Default: `0` - `int AntiAliasFilterRate` --- ### TestSetupROIsRecord ```csharp public class TestSetupROIsRecord : BasePropertyChanged, ITestSetupROIRecord ``` Represents a Region of Interest period definition. **Constructor:** - `TestSetupROIsRecord(IDataReader reader)` — Populates from `sp_TestSetupROIsGet` **Properties:** - `int TestSetupROIId` - `int TestSetupId` - `string Suffix` — e.g., "_ROI Period 1" - `double ROIStart` — Default: `-1.0D` - `double ROIEnd` — Default: `1.0D` - `bool IsEnabled` — Default: `true` - `bool IsDefault` — Default: `true` --- ### CalculatedChannelRecord ```csharp public class CalculatedChannelRecord : BasePropertyChanged, ICalculatedChannelRecord ``` Represents a calculated channel definition. **Constructors:** - `CalculatedChannelRecord()` - `CalculatedChannelRecord(ICalculatedChannelRecord record)` — Copy constructor - `CalculatedChannelRecord(IDataReader reader)` — Populates from database query **Properties:** - `string Name` - `string TestSetupName` - `int Id` — Database ID; default: `-1` - `Operations Operation` — Default: `Operations.SUM` - `string CalculatedValueCode` - `string[] InputChannelIds` — Default: `["-1"]` - `string CFCForInputChannels` - `string ChannelFilterClassForOutput` - `int TestSetupId` - `bool ViewInRealtime` - `int ClipLength` --- ### GraphRecord ```csharp public class GraphRecord : BasePropertyChanged, IGraphRecord ``` Represents graph configuration for visualization. **Constructors:** - `GraphRecord()` - `GraphRecord(IGraphRecord copy)` — Copy constructor - `GraphRecord(IDataReader reader)` — Populates from database query **Properties:** - `int GraphId` - `int TestSetupId` - `string GraphName` — MaxLength: 50 - `string GraphDescription` — MaxLength: 50 - `string ChannelsString` — MaxLength: 2048 - `bool UseDomainMin` - `double DomainMin` — Default: `double.MinValue` - `bool UseDomainMax` - `double DomainMax` — Default: `double.MaxValue` - `bool UseRangeMin` - `double RangeMin` — Default: `double.MinValue` - `bool UseRangeMax` - `double RangeMax` — Default: `double.MaxValue` - `string ThresholdsString` — MaxLength: 2048 - `bool LocalOnly` — Default: `false`; marked as deprecated --- ### RegionOfInterest ```csharp public class RegionOfInterest : IRegionOfInterest ``` Represents a time-based region of interest with channel assignments. **Static Properties:** - `bool Deserializing` — Controls whether property changes trigger notifications (used during deserialization) **Constructors:** - `RegionOfInterest()` - `RegionOfInterest(bool isDefault = false)` - `RegionOfInterest(string suffix = "", bool isDefault = false, double start = -1D, double end = 1D)` **Properties:** - `string Suffix` — Automatically prepends "_" if not present - `double Start` — Default: `double.MinValue`; constrained to be less than `End` - `double End` — Default: `double.MaxValue`; constrained to be greater than `Start` - `bool IsEnabled` — Default: `true` - `bool IsDefault` - `string[] ChannelNames` **Methods:** - `void ResetSuffix()` — Clears suffix to empty string - `void SetChannelNamesNoNotify(string[] names)` — Sets channel names without triggering change notifications **Static Methods:** - `string GetAnalogChanName(string serialNumber, string hardwareChannelName, string startOfHardware, string originalChannelName = "")` - `string GetChanName(string serialNumber, string hardwareChannelName, string originalChannelName = "")` - `string RemoveParentDASName(string entireChannelName)` - `string RemoveAssignedByIDFromHardwareString(string chHardware)` **Events:** - `PropertyChangedEventHandler PropertyChanged` --- ### ISFFile ```csharp public class ISFFile ``` Handles reading and writing ISF (Instrument Setup File) format files. **Constructor:** - `ISFFile()` **Properties:** - `char[] HeaderLine1` — 80 characters - `char[] TestSetupName` — 8 characters starting at position 7 - `char[] NumberOfRecords` — 5 characters starting at position 15 - `char[] TestType` — 22 characters starting at position 20 - `char[] TestDivision` — 30 characters starting at position 42 - `char[] TCFile` — 8 characters starting at position 72 - `IISFSensorRecord[] Records` — Array of sensor records **Methods:** - `void AddRecord(IISFSensorRecord record)` — Adds a record and updates count - `void WriteToFile(string pathToFile)` — Writes the ISF file to disk - `void AddSensors(ISensorData[] sensors)` — Converts sensors to ISFSensorRecord and adds them --- ### ISFSensorRecord ```csharp public class ISFSensorRecord : IISFSensorRecord ``` Represents a sensor record in ISF file format (4 records of 80 characters each). **Constructor:** - `ISFSensorRecord()` — Initializes with spaces and sets `TOMConfigurationName` to "STANDARD" **Properties (Record 1):** - `char[] Record1` — 80 characters - `char[] Tag` — 2 characters at position 75 - `char[] DataChannelNumber` — 5 characters at position 7 - `bool UserIdSensorIDIsNotSpecified` — 1 character at position 15 - `char[] CapacityCharacters` — 11 characters at position 19 - `char[] SerialNumber` — 12 characters at position 30 - `char[] Sensitivity` — 11 characters at position 42 - `char[] BridgeResistance` — 11 characters at position 53 **Properties (Record 2):** - `char[] Record2` — 80 characters - `char[] EngineeringUnits` — 12 characters at position 7 - `char[] C1` — 11 characters at position 20 - `char[] EID` — 17 characters at position 31 - `char[] Unknown1` — 4 characters at position 49 - `char[] Unknown2` — 2 characters at position 53 - `char[] FireDelay` — 11 characters at position 55 - `char[] TOMConfigurationName` — 8 characters at position 66 **Properties (Record 3):** - `char[] Record3` — 80 characters - `char[] CommentPart1` — 15 characters at position 14 - `char[] CommentPart2` — 40 characters at position 33 **Properties (Record 4):** - `char[] Record4` — 80 characters - `char[] CommentPart3` — 15 characters at position 12 - `char[] SensorType` — 20 characters at position 30 - `char[] C2` — 11 characters at position 50 - `char[] C3` — 11 characters at position 61 **Methods:** - `void SetDataChannelNumber(short value)` - `void SetCapacity(double capacity)` - `double GetCapacity()` - `void SetSensitivity(double sensitivity)` - `double GetSensitivity()` - `void SetC1(double c1)` / `double GetC1()` - `void SetC2(double c2)` - `void SetC3(double c3)` - `void SetFireDelay(double fireDelay)` - `void SetSensorComment(string s)` - `void Write(System.IO.BinaryWriter writer)` - `void SetSensor(ISensorData sensor)` --- ### ArrayExtensions (Static Class) ```csharp public static class ArrayExtensions ``` Extension methods for array manipulation. **Methods:** - `void Fill(this T[] sourceArray, T with)` — Fills entire array with value - `void SubFill(this T[] source, T with, int startIndex, int finalIndex)` — Fills a range - `void SetValues(this T[] source, T[] with, int startIndex, int length, T pad)` — Copies values with padding - `T[] GetValues(this T[] source, int startIndex, int length)` — Extracts a sub-array --- ## 3. Invariants - **SimpleHardware** is immutable (inherits from `Tuple<...>`). - **TestSetupHardwareRecord.DASId** defaults to `-1`, indicating an unset/unassigned state. - **CalculatedChannelRecord.Id** defaults to `-1`, indicating a new/unpersisted record. - **CalculatedChannelRecord.InputChannelIds** is never null after construction (defaults to `["-1"]`). - **RegionOfInterest.Start** is always less than `End` (enforced by property setters with 0.01 minimum separation). - **RegionOfInterest.Suffix** is automatically normalized to start with `_` if non-empty. - **ISFFile** uses fixed record length of 80 characters (`ConstantsAndEnums.RECORD_LENGTH`). - **ISFSensorRecord** always consists of exactly 4 records of 80 characters each. - **ISFSensorRecord.NumberOfRecords** in the file header equals `Records.Length * 4`. - **GraphRecord.DomainMin/Max** and **RangeMin/Max** have default values of `double.MinValue`/`double.MaxValue` and are only meaningful when their corresponding `Use*` boolean is `true`. --- ## 4. Dependencies ### This module depends on: - `DTS.Common.Base` — `BasePropertyChanged` base class - `DTS.Common.Interface.TestSetups` — Interface contracts (`IROIPeriodChannelRecord`, `ITestSetupHardwareRecord`, `ITestSetupROIRecord`, `ICalculatedChannelRecord`, `IISFSensorRecord`) - `DTS.Common.Interface.Graphs` — `IGraphRecord` - `DTS.Common.Interface.Sensors` — `ISensorData` - `DTS.Common.Interface.ISO.ExtraProperties` — `IExtraProperty` - `DTS.Common.Interface.RegionOfInterest` — `IRegionOfInterest` - `DTS.Common.Enums` — `Operations` enum, `UIItemStatus` enum - `DTS.Common.Enums.Sensors` — `SensorConstants` - `DTS.Common.Events.RegionOfInterest` — `RegionOfInterestChangedEvent` - `Microsoft.Practices.Prism.Events` — `IEventAggregator` - `Microsoft.Practices.ServiceLocation` — `ServiceLocator` - `System.Data` — `IDataReader` for database record construction - `System.ComponentModel` — `INotifyPropertyChanged`, `PropertyChangedEventHandler` - `System.Windows.Input` — `ICommand` ### What depends on this module: - Not determinable from the source files alone. --- ## 5. Gotchas ### TestSetupROIsRecord Constructor Bug In `TestSetupROIsRecord(IDataReader reader)`, the `TestSetupId` property is incorrectly assigned from the `TestSetupROIId` column: ```csharp TestSetupId = Utility.GetInt(reader, "TestSetupROIId"); // Should likely be "TestSetupId" ``` This appears to be a copy-paste error; `TestSetupId` should probably read from the `"TestSetupId"` column. ### RegionOfInterest Static State `RegionOfInterest.Deserializing` is a **static** property that controls change notifications globally. If multiple threads are deserializing ROIs concurrently, or if the flag is not properly reset, notifications may be incorrectly suppressed or fired. ### RegionOfInterest.NotifyChanged Silent Failures The `NotifyChanged()` method catches and swallows all exceptions silently. Failures in `ServiceLocator` or `IEventAggregator` resolution will go unnoticed. ### ISFFile Overwrites Without Prompt `ISFFile.WriteToFile()` will delete an existing file at the target path without user confirmation via `Utils.FileUtils.DeleteFileOrMove()`. ### GraphRecord.LocalOnly Deprecated The `