init
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Converters/FirstUseDateConverter.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Converters/StandInFieldConverter.cs
|
||||
generated_at: "2026-04-16T04:37:34.782938+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "aee017cd34357419"
|
||||
---
|
||||
|
||||
# Converters
|
||||
|
||||
## Documentation: `HardwareList.Converters` Module
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
This module provides WPF value converters for formatting and conditional display of hardware-related properties in UI-bound data grids or forms. Specifically, `FirstUseDateConverter` and `StandInFieldConverter` translate raw model data into user-friendly string representations (e.g., `"N/A"`, `"---"`, or actual `DateTime` values), handling edge cases such as missing, invalid, or inapplicable data based on hardware state (e.g., `StandIn` flag). These converters enable consistent, declarative UI formatting without cluttering view models with presentation logic.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
#### `FirstUseDateConverter`
|
||||
*Namespace:* `HardwareList.Converters`
|
||||
*Implements:* `IValueConverter`
|
||||
|
||||
- **`Convert(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is not a `HardareList.Model.HardwareModel`, returns `Strings.Table_NA`.
|
||||
- If `model.IsFirstUseValid` is `false`, returns `Strings.NotApplicable`.
|
||||
- If `model.FirstUseDate` is non-null, returns `model.FirstUseDate` (as `DateTime?`).
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Return type:** `object` (typically `string` or `DateTime?`).
|
||||
|
||||
- **`ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is a `DateTime`, returns it.
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Note:** This is a minimal reverse converter; it does not validate or parse strings.
|
||||
- **Return type:** `object`.
|
||||
|
||||
---
|
||||
|
||||
#### `StandInFieldConverter`
|
||||
*Namespace:* `HardwareList.Converters`
|
||||
*Implements:* `IValueConverter`
|
||||
|
||||
- **`Convert(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is not a `HardareList.Model.HardwareModel`, returns `Strings.Table_NA`.
|
||||
- If `model.Hardware` does not implement `IISOHardware`, returns `string.Empty`.
|
||||
- If `isoHW.StandIn` is `true`, returns `Strings.Table_NA`.
|
||||
- If `parameter` is a `string` matching `"CalDueDate"`, `"CalDate"`, or `"Firmware"`, returns the corresponding property (`model.CalDueDate`, `model.CalDate`, or `model.Firmware`).
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Return type:** `object` (typically `string`, `DateTime?`, or `object` depending on the requested field).
|
||||
|
||||
- **`ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)`**
|
||||
- **Behavior:**
|
||||
- If `value` is a `DateTime`, returns it.
|
||||
- Otherwise, returns `Strings.Table_NA`.
|
||||
- **Return type:** `object`.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- **Type Safety:** Both converters expect the input `value` to be a `HardareList.Model.HardwareModel`. Failure to meet this results in fallback to `Strings.Table_NA`.
|
||||
- **Null Handling:**
|
||||
- `FirstUseDateConverter` treats `null` `FirstUseDate` as `"---"` (`Strings.Table_NA`), distinct from `IsFirstUseValid == false` which yields `"N/A"` (`Strings.NotApplicable`).
|
||||
- `StandInFieldConverter` short-circuits to `Strings.Table_NA` if `isoHW.StandIn` is `true`, regardless of the requested field.
|
||||
- **Parameter Dependency (StandInFieldConverter only):**
|
||||
- The converter’s output depends critically on the `parameter` being a `string` matching one of the three known keys (`"CalDueDate"`, `"CalDate"`, `"Firmware"`). Any other parameter yields `Strings.Table_NA`.
|
||||
- **No Validation on ConvertBack:** Both converters perform no validation or parsing in `ConvertBack`; they only pass through `DateTime` values or return `Strings.Table_NA`.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
- **Internal Dependencies (from source):**
|
||||
- `HardareList.Model.HardwareModel` (note: likely typo in namespace `HardareList` vs. `HardwareList`).
|
||||
- `DTS.Common.Strings` (provides `Strings.Table_NA`, `Strings.NotApplicable`).
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.IISOHardware` (used in `StandInFieldConverter`).
|
||||
- `System.Windows.Data.IValueConverter` (WPF base interface).
|
||||
|
||||
- **External Dependencies:**
|
||||
- WPF framework (for `IValueConverter` usage in XAML).
|
||||
- `DTS.Common` assembly (contains `Strings` and `IISOHardware`).
|
||||
|
||||
- **Depended Upon By:**
|
||||
- UI layers (XAML bindings) referencing these converters in `DataGrid` columns or `TextBlock` bindings for hardware properties.
|
||||
- No direct code dependencies inferred—converters are consumed via XAML markup extension or resource references.
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **Typo in Namespace:** The model type is referenced as `HardareList.Model.HardwareModel` (missing 'w' in "Hardware"), which may cause runtime binding failures if the actual namespace is `HardwareList`.
|
||||
- **Ambiguous `parameter` Usage:** `StandInFieldConverter` relies on string literals for field selection (`"CalDueDate"`, etc.). Typos or case mismatches in XAML parameter values will silently fall back to `Strings.Table_NA`.
|
||||
- **Inconsistent `ConvertBack` Behavior:** Both converters return `Strings.Table_NA` for non-`DateTime` inputs in `ConvertBack`, which may be misleading if the UI expects a `null` or `DateTime?` result (e.g., for nullable fields like `CalDueDate`).
|
||||
- **No Handling for Invalid `IISOHardware` Cast:** In `StandInFieldConverter`, if `model.Hardware` is non-null but not `IISOHardware`, the converter returns `string.Empty`—a subtle distinction from `Strings.Table_NA` (`"---"`), which could cause visual inconsistency.
|
||||
- **Missing Documentation for `Strings` Values:** While `Strings.Table_NA` and `Strings.NotApplicable` are used, their exact string values (e.g., `"---"` vs `"N/A"`) are not visible in this source and must be verified in `DTS.Common.Strings`.
|
||||
|
||||
*None identified beyond the above.*
|
||||
@@ -0,0 +1,270 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Model/HardwareChannelAssignment.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Model/SLICE6TreeNode.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Model/Hardware.cs
|
||||
generated_at: "2026-04-16T04:38:28.250792+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "e010e06b613fee2c"
|
||||
---
|
||||
|
||||
# HardwareList.Model Module Documentation
|
||||
|
||||
## 1. Purpose
|
||||
This module provides data models and persistence logic for representing and managing hardware devices (DAS units) in the DataPRO diagnostics system. It defines core entities (`HardwareChannelAssignment`, `SLICE6TreeNode`, `HardwareModel`) that model hardware topology, channel assignments, and device metadata. The module enables querying device hierarchies (e.g., SLICE6DB parent-child relationships), persisting association changes to the database, and exposing hardware properties for UI binding (via `INotifyPropertyChanged`). It serves as the data layer for the Hardware List view, supporting configuration, sorting, filtering, and calibration tracking.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `HardwareChannelAssignment`
|
||||
- **`HardwareChannelAssignment(string channelNumber, string sensor, string name)`**
|
||||
Constructor. Initializes immutable properties with provided values. Represents a mapping between a hardware channel, its connected sensor type, and a user-defined name.
|
||||
|
||||
- **`string ChannelNumber { get; }`**
|
||||
Channel identifier (e.g., "CH1", "A0").
|
||||
|
||||
- **`string Sensor { get; }`**
|
||||
Type of sensor connected to the channel.
|
||||
|
||||
- **`string Name { get; }`**
|
||||
User-assigned name for the channel.
|
||||
|
||||
---
|
||||
|
||||
### `SLICE6TreeNode`
|
||||
- **`SLICE6TreeNode(int dasId, string serialNumber, int port, int number, int positionOnChain)`**
|
||||
Constructor. Initializes properties for a SLICE6 device node in a tree structure.
|
||||
|
||||
- **`int DASId { get; set; }`**
|
||||
Primary key ID from the DAS database table.
|
||||
|
||||
- **`string SerialNumber { get; set; }`**
|
||||
Device serial number.
|
||||
|
||||
- **`int Port { get; set; }`**
|
||||
Physical port number on the S6DB (distributor) to which the device is connected.
|
||||
|
||||
- **`string PortString { get; }`**
|
||||
Readable string representation of `Port`; returns `"---"` if `Port < 0`.
|
||||
|
||||
- **`int Number { get; set; }`**
|
||||
Order of the device on the S6DB (i.e., its position index among siblings).
|
||||
|
||||
- **`int PositionOnChain { get; set; }`**
|
||||
Position of the device within its daisy-chain on a given port.
|
||||
|
||||
- **`string PositionOnChainString { get; }`**
|
||||
Readable string representation of `PositionOnChain`; returns `"---"` if `PositionOnChain < 0`.
|
||||
|
||||
- **`static ISLICE6TreeNode[] GetAvailableTreeNodes(string serialNumberParent)`**
|
||||
Queries the database for all SLICE6 devices *not* associated with `serialNumberParent`. Returns an array of `ISLICE6TreeNode` instances sorted by `SerialNumber`. Returns empty array if `serialNumberParent` is null/empty.
|
||||
|
||||
- **`static ISLICE6TreeNode[] GetTreeNodes(string serialNumberParent)`**
|
||||
Queries the database for all SLICE6 devices *associated* with `serialNumberParent`. Returns an array of `ISLICE6TreeNode` instances sorted by `Number` (i.e., `PositionOnDistributor`). Returns empty array if `serialNumberParent` is null/empty.
|
||||
|
||||
- **`static void SwapNodes(string serialNumberA, string serialNumberB)`**
|
||||
Swaps all child devices between two SLICE6DB units (`serialNumberA` and `serialNumberB`) in the database. *Note: There is a bug in the implementation—both `listA` and `listB` are associated to `serialNumberB` in the second `Associate` call, not `serialNumberA` and `serialNumberB` respectively.*
|
||||
|
||||
- **`static void SaveAssociations(string serialNumber, ISLICE6TreeNode[] attachedSLICE6)`**
|
||||
Commits the current association state of SLICE6 devices to a parent SLICE6DB (`serialNumber`). First clears all existing associations for `serialNumber`, then updates each device in `attachedSLICE6` with its new `ParentDAS`, `PositionOnDistributor`, `PositionOnChain`, and `Port`.
|
||||
|
||||
---
|
||||
|
||||
### `HardwareModel`
|
||||
- **`HardwareModel(IISOHardware d, ...)`**
|
||||
Constructor. Populates properties from an `IISOHardware` instance and calculates derived values (e.g., `CalDueDate`, `ChannelCount`). Requires calibration period parameters per hardware type.
|
||||
|
||||
- **`int DASId { get; set; }`**
|
||||
Database ID of the device.
|
||||
|
||||
- **`bool Disabled { get; set; }`**
|
||||
Whether the device is disabled.
|
||||
|
||||
- **`string SerialNumber { get; set; }`**
|
||||
Device serial number.
|
||||
|
||||
- **`string HardwareType { get; set; }`**
|
||||
Localized string description of the hardware type (e.g., `"SLICE6_BASE"`).
|
||||
|
||||
- **`string ChannelCount { get; set; }`**
|
||||
Human-readable string listing channel types and counts (e.g., `"8 Analog, 2 Digital In"`).
|
||||
|
||||
- **`bool HasIncludedChildren { get; set; }`**
|
||||
Indicates if this device has child devices marked as `Included`.
|
||||
|
||||
- **`string Firmware { get; set; }`**
|
||||
Firmware version string.
|
||||
|
||||
- **`double? MaxSampleRate { get; set; }`**
|
||||
Maximum supported sample rate (Hz); `null` if unknown or not applicable.
|
||||
|
||||
- **`double TestSampleRate { get; set; }`**
|
||||
Current test/sample rate selected for the device.
|
||||
|
||||
- **`double TestAAFilterRateHz { get; set; }`**
|
||||
Anti-aliasing filter rate (Hz) corresponding to `TestSampleRate`.
|
||||
|
||||
- **`DateTime? CalDate { get; set; }`**
|
||||
Last calibration date.
|
||||
|
||||
- **`DateTime? CalDueDate { get; set; }`**
|
||||
Calculated calibration due date based on `CalDate` and hardware-specific period.
|
||||
|
||||
- **`string[] AvailableSampleRates { get; set; }`**
|
||||
Array of available sample rate strings (e.g., `["1000", "2000"]`).
|
||||
|
||||
- **`string SelectedSampleRateItem { get; set; }`**
|
||||
Currently selected sample rate string.
|
||||
|
||||
- **`int SelectedSampleRateIndex { get; set; }`**
|
||||
Index of the current sample rate in `_availableSampleRates`. Setter updates `TestSampleRate` and `TestAAFilterRateHz`.
|
||||
|
||||
- **`object Hardware { get; set; }`**
|
||||
Backing `IISOHardware` instance.
|
||||
|
||||
- **`int AnalogChannels { get; set; }`**
|
||||
Number of analog input channels.
|
||||
|
||||
- **`int SquibChannels { get; set; }`**
|
||||
Number of squib (explosive device) channels.
|
||||
|
||||
- **`int DigitalInChannels { get; set; }`**, **`int DigitalOutChannels { get; set; }`**, **`int UartChannels { get; set; }`**, **`int StreamOutChannels { get; set; }`**, **`int StreamInChannels { get; set; }`**, **`int CanChannels { get; set; }`**
|
||||
Channel counts for respective interface types.
|
||||
|
||||
- **`string IPAddress { get; set; }`**
|
||||
IP address or `"USB"` if connected via USB.
|
||||
|
||||
- **`bool Included { get; set; }`**
|
||||
Whether the device is included in the current configuration.
|
||||
|
||||
- **`double DSPStreamingFilter { get; set; }`**
|
||||
DSP streaming filter value.
|
||||
|
||||
- **`DTS.Common.ClockSyncProfile MasterProfile { get; set; }`**, **`DTS.Common.ClockSyncProfile SlaveProfile { get; set; }`**
|
||||
Clock synchronization profiles (master/slave).
|
||||
|
||||
- **`bool IsClockMaster { get; set; }`**
|
||||
Whether the device is configured as a clock master. Only valid if `IsClockedDAS` is true.
|
||||
|
||||
- **`bool IsClockedDAS { get; }`**
|
||||
Returns `true` if the device type supports clocking (e.g., SLICE6, S6A_EthernetRecorder, TSR_AIR).
|
||||
|
||||
- **`byte PTPDomainID { get; set; }`**
|
||||
PTP domain ID for precision time protocol.
|
||||
|
||||
- **`bool IsPTPSync { get; }`**
|
||||
Returns `true` if PTP synchronization is active (E2E profile in use).
|
||||
|
||||
- **`bool MixedRates { get; set; }`**
|
||||
Whether the device is part of a mixed-sample-rate configuration.
|
||||
|
||||
- **`bool IsDistributor { get; }`**
|
||||
Returns `true` if the device is a distributor (e.g., SLICE6DB, SLICE_Distributor).
|
||||
|
||||
- **`bool IsBattery { get; }`**
|
||||
Returns `true` if the device is a PowerPro.
|
||||
|
||||
- **`bool IsTSRAIR { get; }`**
|
||||
Returns `true` if the device is a TSR_AIR or embedded sensor type.
|
||||
|
||||
- **`bool IncludedAndNotMixedRatesAndCompactOrNotDistributor { get; }`**, **`bool IncludedAndMixedRatesAndCompact { get; }`**
|
||||
Derived UI flags for conditional rendering.
|
||||
|
||||
- **`string ParentDAS { get; set; }`**
|
||||
Serial number of the parent device (distributor).
|
||||
|
||||
- **`int PositionOnChain { get; set; }`**, **`int PositionOnDistributor { get; set; }`**, **`int Port { get; set; }`**
|
||||
Position metadata for hierarchical placement.
|
||||
|
||||
- **`bool HasTreeView { get; set; }`**
|
||||
Indicates if a tree view should be shown for this device (e.g., for SLICE6DB).
|
||||
|
||||
- **`string SerialNumberDisplay { get; }`**
|
||||
Display name: `SerialNumber` unless `StandIn` is true, in which case it returns the hardware type description.
|
||||
|
||||
- **`static IHardware[] GetAvailableSLICE6DB(string serialNumber)`**
|
||||
Returns all SLICE6DB devices (including `SLICE6DB_InDummy`) not currently assigned to any parent, excluding `serialNumber`.
|
||||
|
||||
- **`void DetermineChannelCount(bool showCompact, IHardware[] allHardware)`**
|
||||
Updates `ChannelCount` and `MaxSampleRate` based on device type and child devices. For distributors, calculates min sample rate among children if `showCompact` is true.
|
||||
|
||||
- **`void SetIncluded(bool bIncluded)`**, **`void SetMixedRates(bool mixedRates)`**
|
||||
Updates state and fires property change notifications.
|
||||
|
||||
- **`bool Filter(string term)`**
|
||||
Returns `true` if `SerialNumber`, `Firmware`, or `HardwareType` contains `term` (case-insensitive).
|
||||
|
||||
- **`class HardwareComparer : IComparer<IHardware>`**
|
||||
Implements sorting for `IHardware` objects. Supports sorting by `HardwareListTags` (e.g., `SerialNumber`, `CalDate`, `FirstUseDate`). Handles nulls and `double?/DateTime?` comparisons. `FirstUseDate` sorts nulls last when valid.
|
||||
|
||||
---
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **`SLICE6TreeNode`**
|
||||
- `Port`, `Number`, and `PositionOnChain` must be non-negative integers for valid hardware placements. Negative values are represented as `"---"` in UI via `PortString`/`PositionOnChainString`.
|
||||
- `GetAvailableTreeNodes` and `GetTreeNodes` only query devices with `Type = SLICE6_Base` and `Position ≠ 'Prototype'` (for `GetAvailableTreeNodes`).
|
||||
- `SwapNodes` assumes all child devices of both parents are retrieved in one query and re-associated. *Bug: Both lists are associated to `serialNumberB`.*
|
||||
|
||||
- **`HardwareModel`**
|
||||
- `CalDueDate` is derived from `CalDate` (or `FirstUseDate` if `IsFirstUseValid`) plus a hardware-specific calibration period.
|
||||
- `MaxSampleRate` is `null` if `d.MaxSampleRate` is `<= 0` or `uint.MaxValue`.
|
||||
- `IsClockedDAS` is determined by a fixed set of `HardwareTypes`.
|
||||
- `Included` and `MixedRates` flags affect derived properties (`IncludedAndNotMixedRatesAndCompactOrNotDistributor`, `IncludedAndMixedRatesAndCompact`).
|
||||
- `ChannelCount` for distributors is `"N/A"` if `showCompact` is false or no children exist.
|
||||
|
||||
- **General**
|
||||
- All database operations use `DTS.Common.Storage.DbOperations.GetSQLCommand()` and explicitly dispose connections in `finally` blocks.
|
||||
- `HardwareModel` instances are constructed with a non-null `HardwareListViewModel` (`_vm`) reference for event callbacks.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **`DTS.Common.*`**
|
||||
- `DTS.Common.Base.BasePropertyChanged` (base class for `SLICE6TreeNode`)
|
||||
- `DTS.Common.Storage.DbOperations` (database access)
|
||||
- `DTS.Common.Enums.Hardware.HardwareTypes` (device type enumeration)
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.IISOHardware`, `IHardware` (hardware abstraction interfaces)
|
||||
- `DTS.Common.Converters.EnumDescriptionTypeConverter` (localized enum descriptions)
|
||||
- `DTS.Common.ClockSyncProfile` (clock sync profiles)
|
||||
|
||||
- **`HardwareList.Resources.StringResources`**
|
||||
- Used for localized strings (e.g., `"Analog"`, `"USB"`, `"N/A"`).
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- **`HardwareList.HardwareListViewModel`**
|
||||
- Passed into `HardwareModel` constructor; used for event callbacks (`FireSampleRate`, `FireClockMaster`, etc.).
|
||||
- **UI Layer**
|
||||
- `HardwareModel` properties (e.g., `Included`, `CalDueDate`, `ChannelCount`) are bound to views.
|
||||
- `SLICE6TreeNode` is used to populate tree views for SLICE6DB hierarchies.
|
||||
- **HardwareList Module**
|
||||
- `HardwareList.Model` is the core data model for the `HardwareList` module.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **`SLICE6TreeNode.SwapNodes` Bug**:
|
||||
The `Associate` method is called twice—once for `listA` with `serialNumberB`, and again for `listB` *also* with `serialNumberB`. This means devices originally under `serialNumberB` are incorrectly moved to `serialNumberB` (no-op), and devices under `serialNumberA` are moved to `serialNumberB`, but the reverse move does not occur. The intended behavior is likely `Associate(serialNumberB, listA)` and `Associate(serialNumberA, listB)`.
|
||||
|
||||
- **`HardwareModel.CalDueDate` Calculation**:
|
||||
Uses `FirstUseDate` only if `IsFirstUseValid` is true. If `FirstUseDate` is `null` and `IsFirstUseValid` is true, it defaults to `DateTime.Today`. This may cause unexpected recalculations if `FirstUseDate` is set later.
|
||||
|
||||
- **`HardwareModel.TestSampleRate` Setter Side Effect**:
|
||||
Setting `TestSampleRate` triggers `OnPropertyChanged("SelectedSampleRateIndex")`, but the getter for `SelectedSampleRateIndex` re-computes `SelectedSampleRateItem` and calls `_vm.FireSampleRate`. This could cause redundant UI updates if `TestSampleRate` is set multiple times.
|
||||
|
||||
- **`HardwareModel.DetermineChannelCount` for Distributors**:
|
||||
`MaxSampleRate` is recalculated as the *minimum* sample rate of child devices. If children have no sample rate (`null`), `ChannelCount` becomes `"N/A"` and `MaxSampleRate` is set to `null`. This may mask missing configuration.
|
||||
|
||||
- **`HardwareModel.Filter` Case Sensitivity**:
|
||||
Filtering is case-insensitive (`term.ToLower()`), but `SerialNumberDisplay` uses `isoHW.StandIn` logic, which may cause display mismatches if `StandIn` is toggled dynamically.
|
||||
|
||||
- **`HardwareModel.Hardware` is `object`**:
|
||||
The `Hardware` property is typed as `object`, requiring casting to `IISOHardware` for type-specific checks (e.g., `IsClockedDAS`, `IsDistributor`). This risks runtime errors if the underlying type is not `IISOHardware`.
|
||||
|
||||
- **`SLICE6TreeNode` SQL Injection Risk**:
|
||||
`GetAvailableTreeNodes` uses string interpolation for `HardwareTypes.SLICE6_Base` in the `WHERE` clause (`[(int)HardwareTypes.SLICE6_Base]`). While the enum value is fixed, this pattern is fragile and error-prone.
|
||||
|
||||
- **`HardwareModel` Constructor Side Effects**:
|
||||
The constructor calls `d.GetChannelsString(...)` and computes `CalDueDate` based on `d.DASTypeEnum`. If `Hardware` is `null` or `DASTypeEnum` is invalid, it throws `ArgumentOutOfRangeException`.
|
||||
|
||||
- **`HardwareComparer.NumericCompare` Logic**:
|
||||
For `double`/`DateTime`, `a > b` returns `-1` (descending order), but the method returns `1` for all other cases. This may cause inconsistent sorting if types are mixed (e.g., `double` vs `DateTime`).
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Properties/Settings.Designer.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Properties/AssemblyInfo.cs
|
||||
generated_at: "2026-04-16T04:37:43.934636+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "5208913b7b0145de"
|
||||
---
|
||||
|
||||
# Properties
|
||||
|
||||
## Documentation Page: HardwareList.Properties.Settings
|
||||
|
||||
### 1. Purpose
|
||||
This module defines the application settings infrastructure for the `HardwareList` module within the DataPRO system. Specifically, it provides a strongly-typed, thread-safe singleton accessor (`Settings.Default`) for reading application-level configuration values stored in the standard .NET configuration system (e.g., `app.config` or `user.config`). It serves as the runtime interface to persisted settings but contains no user-defined settings properties itself—only the infrastructure class required to expose them.
|
||||
|
||||
### 2. Public Interface
|
||||
The module exposes a single internal sealed class with the following public members:
|
||||
|
||||
- **`Settings.Default` (static property)**
|
||||
- **Type**: `HardwareList.Properties.Settings`
|
||||
- **Signature**: `public static Settings Default { get; }`
|
||||
- **Behavior**: Returns the singleton instance of the `Settings` class. The instance is created via `ApplicationSettingsBase.Synchronized(...)`, ensuring thread-safe access to settings values. This is the *only* public entry point to the settings system in this file.
|
||||
|
||||
> **Note**: No user-defined settings properties (e.g., `string SomeSetting { get; set; }`) are declared in this file. Their absence indicates that either:
|
||||
> - Settings are defined elsewhere (e.g., in `Settings.settings` designer file or `app.config`), or
|
||||
> - This module is intentionally minimal and relies on external configuration sources.
|
||||
|
||||
### 3. Invariants
|
||||
- The `defaultInstance` is lazily initialized on first access to `Settings.Default` and remains constant thereafter.
|
||||
- Thread safety is guaranteed via `ApplicationSettingsBase.Synchronized(...)`, which wraps the instance in a `SyncRoot`-based synchronization mechanism.
|
||||
- The class is `sealed` and `internal`, preventing external inheritance or instantiation.
|
||||
- No validation or transformation logic is present in this file; settings values are assumed to be validated/typed by the underlying .NET configuration system at runtime.
|
||||
|
||||
### 4. Dependencies
|
||||
- **Depends on**:
|
||||
- `System.Configuration` (specifically `System.Configuration.ApplicationSettingsBase`)
|
||||
- `System.Runtime.CompilerServices.CompilerGeneratedAttribute`
|
||||
- `System.CodeDom.Compiler.GeneratedCodeAttribute`
|
||||
- **Depended on by**:
|
||||
- Other modules in the `HardwareList` assembly (e.g., code that reads settings via `Settings.Default.SomeProperty`, though *no such usage is visible in the provided source*).
|
||||
- The .NET configuration system at runtime (via `app.config`/`user.config`), which must contain matching `<setting>` entries for any properties defined in `Settings.settings`.
|
||||
|
||||
### 5. Gotchas
|
||||
- **Auto-generated file**: This file is auto-generated by the Visual Studio Settings Designer (`SettingsSingleFileGenerator`). Manual edits will be overwritten on regeneration.
|
||||
- **No settings defined here**: Despite the class name `Settings`, this file contains *no property declarations*. Any settings used at runtime must be defined in the corresponding `Settings.settings` file (not provided) or in `app.config`.
|
||||
- **Thread-safety caveat**: While `Synchronized()` ensures thread-safe *access*, it does *not* guarantee atomicity for compound operations (e.g., read-modify-write).
|
||||
- **Versioning ambiguity**: Assembly version is fixed at `1.0.0.0` (with `AssemblyFileVersion` identical), which may complicate deployment or rollback if settings schema evolves.
|
||||
- **COM visibility disabled**: `ComVisible(false)` means this module is not exposed to COM clients—intentional for a .NET-only module.
|
||||
@@ -0,0 +1,92 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/Resources/TranslateExtension.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/Resources/StringResources.Designer.cs
|
||||
generated_at: "2026-04-16T04:37:17.643250+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "41df486c1d53cd9a"
|
||||
---
|
||||
|
||||
# Resources
|
||||
|
||||
## Documentation: `TranslateExtension` Markup Extension
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
The `TranslateExtension` class is a WPF `MarkupExtension` used to enable localized string binding in XAML. It resolves a given string key at runtime by querying the `StringResources` strongly-typed resource class (which wraps the application’s `.resx`-based resources), returning the corresponding localized value. If the key is missing or empty, it returns a consistent fallback string (`#stringnotfound#` or `#stringnotfound# <key>`), allowing UI elements to gracefully handle missing translations. This extension is essential for internationalization of the HardwareList module’s UI.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
#### `TranslateExtension` class
|
||||
|
||||
- **Namespace**: `HardwareList`
|
||||
- **Base Type**: `System.Windows.Markup.MarkupExtension`
|
||||
|
||||
##### Constructor
|
||||
|
||||
```csharp
|
||||
public TranslateExtension(string key)
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `key` (`string`): The resource key used to look up a localized string in `StringResources`.
|
||||
- **Behavior**: Stores the key for later resolution during `ProvideValue`.
|
||||
|
||||
##### Override
|
||||
|
||||
```csharp
|
||||
public override object ProvideValue(IServiceProvider serviceProvider)
|
||||
```
|
||||
|
||||
- **Parameters**:
|
||||
- `serviceProvider` (`IServiceProvider`): WPF service provider (unused in current implementation).
|
||||
- **Returns**:
|
||||
- `string`: The localized string corresponding to `_key`, or a fallback string if the key is null/empty or not found.
|
||||
- **Behavior**:
|
||||
- If `_key` is `null` or empty → returns `"#stringnotfound#"`.
|
||||
- Otherwise, calls `StringResources.ResourceManager.GetString(_key)`.
|
||||
- If a matching resource exists → returns the string value.
|
||||
- If no match → returns `"#stringnotfound# " + _key`.
|
||||
|
||||
> **Note**: The `MarkupExtensionReturnType` attribute indicates the extension always returns a `string`.
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- `_key` is immutable after construction (no setter or mutation).
|
||||
- `StringResources.ResourceManager.GetString(key)` is assumed to be thread-safe (as per .NET `ResourceManager` behavior).
|
||||
- The fallback string `#stringnotfound#` is **hardcoded** and must not be localized itself.
|
||||
- Empty or null keys are treated identically and return the base fallback string (no key suffix).
|
||||
- If a key exists in `StringResources.Designer.cs` but the underlying `.resx` file lacks the entry, `GetString` returns `null`, triggering the fallback.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
#### Dependencies *on* this module:
|
||||
- **WPF Framework**: Requires `System.Windows.Markup` and `System` (for `ResourceManager`, `IServiceProvider`).
|
||||
- **`HardwareList.Resources.StringResources`**: This module depends on the auto-generated `StringResources` class for resource lookup.
|
||||
- **XAML Parser**: Used via `MarkupExtension` mechanism in XAML (e.g., `{local:Translate KeyName}`).
|
||||
|
||||
#### Dependencies *of* this module:
|
||||
- None beyond standard .NET libraries (`System`, `System.Windows`).
|
||||
- `StringResources` is generated from `.resx` files (not visible here), but the module assumes its existence and structure.
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **No caching of resolved values**: Each `ProvideValue` call re-queries `ResourceManager.GetString`, which is acceptable but could be optimized if performance becomes critical.
|
||||
- **Fallback format is not user-friendly**: The fallback `"#stringnotfound# <key>"` may appear in the UI if keys are missing—ensure translators or developers catch these during testing.
|
||||
- **Case sensitivity**: Resource keys are case-sensitive (e.g., `"Add"` ≠ `"add"`). A mismatch yields the fallback string.
|
||||
- **Culture handling**: Uses the current UI culture (`CultureInfo.CurrentUICulture`) implicitly via `ResourceManager.GetString`, unless `StringResources.Culture` is explicitly set (which is possible but not done here).
|
||||
- **No null-safety for `serviceProvider`**: While `serviceProvider` is unused, `ProvideValue` does not guard against null—though WPF guarantees non-null in normal usage.
|
||||
- **Auto-generated resource class**: `StringResources.Designer.cs` is auto-generated; manual edits will be overwritten. Ensure keys used in `TranslateExtension` exist in the `.resx` file.
|
||||
|
||||
> **None identified from source alone.**
|
||||
@@ -0,0 +1,67 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListOverdueView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListReplaceView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/SLICE6TreeView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListSelectView.xaml.cs
|
||||
- DataPRO/Modules/Hardware/HardwareList/View/HardwareListView.xaml.cs
|
||||
generated_at: "2026-04-16T04:38:01.309494+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "19f25015f9f12fa7"
|
||||
---
|
||||
|
||||
# View
|
||||
|
||||
### **Purpose**
|
||||
This module provides WPF view implementations for the hardware diagnostics hardware list feature, serving as the UI layer that binds to `IHardwareListViewModel` and related interfaces. It enables users to view, sort, filter, and manipulate hardware items—including overdue items, replaceable units, and SLICE6 associations—through a set of specialized views (`HardwareListView`, `HardwareListOverdueView`, `HardwareListReplaceView`, `HardwareListSelectView`, `SLICE6TreeView`). These views handle user interactions (e.g., column header clicks, button presses, tree node operations) and delegate business logic to the underlying view model, while also publishing `PageModifiedEvent` to signal state changes.
|
||||
|
||||
---
|
||||
|
||||
### **Public Interface**
|
||||
All classes implement interfaces in the `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` namespace (e.g., `IHardwareListView`, `IHardwareListOverdueView`). They expose no public methods beyond their constructors; all behavior is driven via event handlers wired in XAML. The interfaces they implement are assumed to define the contract for view-model binding, but the *actual* public surface is minimal and consists solely of:
|
||||
|
||||
| Class | Constructor | Notes |
|
||||
|-------|-------------|-------|
|
||||
| `HardwareListOverdueView()` | `public HardwareListOverdueView()` | Initializes component; handles `ListViewHeader_Click` for sorting overdue items. |
|
||||
| `HardwareListReplaceView()` | `public HardwareListReplaceView()` | Initializes component; handles `Replace_Click` to invoke `IHardwareListViewModel.Replace()`. |
|
||||
| `SLICE6TreeView()` | `public SLICE6TreeView()` | Initializes component; handles `Remove_Click`, `Add_Click`, and `Swap_Click` to manage SLICE6 associations and publish `PageModifiedEvent`. |
|
||||
| `HardwareListSelectView()` | `public HardwareListSelectView()` | Initializes component; provides `InitializeColumns(bool bSteamingTest)` to dynamically show/hide the `DSPStreamingColumn`. Also handles sorting, filtering, inclusion, and chain sample rate mixed button clicks. |
|
||||
| `HardwareListView()` | `public HardwareListView()` | Initializes component; handles search, sorting, double-click (via `MouseDoubleClick`), and tree view popup invocation (`TreeviewButton_Click`). |
|
||||
|
||||
> **Note**: No public methods beyond constructors exist in the source. All functionality is exposed via private event handlers (`ListViewHeader_Click`, `Replace_Click`, etc.) bound in XAML.
|
||||
|
||||
---
|
||||
|
||||
### **Invariants**
|
||||
- **View Model Contract**: All views assume their `DataContext` implements a specific interface (`IHardwareListViewModel`, `ISLICE6TreeNode`, or `IHardware`) and that required properties (e.g., `SelectedSLICE6`, `SelectedSLICE6DB`, `ShowCompact`) are non-null when used. Null checks are performed before use, but no fallback behavior is defined.
|
||||
- **Event Publishing**: In `SLICE6TreeView`, after `Associate`, `UnAssociate`, or `Swap` operations, a `PageModifiedEvent` with status `Modified` is *always* published—regardless of whether the operation succeeded or the tree node was valid.
|
||||
- **Column Management**: In `HardwareListSelectView.InitializeColumns`, the `CalDateColumn` index is used as a reference point for inserting `DSPStreamingColumn`; if `CalDateColumn` is not found (index < 0), index `0` is used as fallback.
|
||||
- **Sorting Consistency**: All column header click handlers (`ListViewHeader_Click`, `GridViewColumnHeader_OnClick`, `GridViewColumnHeaderCheckBox_OnClick`) invoke `Sort(..., true)`, implying ascending sort order is hardcoded (or `true` indicates a toggle flag—source does not clarify).
|
||||
- **Popup State**: In `HardwareListView.TreeviewButton_Click`, the `SLICE6TreeViewPopup` is explicitly closed before reassigning its `Child` and reopening—ensuring only one instance is active at a time.
|
||||
|
||||
---
|
||||
|
||||
### **Dependencies**
|
||||
**External Dependencies (imports):**
|
||||
- `System.Windows.*` (WPF core: `Controls`, `Data`, `Media`, `Input`)
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` — defines core interfaces: `IHardwareListOverdueView`, `IHardwareListReplaceView`, `ISLICE6TreeView`, `IHardwareListSelectView`, `IHardwareListView`, `IHardwareListViewModel`, `IHardware`, `ISLICE6TreeNode`.
|
||||
- `DTS.Common.Controls` — provides custom controls like `GridViewColumnHeaderSearchable`, `GridViewColumnHeaderSelectable`, `Popup` (`SLICE6TreeViewPopup`).
|
||||
- `DTS.Common.Utils` — utility methods: `Utils.FindChild<T>` (used in `HardwareListSelectView` and `HardwareListView` for tag resolution).
|
||||
- `Prism.Ioc`, `Prism.Events` — used in `SLICE6TreeView` to resolve `IEventAggregator` and publish `PageModifiedEvent`.
|
||||
|
||||
**Consumed by:**
|
||||
- The module’s view model layer (`IHardwareListViewModel` implementations) — binds to these views via `DataContext`.
|
||||
- Likely the main hardware list module shell (e.g., Prism module initialization) — instantiates and hosts these views.
|
||||
|
||||
---
|
||||
|
||||
### **Gotchas**
|
||||
- **Typo in `InitializeColumns` parameter**: The parameter is named `bSteamingTest`, likely intended to be `bStreamingTest` (note missing 'r'). This may cause confusion or mismatches in downstream code.
|
||||
- **Ambiguous sort flag**: All `Sort(..., true)` calls use a literal `true`. Without the interface definition or implementation, it is unclear whether this indicates ascending order, a toggle reset, or a secondary sort flag.
|
||||
- **Redundant null checks**: In `HardwareListSelectView` and `HardwareListView`, `sender` is cast to `Control` before checking `control.DataContext`. This is safe but verbose; could be simplified with pattern matching (e.g., `if (sender is Control control && control.DataContext is IHardwareListViewModel vm)`).
|
||||
- **EventAggregator resolution in SLICE6TreeView**: `ContainerLocator.Container.Resolve<IEventAggregator>()` is called *synchronously* on each `Add_Click`, `Remove_Click`, and `Swap_Click`. This is inefficient and violates Prism best practices (should be injected via constructor). No DI constructor is present, suggesting tight coupling to Prism’s static locator.
|
||||
- **Missing error handling**: All click handlers silently return on failed casts (e.g., `if (!(control.DataContext is IHardwareListViewModel vm)) { return; }`). No logging or user feedback occurs if expectations are violated.
|
||||
- **`GetCurrentIndex` logic**: In `HardwareListView`, `GetCurrentIndex` iterates over all items and uses `VisualTreeHelper.GetDescendantBounds` and `IsMouseOverTarget` to determine the clicked item. This is computationally expensive for large lists and may be fragile if item containers are virtualized or not yet generated.
|
||||
|
||||
> **None identified from source alone.** → *Not applicable; multiple gotchas found.*
|
||||
@@ -0,0 +1,280 @@
|
||||
---
|
||||
source_files:
|
||||
- DataPRO/Modules/Hardware/HardwareList/ViewModel/HardwareListViewModel.cs
|
||||
generated_at: "2026-04-16T04:37:43.305054+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "529cbbf4accc9016"
|
||||
---
|
||||
|
||||
# ViewModel
|
||||
|
||||
**Documentation: HardwareListViewModel.cs**
|
||||
|
||||
---
|
||||
|
||||
### 1. **Purpose**
|
||||
|
||||
The `HardwareListViewModel` class serves as the central MVVM ViewModel for the hardware list UI module in the DASFactory diagnostics system. It manages the presentation and interaction logic for hardware inventory—including filtering, sorting, selection, calibration status tracking, sample rate configuration, and SLICE6/SLICE6DB association management. It aggregates raw hardware data from `DTS.Common.ISO.Hardware.GetAllDAS`, wraps it in `HardwareModel` instances, and exposes structured collections (`Hardware`, `OverdueHardware`, `AvailableHardware`, etc.) to views. It also coordinates inter-view communication via Prism’s `IEventAggregator`, handles user actions (e.g., editing, replacing, associating hardware), and enforces domain-specific rules such as parent–child DAS sample rate consistency and channel assignment tracking during hardware replacement.
|
||||
|
||||
---
|
||||
|
||||
### 2. **Public Interface**
|
||||
|
||||
All methods and properties are `public` unless otherwise noted. The class implements `IHardwareListViewModel` (inferred from `: IHardwareListViewModel`).
|
||||
|
||||
#### **Constructors**
|
||||
- **`HardwareListViewModel(IHardwareListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer)`**
|
||||
Initializes the ViewModel with required dependencies, sets up event subscriptions (`RaiseNotification`, `BusyIndicatorChangeNotification`), and initializes `SelectedHardwareItems` as an `ObservableCollection<IHardware>`.
|
||||
|
||||
#### **Public Methods**
|
||||
- **`void LoadTreeView(string serialNumber)`**
|
||||
Populates `SLICE6TreeNodes`, `AvailableSLICE6`, `SelectedSLICE6DB`, and `AvailableSLICE6DB` for the given SLICE6DB serial number using `SLICE6TreeNode.GetTreeNodes()` and `HardwareModel.GetAvailableSLICE6DB()`.
|
||||
|
||||
- **`void GetHardware(bool bIncludeModules, bool bIncludeOverdue, bool bIncludeBridges, int? testId, int? groupId)`**
|
||||
Loads and processes hardware from `DTS.Common.ISO.Hardware.GetAllDAS()`, constructs `HardwareModel` instances, aggregates channel counts for parent DAS with child modules, and filters based on overdue status and inclusion flags. Stores results in `_allHardware`, then calls `Filter()` and `Sort()`.
|
||||
|
||||
- **`void SetTestSampleRates(Dictionary<string, double> testSampleRates)`**
|
||||
Applies sample rates from `testSampleRates` to all hardware in `_allHardware`. If a rate is unavailable, uses the next highest available rate. Updates `TestSampleRate`, `SelectedSampleRateIndex`, and calls `SetDSPRate()` and `CheckForMixedDAS()`.
|
||||
|
||||
- **`void UpdateTestSampleRate(string childSerialNumber, double testSampleRate)`**
|
||||
Updates sample rate and AAF rate for a specific child hardware (by `SerialNumber`), then updates DSP filter rate.
|
||||
|
||||
- **`void SetTestAAFRates(Dictionary<string, float> testAAFRates)`**
|
||||
Applies AAF rates from `testAAFRates`. If missing for a hardware item, computes default via `GetAAFForHardware()` and logs a warning via `PageErrorEvent`.
|
||||
|
||||
- **`void UpdateTestAAFilterRate(string childSerialNumber, float testAAFilterRate)`**
|
||||
Updates AAF rate for a specific hardware item.
|
||||
|
||||
- **`void SetTestClockMasters(Dictionary<string, bool> testClockMasters)`**
|
||||
Sets `IsClockMaster` for hardware whose `SerialNumber` appears in the dictionary.
|
||||
|
||||
- **`void UpdateTestClockMaster(string childSerialNumber, bool testClockMaster)`**
|
||||
Sets `IsClockMaster` for a specific hardware item.
|
||||
|
||||
- **`void SetTestPTPDomainIDs(Dictionary<string, byte> testPTPDomainIDs)`**
|
||||
Sets `PTPDomainID` for hardware whose `SerialNumber` appears in the dictionary.
|
||||
|
||||
- **`void UpdateTestPTPDomainID(string childSerialNumber, byte ptpDomainId)`**
|
||||
Sets `PTPDomainID` for a specific hardware item.
|
||||
|
||||
- **`void CheckForMixedDAS(string nonParentSerialNumber, double testSampleRate)`**
|
||||
Ensures sample rate consistency between a child DAS and its parent. If siblings have differing rates, marks the parent as `MixedRates = true`; otherwise, aligns parent rate to child.
|
||||
|
||||
- **`void SetParentMixedRates(string parentDAS, bool mixedRates)`**
|
||||
Sets `MixedRates` property on the parent DAS.
|
||||
|
||||
- **`void SetHasIncludedChildren()`**
|
||||
Sets `HasIncludedChildren = true` for distributors that have at least one included child.
|
||||
|
||||
- **`bool AnyChildren(string distributorDAS)`**
|
||||
Returns `true` if any included hardware has `ParentDAS == distributorDAS`.
|
||||
|
||||
- **`void Filter(object tag, string term)`**
|
||||
Updates filter criteria for a specific field (`Fields` enum) and re-applies filtering.
|
||||
|
||||
- **`void Filter(string term)`**
|
||||
Applies `_currentSearchTerm` and field-specific filters to `_allHardware`, populating `Hardware` and `OverdueHardware`. Handles compact view logic (hides rack modules under certain conditions) and recalculates channel counts.
|
||||
|
||||
- **`void Sort(object o, bool bColumnClick)`**
|
||||
Sorts `Hardware` by field (`HardwareListTags`) and direction (toggle on repeated column click). Uses `HardwareComparer`.
|
||||
|
||||
- **`void SortOverdue(object o, bool bColumnClick)`**
|
||||
Sorts `OverdueHardware` similarly.
|
||||
|
||||
- **`void SetIncluded(string[] serialNumbers, bool included)`**
|
||||
Sets `Included` flag for hardware matching `serialNumbers` in the *filtered* `Hardware` list.
|
||||
|
||||
- **`void SetIncluded(int[] ids)`**
|
||||
Sets `Included = true` for hardware matching `DASId` in `_allHardware`.
|
||||
|
||||
- **`void IncludeChildren(IHardware hardware)`**
|
||||
Sets `Included` for all child modules (via `IsPseudoRackModule()`) of the given hardware to match its `Included` value.
|
||||
|
||||
- **`void RemoveMultipleButton(IHardware hardware)`**
|
||||
Clears sample rate display (`TestSampleRate = 0`) and `MixedRates` flag for the given hardware.
|
||||
|
||||
- **`void Unset()`**
|
||||
Resets all hardware collections, SLICE6 associations, and channel assignments; publishes `ListViewStatusEvent.Unloaded`.
|
||||
|
||||
- **`void ClearAllFilters()`**
|
||||
Clears `_filterByField`.
|
||||
|
||||
- **`void Cleanup()` / `Task CleanupAsync()` / `void Initialize()` / `Task InitializeAsync()` / `void Activated()`**
|
||||
No-op stubs (likely required by Prism interfaces).
|
||||
|
||||
- **`void SaveSLICE6Associations(string serialNumber)`**
|
||||
Commits SLICE6 associations to DB via `SLICE6TreeNode.SaveAssociations()`. If `_swappedHardware` is set, swaps nodes first.
|
||||
|
||||
- **`void Associate(ISLICE6TreeNode node)`**
|
||||
Adds a `SLICE6TreeNode` to `SLICE6TreeNodes`, assigns `Number`, `Port`, `PositionOnChain`, and removes from `AvailableSLICE6`.
|
||||
|
||||
- **`void Associate(IHardware node)`**
|
||||
Sets `_swappedHardware`, reloads tree view for `node.SerialNumber`, and updates `AvailableSLICE6`/`SLICE6TreeNodes`.
|
||||
|
||||
- **`void UnAssociate(ISLICE6TreeNode node)`**
|
||||
Removes `node` from `SLICE6TreeNodes`, renumbers remaining nodes, resets its metadata, and adds back to `AvailableSLICE6`.
|
||||
|
||||
- **`void Replace()`**
|
||||
Commits hardware replacement: sets `ReplacementHardware.Included = true`, publishes `HardwareReplaceEvent`, and clears `HardwareToReplace`/`ReplacementHardware`.
|
||||
|
||||
- **`IHardware[] GetSelectedItems()`**
|
||||
Returns `SelectedHardwareItems.ToArray()`.
|
||||
|
||||
- **`void SetCalPeriods(...)`**
|
||||
Sets all `*CalPeriod` properties (e.g., `G5CalPeriod`, `SLICE6_CalPeriod`) for use in `HardwareModel` construction.
|
||||
|
||||
#### **Public Properties**
|
||||
- **`IHardwareListView View`, `IHardwareListOverdueView OverdueView`, `IHardwareListSelectView SelectView`, `IHardwareListReplaceView ReplaceView`, `ISLICE6TreeView SLICE6TreeView`**
|
||||
View interfaces bound to this ViewModel.
|
||||
|
||||
- **`InteractionRequest<Notification> NotificationRequest`, `InteractionRequest<Confirmation> ConfirmationRequest`**
|
||||
Prism interaction triggers for modal dialogs.
|
||||
|
||||
- **`event PropertyChangedEventHandler PropertyChanged`**
|
||||
Standard `INotifyPropertyChanged` implementation.
|
||||
|
||||
- **`IHardware[] Hardware`**
|
||||
Filtered and sorted list of hardware for display.
|
||||
|
||||
- **`IHardware[] OverdueHardware`**
|
||||
Hardware with `CalDueDate <= DateTime.Today`.
|
||||
|
||||
- **`IHardware[] AvailableHardware`**
|
||||
Hardware suitable for replacement (excludes included items, matches `HardwareType`, respects rack size constraints).
|
||||
|
||||
- **`IHardware HardwareToReplace`, `IHardware ReplacementHardware`**
|
||||
Current hardware being replaced and its candidate replacement.
|
||||
|
||||
- **`Model.HardwareChannelAssignment[] AssignedChannels`**
|
||||
Channels assigned to `HardwareToReplace` (populated in `InitializeReplace()` and `PopulateAvailableHardware()`).
|
||||
|
||||
- **`ISLICE6TreeNode[] SLICE6TreeNodes`, `ISLICE6TreeNode[] AvailableSLICE6`**
|
||||
Associated and available SLICE6 units for a given SLICE6DB.
|
||||
|
||||
- **`IHardware[] AvailableSLICE6DB`**
|
||||
SLICE6DB units available for association.
|
||||
|
||||
- **`bool ShowCompact`**
|
||||
Controls whether rack modules are hidden (default `true`). Triggers re-filtering and publishes `HardwareListShowCompactEvent`.
|
||||
|
||||
- **`ObservableCollection<IHardware> SelectedHardwareItems`**
|
||||
Tracks selected hardware items; raises `HardwareListHardwareSelectedEvent` on change.
|
||||
|
||||
- **`bool IsBusy`**
|
||||
Bound to busy indicator; set via `BusyIndicatorChangeNotification` event.
|
||||
|
||||
- **`bool IsDirty`**
|
||||
Always `false`; not updated anywhere in source.
|
||||
|
||||
- **`string ListViewId => "HardwareListView"`**
|
||||
Identifier for the view.
|
||||
|
||||
- **`int TDASCalPeriod`, `int G5CalPeriod`, ..., `int SLICE_PRO_CAN_FD_CalPeriod`**
|
||||
Calibration period constants passed to `HardwareModel`.
|
||||
|
||||
- **`IStreamingFilterProfile StreamingDSPProfile`**
|
||||
Used to compute `DSPStreamingFilter` via `GetDSPFilterRate()`.
|
||||
|
||||
#### **Internal/Protected Methods (Not Public Interface)**
|
||||
- **`void FireAAFilterRate(...)`, `FireSampleRate(...)`, `FireClockMaster(...)`, `FireIncluded(...)`, `FirePTPDomainID(...)`**
|
||||
Publish corresponding `HardwareListHardware*Event` instances.
|
||||
|
||||
- **`private void FireSelectionChanged()`**
|
||||
Publishes `HardwareListHardwareSelectedEvent` with selected serial numbers.
|
||||
|
||||
- **`private void Hardware_PropertyChanged(...)`**
|
||||
Handles `TestAAFilterRateHz` changes to call `SetDSPRate()`.
|
||||
|
||||
- **`private void SetDSPRate(HardwareModel hardware)`**, **`private void UpdateDSP(HardwareModel hardware)`**
|
||||
Computes `DSPStreamingFilter` using `StreamingDSPProfile`.
|
||||
|
||||
- **`private double GetNextHighestAvailableSampleRate(...)`**
|
||||
Helper for `SetTestSampleRates`.
|
||||
|
||||
- **`internal float GetAAFForHardware(IISOHardware h, int sampleRate)`**
|
||||
Returns AAF rate based on DAS type (TDAS vs SLICE).
|
||||
|
||||
- **`private bool AnyMixedChildren(...)`**, **`private void PopulateAvailableHardware()`**, **`private void OnRaiseNotification(...)`, `OnBusyIndicatorNotification(...)`**
|
||||
Internal helpers.
|
||||
|
||||
---
|
||||
|
||||
### 3. **Invariants**
|
||||
|
||||
- **Hardware Uniqueness**: `_allHardware` must contain no duplicate `SerialNumber`s. Duplicates are logged via `APILogger.Log()` during `GetHardware()`.
|
||||
|
||||
- **Parent–Child Sample Rate Consistency**: For any child DAS with `ParentDAS` set, `CheckForMixedDAS()` ensures the parent’s `MixedRates` flag reflects whether any included siblings have differing `TestSampleRate`. If all children match, the parent’s rate is updated to match.
|
||||
|
||||
- **Calibration Overdue Logic**: `OverdueHardware` includes all hardware where `CalDueDate <= DateTime.Today`. This is recomputed on every `Filter()` call.
|
||||
|
||||
- **Channel Aggregation for Parent DAS**: When `bIncludeModules == false`, parent DAS channel counts (`AnalogChannels`, `SquibChannels`, etc.) are aggregated from included child modules. If a parent has only one analog channel, it is reset to `0` before adding child channels.
|
||||
|
||||
- **SLICE6 Association Integrity**: `SLICE6TreeNode.Number`, `Port`, and `PositionOnChain` are managed during `Associate()`/`UnAssociate()` to maintain ordering and uniqueness.
|
||||
|
||||
- **Replacement Hardware Constraints**: In `PopulateAvailableHardware()`, replacement hardware must match `HardwareType`. For `TDAS_Pro_Rack`, replacement must have `MaxModules >=` original’s `MaxModules`.
|
||||
|
||||
- **Filtering Scope**: `Filter(string term)` operates on `_allHardware`, but `SetIncluded(string[])` operates on the *filtered* `Hardware` list.
|
||||
|
||||
---
|
||||
|
||||
### 4. **Dependencies**
|
||||
|
||||
#### **Imports/Usings**
|
||||
- **Core**: `System.Collections.Generic`, `System.Linq`, `System.Threading.Tasks`, `System.ComponentModel`, `System.Collections.Specialized`.
|
||||
- **Prism**: `Prism.Regions`, `Prism.Events`, `Unity` (`IUnityContainer`, `IRegionManager`, `IEventAggregator`).
|
||||
- **Common Libraries**:
|
||||
- `DTS.Common.Classes.Hardware`, `DTS.Common.Enums.Hardware`, `DTS.Common.Events.Hardware.HardwareList`
|
||||
- `DTS.Common.Interface.DASFactory.Diagnostics.HardwareList` (e.g., `IHardwareListView`, `ISLICE6TreeNode`)
|
||||
- `HardareList.Model` (e.g., `HardwareModel`, `HardwareChannelAssignment`)
|
||||
- `DTS.Common.Interface.TestSetups.TestSetupsList` (`ITestSetup`)
|
||||
- `DTS.Common.Utilities.Logging` (`APILogger`)
|
||||
- `DTS.Common.Classes.DSP` (`IStreamingFilterProfile`)
|
||||
- `DTS.Common.Interactivity` (`InteractionRequest<T>`)
|
||||
|
||||
#### **External Types Referenced**
|
||||
- `IHardware`, `IISOHardware`, `HardwareModel`, `ISLICE6TreeNode`, `ISLICE6TreeView`, `ITestSetup`, `HardwareTypes`, `SerializableAAF.DAS_TYPE`, `DTS.Common.ClockSyncProfile`, `DTS.Common.ISO.Hardware`, `DFConstantsAndEnums.TSRAIR_ValidSampleRates`.
|
||||
|
||||
#### **Event Types Published/Consumed**
|
||||
- **Consumed**: `RaiseNotification`, `BusyIndicatorChangeNotification`, `PageErrorEvent`.
|
||||
- **Published**: `HardwareListEditHardwareEvent`, `HardwareListHardwareTestAAFilterRateEvent`, `HardwareListHardwareTestSampleRateEvent`, `HardwareListHardwareTestClockMasterEvent`, `HardwareListHardwareIncludedEvent`, `HardwareListHardwareSelectedEvent`, `HardwareListHardwareTestPTPDomainIDEvent`, `HardwareReplaceEvent`, `HardwareListShowCompactEvent`, `ListViewStatusEvent`.
|
||||
|
||||
#### **Dependents**
|
||||
- Views (`IHardwareListView`, `IHardwareListOverdueView`, etc.) bind to this ViewModel.
|
||||
- Other modules subscribe to its published events (e.g., `HardwareReplaceEvent`).
|
||||
|
||||
---
|
||||
|
||||
### 5. **Gotchas**
|
||||
|
||||
- **`IsDirty` is never set**: The property is declared but always `false`. This may indicate incomplete implementation or unused state tracking.
|
||||
|
||||
- **`HardwareFilter` uses `Fields` enum, but `Filter(string term)` uses `_currentSearchTerm` for global search**: Field-specific filters are stored in `_filterByField`, but the primary `Filter(string term)` method only uses `_currentSearchTerm`. This may cause confusion—field filters are only applied via `Filter(object tag, string term)`.
|
||||
|
||||
- **`SetTestSampleRates` silently overrides unavailable rates**: If a requested sample rate is not in `hardware._availableSampleRates`, it jumps to the next highest *without user confirmation*. This could mask configuration errors.
|
||||
|
||||
- **`GetAAFForHardware` uses `DASTypeEnum` to choose between `TDAS` and `SLICE` AAF profiles**: The `default` case assumes all non-TDAS hardware is SLICE, which may be incorrect for future hardware types.
|
||||
|
||||
- **`SLICE6TreeNode.Number` assignment assumes sequential numbering**: `node.Number = 1 + SLICE6TreeNodes.Length` may cause conflicts if nodes are added out-of-order or reloaded from persistent state.
|
||||
|
||||
- **`Hardware_PropertyChanged` only handles `TestAAFilterRateHz`**: Other property changes (e.g., `Included`, `TestSampleRate`) do not trigger DSP recalculation unless explicitly handled elsewhere (e.g., `SetTestSampleRates`).
|
||||
|
||||
- **`Unset()` does not clear `_dasIdToChannels`**: While `InitializeReplace()` clears it, `Unset()` does not. If `Unset()` is called mid-replace operation, stale channel assignments may persist.
|
||||
|
||||
- **`ShowCompact` triggers re-filtering but not re-sorting**: Changing `ShowCompact` calls `Filter()` but not `Sort()`, potentially leaving the list in an inconsistent order until the user re-sorts.
|
||||
|
||||
- **`SelectedHardwareItems.CollectionChanged` handler `SelectedHardwareItemsOnCollectionChanged` calls `FireSelectionChanged()`**: This may fire multiple times if items are added/removed in bulk (e.g., via `SetIncluded()`), though `SelectedItemsStatus.GetUpdating()` is checked in `FireSelectionChanged()` (source of `SelectedItemsStatus` not provided—behavior uncertain).
|
||||
|
||||
- **`GetHardware()` aggregates child channels only when `bIncludeModules == false`**: When `bIncludeModules == true`, parent DAS channel counts are *not* aggregated, leading to inconsistent channel counts depending on view mode.
|
||||
|
||||
- **`GetAAFForHardwareFunc` is a public property**: Allows external override of AAF computation logic, but no usage is shown in this file.
|
||||
|
||||
- **`IsEdit`, `IsMenuIncluded`, `IsNavigationIncluded` are exposed but never set in this file**: Their purpose is unclear without context from other modules.
|
||||
|
||||
- **Typo in namespace import**: `using HardareList.Model;` (missing 'd' in "Hardware")—likely a ReSharper suppression or legacy artifact.
|
||||
|
||||
- **`SLICE6TreeNode.SwapNodes()` and `SaveAssociations()` are called in `SaveSLICE6Associations()`**: The order (swap first, then save) may be critical for data integrity, but no error handling is visible.
|
||||
|
||||
- **`SelectedHardwareItems` is initialized as `new ObservableCollection<IHardware>()` but never cleared in `Unset()`**: `Unset()` reassigns `SelectedHardwareItems = null`? No—`Unset()` does not modify it. This may leave stale selections after unloading.
|
||||
|
||||
- **`Hardware` and `OverdueHardware` arrays are reassigned directly**: This bypasses `OnPropertyChanged` unless explicitly triggered (e.g., `OnPropertyChanged("Hardware")`), which is done—but only after sorting/filtering. Direct array mutation (e.g
|
||||
Reference in New Issue
Block a user