namespace ProximaAnalizer.ViewModels; internal partial class DBInfoAlarmViewModel : ObservableObject { public DBInfoAlarmViewModel(DBDataHelper dBDataHelper, TraceData traceData, IRegionManager regionManager, IEventAggregator eventAggregator, IDialogService dialogService) { this._traceData = traceData; this._DBDataHelper = dBDataHelper; this._dialogService = dialogService; this._regionManager = regionManager; this._eventAggregator = eventAggregator; CurrentChangedQueue = new(CurrentChangedQueueHandler); eventAggregator.GetEvent().Subscribe(InitDisplayData); eventAggregator.GetEvent().Subscribe(SelectedData); } private readonly IRegionManager _regionManager; private readonly IEventAggregator _eventAggregator; private readonly IDialogService _dialogService; private readonly DBDataHelper _DBDataHelper; private readonly TraceData _traceData; private readonly EventQueue CurrentChangedQueue; private Timer? _AutoPlayTimer; private Pages? _FromPage; private void SelectedData() { this.Selected = _eventAggregator.GetEvent().Selected; } private void InitDisplayData() { this.RecipeSteps.Clear(); this._regionManager.RequestNavigate("AlarmRegion", "AlarmData"); RefreshAlarmData alarmData = _eventAggregator.GetEvent(); this._FromPage = alarmData.FromPage; if (_traceData.ProcessData is null) return; this.RecipeName = _traceData.ProcessData.Recipe_Name; if (!this._DBDataHelper.GetRecipeSteps(_traceData.ProcessData.Guid, out string reason, out List? recipeSteps) || recipeSteps is null) { MessageBox.Show(reason, "Warning", MessageBoxButton.OK, MessageBoxImage.Warning); return; } recipeSteps.Foreach(t => this.RecipeSteps.TryAdd(TimeRounder.IngoreMillionSeconds(t.Step_Begin_Time.Ticks), t)); this.Start = recipeSteps.First().Step_Begin_Time; this.End = recipeSteps.Last().Step_End_Time; this._DBDataHelper.SetTimeRange(this.Start, this.End); if (this._DBDataHelper.GetAlarmData(out List? alarms) && alarms is not null) { Dictionary alarmCache = []; foreach (EventData? alarm in alarms) { if (alarm is null || string.IsNullOrEmpty(alarm.Level)) continue; DateTime occorTime = TimeRounder.IngoreMillionSeconds(alarm.Occur_Time.Ticks); if (!alarmCache.TryGetValue(occorTime, out StringBuilder? events) || events is null) { events = new(); alarmCache[occorTime] = events; events.Append(alarm.Description); continue; } events.Append(Environment.NewLine); events.Append(alarm.Description); } this.Alarms = alarmCache; } if (alarmData.Selected is not null) { DateTime time = TimeRounder.IngoreMillionSeconds(alarmData.Selected.Occur_Time.Ticks); this.Current = time; this.CurrentLong = time.Ticks; return; } this.Current = this.Start; this.CurrentLong = this.Start.Ticks; } [ObservableProperty] private RecipeStepData? _CurrentRecipeStep; [ObservableProperty] private ObservableDictionary _RecipeSteps = []; [ObservableProperty] private Dictionary _Alarms = []; [ObservableProperty] private KeyValuePair? _SelectedAlarm; partial void OnSelectedAlarmChanged(KeyValuePair? value) { if (value is null) return; this.CurrentLong = value.Value.Key.Ticks; } [ObservableProperty] private string? _RecipeName; [ObservableProperty] private DateTime _Start; [ObservableProperty] private DateTime _End; [ObservableProperty] private DateTime _Current; [ObservableProperty] private long _CurrentLong; partial void OnCurrentLongChanged(long value) => this.CurrentChangedQueue.Enqueue(value); private void CurrentChangedQueueHandler(long value) { if (CurrentChangedQueue.Count != 0) return; DateTime time = TimeRounder.IngoreMillionSeconds(value); RecipeStepData? step = this.RecipeSteps.Where(t => t.Key <= this.Current).LastOrDefault().Value; App.Current.Dispatcher?.Invoke(() => { if (this.Alarms.ContainsKey(time)) this.SelectedAlarm = this.Alarms.Where(t => t.Key == time).FirstOrDefault(); else this.SelectedAlarm = null; this.Current = time; this.CurrentRecipeStep = step; }); DateTime startTime = time.AddMilliseconds(-500); DateTime endTime = time.AddMilliseconds(500); this._DBDataHelper.GetSystemData(startTime, endTime, out List? systemData); this._DBDataHelper.GetPMData(startTime, endTime, out List? pmData); this._eventAggregator.GetEvent().PmData = pmData; this._eventAggregator.GetEvent().SystemData = systemData; this._eventAggregator.GetEvent().Publish(); } [ObservableProperty] private Visibility _PlayVis = Visibility.Visible; [ObservableProperty] private Visibility _StopVis = Visibility.Collapsed; [RelayCommand] private void Play(string para) { switch (para) { case "play": this._AutoPlayTimer ??= new(TimerCallback, null, 0, 1000); this.PlayVis = Visibility.Collapsed; this.StopVis = Visibility.Visible; break; case "stop": this._AutoPlayTimer?.Dispose(); this._AutoPlayTimer = null; this.PlayVis = Visibility.Visible; this.StopVis = Visibility.Collapsed; break; default: break; } } private void TimerCallback(object? state) { if (this.CurrentLong >= this.End.Ticks) { this.Play("stop"); return; } App.Current.Dispatcher?.Invoke(() => this.CurrentLong += 10000000); } [RelayCommand] private void TimeOpera(string para) { this.Play("stop"); switch (para) { case "+": if (this.Current >= this.End) return; this.CurrentLong += 10000000; break; case "-": if (this.Current <= Start) return; this.CurrentLong -= 10000000; break; case "++": if (this.Current >= this.End) return; this.CurrentLong += 600000000; break; case "--": if (this.Current <= Start) return; this.CurrentLong -= 600000000; break; case "---": { DateTime alarm = this.Alarms.Where(t => t.Key < this.Current).LastOrDefault().Key; if (alarm == DateTime.MinValue) break; this.CurrentLong = alarm.Ticks; } break; case "+++": { DateTime alarm = this.Alarms.Where(t => t.Key > this.Current).FirstOrDefault().Key; if (alarm == DateTime.MinValue) break; this.CurrentLong = alarm.Ticks; } break; default: break; } } [RelayCommand] private void SingleTrace() { if (this.Selected is null) return; if (_eventAggregator.GetEvent().KeyNames is not object keys || keys is null) return; this.Play("stop"); IDialogParameters para = new DialogParameters { { "point", this.Selected }, { "keys", keys }, { "time", this.Current} }; this._dialogService.ShowDialog("SingleTrace", para); } [RelayCommand] private void Navi(string para) { this.Play("stop"); this.CurrentChangedQueue.Enqueue(this.CurrentLong); this._regionManager.RequestNavigate("AlarmRegion", para); } [RelayCommand] private void Return() { this.Play("stop"); _eventAggregator.GetEvent().Page = _FromPage is null ? Pages.RecipeStepNavi : _FromPage.Value; _eventAggregator.GetEvent().Publish(); } [ObservableProperty] private object? _Selected; partial void OnSelectedChanged(object? value) { } }