This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -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 Prisms `IEventAggregator`, handles user actions (e.g., editing, replacing, associating hardware), and enforces domain-specific rules such as parentchild 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()`.
- **ParentChild Sample Rate Consistency**: For any child DAS with `ParentDAS` set, `CheckForMixedDAS()` ensures the parents `MixedRates` flag reflects whether any included siblings have differing `TestSampleRate`. If all children match, the parents 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 >=` originals `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