using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Composition; using System.Linq; using System.Threading.Tasks; using DTS.Common.Classes.Hardware; using DTS.Common.Enums.Hardware; using DTS.Common.Events; using DTS.Common.Events.Hardware.HardwareList; using DTS.Common.Interface.DASFactory.Diagnostics.HardwareList; using HardareList.Model; using DTS.Common.Interface.DASFactory.Diagnostics; using DTS.Common.Interface.TestSetups.TestSetupsList; using DTS.Common.Enums; using DTS.Common.Utilities.Logging; using DTS.Common.Enums.DASFactory; using DTS.Common.Classes.DSP; using DTS.Common.Interactivity; using Unity; using Prism.Regions; using Prism.Events; // ReSharper disable CheckNamespace // ReSharper disable MemberCanBePrivate.Global // ReSharper disable InconsistentNaming namespace HardwareList { /// /// this class handles HardwareList functionality /// [PartCreationPolicy(CreationPolicy.Shared)] public class HardwareListViewModel : IHardwareListViewModel { /// /// The SensorList view /// public IHardwareListView View { get; set; } public IHardwareListOverdueView OverdueView { get; set; } public IHardwareListSelectView SelectView { get; set; } public IHardwareListReplaceView ReplaceView { get; set; } /// /// 14465 Request for tree view of SLICE 6/Slice 6 Air hardware view /// this is a view for SLICE6 tree (S6DB/SL6.../SL6) /// public ISLICE6TreeView SLICE6TreeView { get; set; } private IEventAggregator _eventAggregator { get; } private IRegionManager _regionManager; private IUnityContainer UnityContainer { get; } public InteractionRequest NotificationRequest { get; } public InteractionRequest ConfirmationRequest { get; } /// /// /// Occurs when a property value changes. /// public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #region constructors and initializers /// /// Creates a new instance of the HardwareListViewModel /// /// /// The logical placeholder defined within the application's UI (in the shell or within views) into which views are displayed. /// The EventAggregator which allows different components to publish/subscribe to events without being coupled to each other. /// The unityContainer. public HardwareListViewModel(IHardwareListView view, IRegionManager regionManager, IEventAggregator eventAggregator, IUnityContainer unityContainer) { View = view; View.DataContext = this; NotificationRequest = new InteractionRequest(); ConfirmationRequest = new InteractionRequest(); _eventAggregator = eventAggregator; UnityContainer = unityContainer; _regionManager = regionManager; _eventAggregator.GetEvent().Subscribe(OnRaiseNotification); _eventAggregator.GetEvent() .Subscribe(OnBusyIndicatorNotification, ThreadOption.PublisherThread, true); SelectedHardwareItems = new ObservableCollection(); } #endregion #region Methods /// /// loads tree for given hardware /// /// public void LoadTreeView(string serialNumber) { SLICE6TreeNodes = SLICE6TreeNode.GetTreeNodes(serialNumber); SelectedSLICE6 = null; AvailableSLICE6 = SLICE6TreeNode.GetAvailableTreeNodes(serialNumber); SelectedSLICE6DB = null; AvailableSLICE6DB = HardwareModel.GetAvailableSLICE6DB(serialNumber); } public void SetCache(IISOHardware[] hardware) { _cachedHardware.Clear(); } public void MouseDoubleClick(int index) { if (index >= 0 && index < Hardware.Length && SelectedHardwareItems.Count == 1) { _eventAggregator.GetEvent().Publish(Hardware[index].SerialNumber); } } public void FireAAFilterRate(IHardware hardware, string testAAFilterRate) { _eventAggregator.GetEvent() .Publish(new HardwareListHardwareTestAAFilterRateEventArgs(hardware.SerialNumber, Convert.ToSingle(testAAFilterRate), hardware.DASId)); } public void FireSampleRate(IHardware hardware, string testSampleRate) { _eventAggregator.GetEvent() .Publish(new HardwareListHardwareTestSampleRateEventArgs(hardware.SerialNumber, Convert.ToDouble(testSampleRate), hardware.DASId)); } public void FireClockMaster(IHardware hardware, bool isClockMaster) { _eventAggregator.GetEvent() .Publish(new HardwareListHardwareTestClockMasterEventArgs(hardware.SerialNumber, isClockMaster, hardware.DASId)); } public void FireIncluded(IHardware hardware) { _eventAggregator.GetEvent() .Publish(new HardwareListHardwareIncludedEventArgs(hardware.SerialNumber, hardware.Included, hardware.DASId)); } private void FireSelectionChanged() { if (SelectedItemsStatus.GetUpdating(SelectedHardwareItems)) { return; } _eventAggregator.GetEvent() .Publish(_selectedHardwareItems.Select(hw => hw.SerialNumber).ToArray()); } public void FirePTPDomainID(IHardware hardware, byte ptpDomainID) { _eventAggregator.GetEvent() .Publish(new HardwareListHardwareTestPTPDomainIDEventArgs(hardware.SerialNumber, hardware.DASId, ptpDomainID)); } private Dictionary> _dasIdToChannels = new Dictionary>(); /// /// initializes the replace view with data /// public void InitializeReplace(ITestSetup testSetup, IsoViewMode viewMode) { //16079 Strange UI behavior when replacing SPS with generic SPS in test setup. I get the channel list //make sure we don't carry over das channel assignments from a previous load _dasIdToChannels.Clear(); var included = (from h in Hardware where h.Included select h).ToArray(); HardwareInTest = included; var channels = testSetup.GetChannels(); foreach (var ch in channels) { if (ch.IsBlank() || ch.IsDisabled) { continue; } if (!ch.SensorValid) { continue; } if (!ch.HardwareValid) { continue; } if (!_dasIdToChannels.ContainsKey(ch.DASId)) { _dasIdToChannels[ch.DASId] = new List(); } _dasIdToChannels[ch.DASId].Add(new Model.HardwareChannelAssignment(ch.HardwareChannel.ToString(), ch.Sensor, ch.GetChannelName(viewMode))); } } public void GetHardware(bool bIncludeModules, bool bIncludeOverdue, bool bIncludeBridges, int? testId, int? groupId) { var das = DTS.Common.ISO.Hardware.GetAllDAS(null, null); var list = new List(); var notIncludedModules = new List(); foreach (var d in das) { if (d.StandIn) { if (null != testId) { if (null != d.TestId) { if (testId != (int)d.TestId) { continue; } } else { continue; } } else { continue; } } var hardware = new HardwareModel(d, TDASCalPeriod, G5CalPeriod, SLICE1CalPeriod, SLICE2_CalPeriod, SLICE1_5CalPeriod, SLICE6_CalPeriod, POWERPRO_CalPeriod, SLICE6Air_CalPeriod, SLICE6AirBridge_CalPeriod, SLICE6DB_CalPeriod, TSRAir_CalPeriod, SLICETC_CalPeriod, SLICE_PRO_CAN_FD_CalPeriod, this); if (d.IsModule && !d.IsPseudoRackModule() && !bIncludeBridges) { continue; } if (d.IsPseudoRackModule() && !bIncludeModules) { notIncludedModules.Add(hardware); } if (hardware.CalDueDate <= DateTime.Today) { if(!bIncludeOverdue) { continue; }; } hardware.PropertyChanged += Hardware_PropertyChanged; list.Add(hardware); } var lookup = new Dictionary(); foreach (var s in list) { if (lookup.ContainsKey(s.SerialNumber)) { APILogger.Log($"Unexpected duplicates in hardware list, {s.SerialNumber}"); } else { lookup[s.SerialNumber] = s; } } var tempList = new List(list); tempList.AddRange(notIncludedModules); var processed = new HashSet(); foreach (var d in tempList) { //was finding duplicates in this list which was throwing off channel counts ... //so this eliminates the double counts if (processed.Contains(d.SerialNumber)) { continue; } processed.Add(d.SerialNumber); if (!string.IsNullOrWhiteSpace(d.ParentDAS)) { if (lookup.ContainsKey(d.ParentDAS)) { var parent = lookup[d.ParentDAS]; if (null != d.MaxSampleRate) { if (null == parent.MaxSampleRate) { parent.MaxSampleRate = d.MaxSampleRate; } else if (parent.MaxSampleRate > d.MaxSampleRate) { parent.MaxSampleRate = d.MaxSampleRate; } } if (!bIncludeModules) { if (null != d.CalDate) { if (null == parent.CalDate) { parent.CalDate = d.CalDate; } else if (parent.CalDate > d.CalDate) { parent.CalDate = d.CalDate; } } if (null != d.CalDueDate) { if (null == parent.CalDueDate) { parent.CalDueDate = d.CalDueDate; } else if (parent.CalDueDate > d.CalDueDate) { parent.CalDueDate = d.CalDueDate; } } } if (1 == parent.AnalogChannels) { parent.AnalogChannels = 0; } parent.AnalogChannels += d.AnalogChannels; parent.SquibChannels += d.SquibChannels; parent.DigitalInChannels += d.DigitalInChannels; parent.DigitalOutChannels += d.DigitalOutChannels; parent.UartChannels += d.UartChannels; parent.StreamOutChannels += d.StreamOutChannels; } } } _allHardware = list.ToArray(); Filter(_currentSearchTerm); Sort(_sortField.ToString(), false); SortOverdue(_overdueSortField.ToString(), false); } private void Hardware_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "TestAAFilterRateHz") { if (sender is HardwareModel h) { SetDSPRate(h); } } } public void GetAvailableSampleRates(int[] availableSampleRates) { var ratesToUse = availableSampleRates; foreach (HardwareModel hardware in _allHardware) { if (hardware.IsTSRAIR) { ratesToUse = DFConstantsAndEnums.TSRAIR_ValidSampleRates; } else { ratesToUse = availableSampleRates; } var s = new List(); var sampleRates = new List(); foreach (var sps in ratesToUse) { var d = Convert.ToDouble(sps); s.Add(d.ToString("N0")); sampleRates.Add(d); } hardware._availableSampleRates = sampleRates; hardware.AvailableSampleRates = s.ToArray(); } } private double GetNextHighestAvailableSampleRate(Dictionary testSampleRates, HardwareModel hardware) { var requestedRate = testSampleRates[hardware.SerialNumber]; foreach (var sampleRate in hardware._availableSampleRates) { testSampleRates[hardware.SerialNumber] = sampleRate; if (sampleRate > requestedRate) { break; } } return testSampleRates[hardware.SerialNumber]; } public void SetTestSampleRates(Dictionary testSampleRates) { foreach (HardwareModel hardware in _allHardware) { if (hardware._availableSampleRates.IndexOf(testSampleRates[hardware.SerialNumber]) == -1 && !hardware.IsTSRAIR) { //The specified sample rate isn't available, so use the next highest testSampleRates[hardware.SerialNumber] = GetNextHighestAvailableSampleRate(testSampleRates, hardware); } hardware.TestSampleRate = testSampleRates[hardware.SerialNumber]; hardware.SelectedSampleRateIndex = hardware._availableSampleRates.IndexOf(hardware.TestSampleRate); if (!string.IsNullOrWhiteSpace(hardware.ParentDAS)) { //This is not a parent DAS, so if it has a parent, see if it has siblings with a different rate CheckForMixedDAS(hardware.SerialNumber, hardware.TestSampleRate); } SetDSPRate(hardware); } } private void SetDSPRate(HardwareModel hardware) { hardware.DSPStreamingFilter = StreamingDSPProfile?.GetDSPFilterRate(hardware.TestSampleRate, ((DTS.Common.ISO.Hardware)hardware.Hardware)?.DASTypeEnum.ToString() ?? "") ?? double.NaN; } public void UpdateTestSampleRate(string childSerialNumber, double testSampleRate) { foreach (HardwareModel hardware in _allHardware) { if (hardware.SerialNumber == childSerialNumber) { hardware.TestAAFilterRateHz = GetAAFForHardware((IISOHardware)hardware.Hardware, (int)testSampleRate); hardware.TestSampleRate = testSampleRate; hardware.SelectedSampleRateIndex = hardware._availableSampleRates.IndexOf(hardware.TestSampleRate); break; } UpdateDSP(hardware); } } private void UpdateDSP(HardwareModel hardware) { if (null == StreamingDSPProfile) { hardware.DSPStreamingFilter = double.NaN; } hardware.DSPStreamingFilter = StreamingDSPProfile.GetDSPFilterRate(hardware.TestSampleRate, hardware.HardwareType); } public void SetTestAAFRates(Dictionary testAAFRates) { bool shown = false; var keys = string.Join(", ", testAAFRates.Keys); foreach (HardwareModel hardware in _allHardware) { //FB 18857 if the testAAFRates dictionary does not have the AAFRate we will warn the user and get the default and use that value. if (testAAFRates.ContainsKey(hardware.SerialNumber)) { hardware.TestAAFilterRateHz = testAAFRates[hardware.SerialNumber]; } else { if (hardware.Hardware == null) { APILogger.Log("Hardware is null in SetTestAAFRates"); return; } var newAAF = GetAAFForHardware((IISOHardware)hardware.Hardware, (int)hardware.TestSampleRate); APILogger.Log($"testAAFRates dictionary does not contain AAFilterRate for SerialNumber {hardware.SerialNumber} in {keys}. The previous value of TestAAFilterRateHz was { hardware.TestAAFilterRateHz} and the new value is {newAAF} "); hardware.TestAAFilterRateHz = newAAF; if (!shown) { _eventAggregator.GetEvent().Publish(new PageErrorArg(new[] { Resources.StringResources.SetTestAAFRatesWarning }, null)); shown = true; } } } } public void UpdateTestAAFilterRate(string childSerialNumber, float testAAFilterRate) { foreach (HardwareModel hardware in _allHardware) { if (hardware.SerialNumber == childSerialNumber) { hardware.TestAAFilterRateHz = testAAFilterRate; break; } } } internal float GetAAFForHardware(IISOHardware h, int sampleRate) { switch (h.DASTypeEnum) { case HardwareTypes.DIM: case HardwareTypes.G5INDUMMY: case HardwareTypes.G5VDS: case HardwareTypes.SIM: case HardwareTypes.TDAS_Pro_Rack: case HardwareTypes.TDAS_LabRack: case HardwareTypes.TOM: return GetAAFForHardwareFunc(SerializableAAF.DAS_TYPE.TDAS, sampleRate); default: return GetAAFForHardwareFunc(SerializableAAF.DAS_TYPE.SLICE, sampleRate); } } public Func GetAAFForHardwareFunc { get; set; } public void SetTestClockProfiles(DTS.Common.ClockSyncProfile masterProfile, DTS.Common.ClockSyncProfile slaveProfile) { foreach (HardwareModel hardware in _allHardware) { if (!hardware.IsClockedDAS) continue; hardware.MasterProfile = masterProfile; hardware.SlaveProfile = slaveProfile; } } public void SetTestClockMasters(Dictionary testClockMasters) { foreach (HardwareModel hardware in _allHardware) { if (!testClockMasters.ContainsKey(hardware.SerialNumber)) continue; hardware.IsClockMaster = testClockMasters[hardware.SerialNumber]; } } public void UpdateTestClockMaster(string childSerialNumber, bool testClockMaster) { foreach (HardwareModel hardware in _allHardware) { if (hardware.SerialNumber == childSerialNumber) { hardware.IsClockMaster = testClockMaster; break; } } } public void SetTestPTPDomainIDs(Dictionary testPTPDomainIDs) { foreach (HardwareModel hardware in _allHardware) { if (!testPTPDomainIDs.ContainsKey(hardware.SerialNumber)) continue; hardware.PTPDomainID = testPTPDomainIDs[hardware.SerialNumber]; } } public void UpdateTestPTPDomainID(string childSerialNumber, byte ptpDomainId) { foreach (HardwareModel hardware in _allHardware) { if (hardware.SerialNumber == childSerialNumber) { hardware.PTPDomainID = ptpDomainId; break; } } } public void CheckForMixedDAS(string nonParentSerialNumber, double testSampleRate) { foreach (HardwareModel hardware in _allHardware) { if (hardware.SerialNumber == nonParentSerialNumber) { if (string.IsNullOrWhiteSpace(hardware.ParentDAS)) { //It doesn't have a parent, so return return; } else { //It has a parent, so see if the parent has any children with a different rate if (AnyMixedChildren(testSampleRate, hardware.ParentDAS)) { SetParentMixedRates(hardware.ParentDAS, true); } else { //In case the parent is different than all of its children, set it to match UpdateTestSampleRate(hardware.ParentDAS, testSampleRate); SetParentMixedRates(hardware.ParentDAS, false); } return; } } } } private bool AnyMixedChildren(double testSampleRate, string parentDAS) { foreach (HardwareModel hardware in _allHardware) { if (hardware.ParentDAS == parentDAS) { //We found a sibling (or us, which will not be different, duh) if (hardware.Included && (hardware.TestSampleRate != testSampleRate)) { return true; } } } return false; } public void SetParentMixedRates(string parentDAS, bool mixedRates) { foreach (HardwareModel hardware in _allHardware) { if (hardware.SerialNumber == parentDAS) { hardware.MixedRates = mixedRates; return; } } } /// /// Set the HasIncludedChildren property so that the Sample Rate dropdown is visible if True. /// public void SetHasIncludedChildren() { foreach (HardwareModel hardware in _allHardware) { hardware.HasIncludedChildren = hardware.IsDistributor && AnyChildren(hardware.SerialNumber); } } /// /// Given a distributor, see if any DAS are its children. /// /// /// True if a distributor in the Test Setup has at least one child. public bool AnyChildren(string distributorDAS) { foreach (HardwareModel hardware in _allHardware) { if (hardware.Included && !hardware.IsDistributor && (hardware.ParentDAS == distributorDAS)) { return true; } } return false; } public void Filter(object tag, string term) { if (Enum.TryParse((string)tag, out Fields field)) { _filterByField[field] = term; Filter(_currentSearchTerm); } } private bool HardwareFilter(IHardware h) { var fields = Enum.GetValues(typeof(Fields)).Cast().ToArray(); foreach (var field in fields) { if (!_filterByField.ContainsKey(field)) { continue; } var term = _filterByField[field]; if (string.IsNullOrWhiteSpace(term)) { continue; } switch (field) { case Fields.SerialNumber: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.SerialNumber, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.FirstUseDate: { if (h.IsFirstUseValid) { if (null == h.FirstUseDate) { if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(DTS.Common.Strings.Strings.Table_NA, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } } else { var dt = ((DateTime)h.FirstUseDate).ToString("d"); if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(dt, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } } } else { if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(DTS.Common.Strings.Strings.NotApplicable, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } } } break; case Fields.HardwareType: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.HardwareType, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.IPAddress: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.IPAddress, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.ChannelCount: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.ChannelCount, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.Firmware: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.Firmware, term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.MaxSampleRate: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.MaxSampleRate?.ToString() ?? "", term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.TestSampleRate: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.TestSampleRate.ToString(System.Globalization.CultureInfo.InvariantCulture) ?? "", term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.CalDate: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.CalDate?.ToString("d") ?? "", term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; case Fields.CalDueDate: if (!(System.Globalization.CultureInfo.CurrentCulture.CompareInfo.IndexOf(h.CalDueDate?.ToString("d") ?? "", term, System.Globalization.CompareOptions.OrdinalIgnoreCase) >= 0)) { return false; } break; default: throw new ArgumentOutOfRangeException(); } } return true; } public void IncludeChildren(IHardware hardware) { foreach (var h in _allHardware) { var isoH = (IISOHardware)h.Hardware; if (!isoH.IsPseudoRackModule()) { continue; } if (isoH.ParentDAS == hardware.SerialNumber) { h.SetIncluded(hardware.Included); } } } public void RemoveMultipleButton(IHardware hardware) { foreach (var h in _allHardware) { if (h.SerialNumber == hardware.SerialNumber) { UpdateTestSampleRate(h.SerialNumber, 0); //So nothing is displayed h.SetMixedRates(false); } } } public void Filter(string term) { if (null == _allHardware) { return; } _currentSearchTerm = term; var hardware = new List(); var overdue = new List(); foreach (var h in _allHardware) { if (null != h.Hardware) { if (h.Hardware is IISOHardware iHardware) { if (iHardware.IsModule && ShowCompact && !string.IsNullOrWhiteSpace(iHardware.ParentDAS)) { if (h.CalDueDate <= DateTime.Today) { overdue.Add(h); } continue; } } } if (!h.Filter(_currentSearchTerm)) continue; h.DetermineChannelCount(ShowCompact, _allHardware); if (HardwareFilter(h)) { hardware.Add(h); } if (h.CalDueDate <= DateTime.Today) { overdue.Add(h); } } _overDueComparer.SortAscending = _sortOverdueAscending; _overDueComparer.SortField = _overdueSortField; overdue.Sort(_overDueComparer); OverdueHardware = overdue.ToArray(); OnPropertyChanged("OverdueHardware"); _comparer.SortAscending = _sortAscending; _comparer.SortField = _sortField; hardware.Sort(_comparer); Hardware = hardware.ToArray(); OnPropertyChanged("Hardware"); } public void SetIncluded(string[] serialNumbers, bool included) { var hash = new HashSet(serialNumbers); foreach (var h in Hardware) { if (hash.Contains(h.SerialNumber)) { h.SetIncluded(included); } } } public void SetIncluded(int[] ids) { var hash = new HashSet(ids); foreach (var h in _allHardware) { if (hash.Contains(h.DASId)) { h.SetIncluded(true); } } } public void Unset() { Hardware = new IHardware[0]; OnPropertyChanged("Hardware"); OverdueHardware = new IHardware[0]; OnPropertyChanged("OverdueHardware"); _cachedHardware.Clear(); ClearAllFilters(); _eventAggregator.GetEvent() .Publish(new ListViewStatusArg(ListViewStatusArg.ListViewStatus.Unloaded, ListViewId)); SelectedSLICE6 = null; SLICE6TreeNodes = new ISLICE6TreeNode[0]; AvailableSLICE6 = new ISLICE6TreeNode[0]; SelectedSLICE6DB = null; AvailableSLICE6DB = new IHardware[0]; _swappedHardware = null; _dasIdToChannels.Clear(); } public void ClearAllFilters() { _filterByField.Clear(); } public void Sort(object o, bool bColumnClick) { if (!(o is string s)) { return; } if (!Enum.TryParse(s, out HardwareListTags tag)) { return; } if (bColumnClick) { if (tag != _sortField) { _sortField = tag; _sortAscending = true; } else { _sortAscending = !_sortAscending; } } _comparer.SortAscending = _sortAscending; _comparer.SortField = _sortField; var list = new List(Hardware); list.Sort(_comparer); if (Hardware.SequenceEqual(list) && Hardware.Length > 1) { //list was already in order. flip it for the user _sortAscending = !_sortAscending; _comparer.SortAscending = _sortAscending; list.Sort(_comparer); } Hardware = list.ToArray(); OnPropertyChanged("Hardware"); } public void SortOverdue(object o, bool bColumnClick) { if (!(o is string s)) { return; } if (!Enum.TryParse(s, out HardwareListTags tag)) { return; } if (bColumnClick) { if (tag != _overdueSortField) { _overdueSortField = tag; _sortOverdueAscending = true; } else { _sortOverdueAscending = !_sortOverdueAscending; } } _overDueComparer.SortAscending = _sortOverdueAscending; _overDueComparer.SortField = _overdueSortField; var list = new List(OverdueHardware); list.Sort(_overDueComparer); OverdueHardware = list.ToArray(); OnPropertyChanged("OverdueHardware"); } public void Cleanup() { } public Task CleanupAsync() { return Task.CompletedTask; } public void Initialize() { } public void Initialize(object parameter) { } public void Initialize(object parameter, object model) { } public Task InitializeAsync() { return Task.CompletedTask; } public Task InitializeAsync(object parameter) { return Task.CompletedTask; } public void Activated() { } /// /// Private Event handler for RaiseNotification event. /// private void OnBusyIndicatorNotification(bool eventArg) { IsBusy = eventArg; } /// /// Private Event handler for RaiseNotification event. /// private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle) { // The NotificationRequest.Raise triggers the Invoke() method of the PopupWindowAction object to show the NotificationWindow window // Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string. var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, "", eventArgsWithTitle.Image, string.Empty); NotificationRequest.Raise(new Notification { Content = eventArgsWithoutTitle, Title = eventArgsWithTitle.Title }); } /// /// commits any changes to the SLICE6 associations to a SLICE6DB to the db /// public void SaveSLICE6Associations(string serialNumber) { if (null != _swappedHardware) { //first just swap all nodes SLICE6TreeNode.SwapNodes(serialNumber, _swappedHardware.SerialNumber); } //then finally apply any changes in addition to that SLICE6TreeNode.SaveAssociations(serialNumber, SLICE6TreeNodes); } /// /// associates a SLICE6 with a SLICE6DB /// [does not commit] /// /// public void Associate(ISLICE6TreeNode node) { SelectedSLICE6 = null; node.Number = 1 + SLICE6TreeNodes.Length; node.Port = -1; node.PositionOnChain = -1; _availableSLICE6.Remove(node); OnPropertyChanged("AvailableSLICE6"); _slice6TreeNodes.Add(node); OnPropertyChanged("SLICE6TreeNodes"); } private IHardware _swappedHardware = null; /// /// associates units from one SLICE6DB /// with another /// [does not commit] /// /// public void Associate(IHardware node) { _swappedHardware = node; SelectedSLICE6DB = null; LoadTreeView(node.SerialNumber); OnPropertyChanged("AvailableSLICE6"); OnPropertyChanged("SLICE6TreeNodes"); } /// /// removes the association of a SLICE6 with a SLICE6DB /// [does not commit] /// /// public void UnAssociate(ISLICE6TreeNode node) { for (int i = 0; i < _slice6TreeNodes.Count; i++) { var slice6 = _slice6TreeNodes[i]; if (slice6 == node) { continue; } if (slice6.Number > node.Number) { slice6.Number = slice6.Number - 1; } if (slice6.Port == node.Port) { if (slice6.PositionOnChain > node.PositionOnChain) { slice6.PositionOnChain = slice6.PositionOnChain - 1; } } } node.Port = -1; node.PositionOnChain = -1; node.Number = -1; _availableSLICE6.Add(node); OnPropertyChanged("AvailableSLICE6"); _slice6TreeNodes.Remove(node); OnPropertyChanged("SLICE6TreeNodes"); } /// /// populates the available hardware based on the hardware to be replaced /// private void PopulateAvailableHardware() { if (null == HardwareToReplace) { AvailableHardware = new IHardware[0]; AssignedChannels = new Model.HardwareChannelAssignment[0]; } var suitable = new List(); if (null != HardwareToReplace) { if (_dasIdToChannels.ContainsKey(HardwareToReplace.DASId)) { AssignedChannels = _dasIdToChannels[HardwareToReplace.DASId].ToArray(); } else { AssignedChannels = new Model.HardwareChannelAssignment[0]; } OnPropertyChanged("AssignedChannels"); foreach (var h in Hardware) { if (h.Included) { continue; } //skip hardware in test if (!h.HardwareType.Equals(HardwareToReplace.HardwareType)) { continue; } if (HardwareToReplace.Hardware is IISOHardware h1 && h.Hardware is IISOHardware h2) { if (h1.DASTypeEnum == HardwareTypes.TDAS_Pro_Rack) { //Replace allows replacing a larger rack with a smaller one and throws an exception (assert) //we want to prevent replacement hardware that has less modules than the hardware to be replaced ... if (h1.MaxModules > h2.MaxModules) { continue; } } } suitable.Add(h); } } AvailableHardware = suitable.ToArray(); } /// /// replace hardwaretoreplace with replacementhardware /// public void Replace() { if (null == HardwareToReplace || null == ReplacementHardware) { return; } ReplacementHardware.Included = true; _eventAggregator.GetEvent() .Publish(new Tuple(HardwareToReplace, ReplacementHardware)); var hwReplaced = HardwareToReplace; HardwareToReplace = null; ReplacementHardware = null; AssignedChannels = new Model.HardwareChannelAssignment[0]; hwReplaced.Included = false; } #endregion #region Properties public IStreamingFilterProfile StreamingDSPProfile { get; set; } private List _assignedChannels = new List(); public Model.HardwareChannelAssignment[] AssignedChannels { get => _assignedChannels.ToArray(); set { _assignedChannels.Clear(); _assignedChannels.AddRange(value); OnPropertyChanged("AssignedChannels"); } } private IHardware _replacementHardware = null; /// /// the hardware to replace with /// public IHardware ReplacementHardware { get => _replacementHardware; set { _replacementHardware = value; OnPropertyChanged("ReplacementHardware"); } } private List _hardwareInTest = new List(); /// /// the hardware in the test available to be replaced /// public IHardware[] HardwareInTest { get => _hardwareInTest.ToArray(); set { _hardwareInTest.Clear(); _hardwareInTest.AddRange(value); OnPropertyChanged("HardwareInTest"); } } private IHardware _hardwareToReplace = null; /// /// the hardware to replace /// public IHardware HardwareToReplace { get => _hardwareToReplace; set { _hardwareToReplace = value; OnPropertyChanged("HardwareToReplace"); PopulateAvailableHardware(); } } private List _availableHardware = new List(); /// /// the available hardware to replace HardwareToReplace with /// public IHardware[] AvailableHardware { get => _availableHardware.ToArray(); set { _availableHardware.Clear(); _availableHardware.AddRange(value); OnPropertyChanged("AvailableHardware"); } } private bool _isEdit = false; public bool IsEdit { get => _isEdit; set { _isEdit = value; OnPropertyChanged("IsEdit"); } } private ISLICE6TreeNode _selectedSLICE6 = null; /// /// a user selected slice6 /// public ISLICE6TreeNode SelectedSLICE6 { get => _selectedSLICE6; set { _selectedSLICE6 = value; OnPropertyChanged("SelectedSLICE6"); } } private IHardware _selectedSLICE6DB = null; /// /// currently selected SLICE6DB /// public IHardware SelectedSLICE6DB { get => _selectedSLICE6DB; set { _selectedSLICE6DB = value; OnPropertyChanged("SelectedSLICE6DB"); } } private List _availableSLICE6DB = new List(); /// /// all available SLICE6DB /// public IHardware[] AvailableSLICE6DB { get => _availableSLICE6DB.ToArray(); set { _availableSLICE6DB.Clear(); _availableSLICE6DB.AddRange(value); OnPropertyChanged("AvailableSLICE6DB"); } } private List _availableSLICE6 = new List(); /// /// all slice6 which are not associated with a given S6DB /// public ISLICE6TreeNode[] AvailableSLICE6 { get => _availableSLICE6.ToArray(); set { _availableSLICE6.Clear(); _availableSLICE6.AddRange(value); OnPropertyChanged("AvailableSLICE6"); } } private List _slice6TreeNodes = new List(); /// /// all the SLICE6 associated with a S6DB /// public ISLICE6TreeNode[] SLICE6TreeNodes { get => _slice6TreeNodes.ToArray(); set { _slice6TreeNodes.Clear(); _slice6TreeNodes.AddRange(value); OnPropertyChanged("SLICE6TreeNodes"); } } /// /// whether to show a compact view (no rack modules) or /// expanded (show rack modules) /// private bool _showCompact = true; public bool ShowCompact { get => _showCompact; set { _showCompact = value; OnPropertyChanged("ShowCompact"); Filter(_currentSearchTerm); _eventAggregator.GetEvent().Publish(value); } } public enum Fields { SerialNumber, HardwareType, IPAddress, ChannelCount, Firmware, MaxSampleRate, TestSampleRate, CalDate, CalDueDate, IsClockMaster, FirstUseDate, PTPDomainID } private readonly Dictionary _filterByField = new Dictionary(); private readonly Dictionary _cachedHardware = new Dictionary(); private string _currentSearchTerm = ""; public int _testSampleRateColumnWidth; public int TestSampleRateColumnWidth { get => _testSampleRateColumnWidth; set { _testSampleRateColumnWidth = value; OnPropertyChanged("TestSampleRateColumnWidth"); } } public int _testClockMasterColumnWidth; public int TestClockMasterColumnWidth { get => _testClockMasterColumnWidth; set { _testClockMasterColumnWidth = value; OnPropertyChanged("TestClockMasterColumnWidth"); } } private int _ptpDomainColumnWidth; public int PTPDomainColumnWidth { get => _ptpDomainColumnWidth; set { _ptpDomainColumnWidth = value; OnPropertyChanged("PTPDomainColumnWidth"); } } public int _testAAFRateHzColumnWidth; public int TestAAFRateHzColumnWidth { get => _testAAFRateHzColumnWidth; set { _testAAFRateHzColumnWidth = value; OnPropertyChanged("TestAAFRateHzColumnWidth"); } } public int SelectedHardwareIndex { get; set; } = -1; public ObservableCollection _selectedHardwareItems; public ObservableCollection SelectedHardwareItems { get => _selectedHardwareItems; set { if (_selectedHardwareItems != null) { _selectedHardwareItems.CollectionChanged -= SelectedHardwareItemsOnCollectionChanged; } _selectedHardwareItems = value; if (_selectedHardwareItems != null) { _selectedHardwareItems.CollectionChanged += SelectedHardwareItemsOnCollectionChanged; } FireSelectionChanged(); } } public IHardware[] GetSelectedItems() { return SelectedHardwareItems.ToArray(); } private void SelectedHardwareItemsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { FireSelectionChanged(); } public int SelectedOverdueIndex { get; set; } = -1; private bool _sortAscending { get; set; } = true; private HardwareListTags _sortField { get; set; } = HardwareListTags.SerialNumber; private HardwareComparer _comparer = new HardwareComparer(); private bool _sortOverdueAscending { get; set; } = true; private HardwareListTags _overdueSortField { get; set; } = HardwareListTags.SerialNumber; private HardwareComparer _overDueComparer = new HardwareComparer(); public int TDASCalPeriod { get; set; } public int G5CalPeriod { get; set; } public int SLICE1CalPeriod { get; set; } public int SLICE1_5CalPeriod { get; set; } public int SLICE2_CalPeriod { get; set; } public int SLICE6_CalPeriod { get; set; } public int POWERPRO_CalPeriod { get; set; } public int SLICE6Air_CalPeriod { get; set; } public int SLICE6AirBridge_CalPeriod { get; set; } public int SLICE6DB_CalPeriod { get; set; } public int TSRAir_CalPeriod { get; set; } public int SLICETC_CalPeriod { get; set; } public int SLICE_PRO_CAN_FD_CalPeriod { get; set; } private IHardware[] _allHardware { get; set; } public IHardware[] Hardware { get; set; } public IHardware[] OverdueHardware { get; set; } public bool IsDirty { get; private set; } private bool _isBusy; public bool IsBusy { get => _isBusy; set { _isBusy = value; OnPropertyChanged("IsBusy"); } } private bool _isMenuIncluded; public bool IsMenuIncluded { get => _isMenuIncluded; set { _isMenuIncluded = value; OnPropertyChanged("IsMenuIncluded"); } } private bool _isNavigationIncluded; public bool IsNavigationIncluded { get => _isNavigationIncluded; set { _isNavigationIncluded = value; OnPropertyChanged("IsNavigationIncluded"); } } public void SetCalPeriods(int g5CalPeriod, int slice1CalPeriod, int slice1_5CalPeriod, int slice2_CalPeriod, int slice6_CalPeriod, int tdasCalPeriod, int powerpro_CalPeriod, int slice6Air_CalPeriod, int slice6DB_CalPeriod, int tsrAir_CalPeriod, int slice6AirBridge_CalPeriod, int sliceTcCalPeriod, int sliceProCanFdPeriod) { G5CalPeriod = g5CalPeriod; SLICE1CalPeriod = slice1CalPeriod; SLICE1_5CalPeriod = slice1_5CalPeriod; SLICE2_CalPeriod = slice2_CalPeriod; SLICE6_CalPeriod = slice6_CalPeriod; TDASCalPeriod = tdasCalPeriod; POWERPRO_CalPeriod = powerpro_CalPeriod; SLICE6Air_CalPeriod = slice6Air_CalPeriod; SLICE6AirBridge_CalPeriod = slice6AirBridge_CalPeriod; SLICE6DB_CalPeriod = slice6DB_CalPeriod; TSRAir_CalPeriod = tsrAir_CalPeriod; SLICETC_CalPeriod = sliceTcCalPeriod; SLICE_PRO_CAN_FD_CalPeriod = sliceProCanFdPeriod; } public string ListViewId => "HardwareListView"; #endregion Properties #region Commands #endregion } }