RealtimeDataPlotHelper.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. using ScottPlot;
  2. using ScottPlot.Plottables;
  3. using ScottPlot.WPF;
  4. namespace MinicsUI.Helper;
  5. public partial class RealtimeDataPlotHelper : ObservableObject, IDisposable
  6. {
  7. [ObservableProperty]
  8. private WpfPlot? _PlotControl;
  9. private bool _DisposedValue;
  10. private readonly List<float> _HistoryData = [];
  11. private readonly List<DateTime> _HistoryTime = [];
  12. public Channel? Channel { get; private set; }
  13. public void InitPlot(Channel channel)
  14. {
  15. if (channel is null)
  16. return;
  17. this.Channel = channel;
  18. this._HistoryData.Clear();
  19. this._HistoryTime.Clear();
  20. _HistoryData.AddRange(this.Channel.PVRingBuffer.ReadValues());
  21. _HistoryTime.AddRange(this.Channel.DateTimeRingBuffer.ReadValues());
  22. this.PlotControl = new();
  23. this.PlotControl.Plot.Grid.XAxisStyle.MajorLineStyle.Width = 1f;
  24. this.PlotControl.Plot.Grid.YAxisStyle.MajorLineStyle.Width = 1f;
  25. this.PlotControl.Plot.FigureBackground.Color = ScottPlot.Colors.Transparent;
  26. this.PlotControl.UserInputProcessor.Disable();
  27. this.PlotControl.Plot.RenderManager.RenderStarting += (s, e) =>
  28. {
  29. Tick[] ticks = this.PlotControl.Plot.Axes.Bottom.TickGenerator.Ticks;
  30. for (int i = 0; i < ticks.Length; i++)
  31. {
  32. DateTime dt = DateTime.FromOADate(ticks[i].Position);
  33. string label = $"{dt:HH:mm:ss}";
  34. ticks[i] = new Tick(ticks[i].Position, label);
  35. }
  36. };
  37. this.Channel.OnPVChangedEvent += OnPVChanged;
  38. }
  39. private void OnPVChanged(float pv, DateTime dateTime)
  40. {
  41. if (Channel is null)
  42. return;
  43. if (this.PlotControl is null)
  44. return;
  45. switch (this._HistoryData.Count)
  46. {
  47. case >= 120:
  48. _HistoryTime.RemoveAt(0);
  49. _HistoryTime.Add(dateTime);
  50. _HistoryData.RemoveAt(0);
  51. _HistoryData.Add(pv);
  52. break;
  53. default:
  54. _HistoryData.Add(pv);
  55. _HistoryTime.Add(dateTime);
  56. break;
  57. }
  58. if (this.PlotControl is null)
  59. return;
  60. this.PlotControl.Plot.Clear();
  61. this.PlotControl.Plot.Add.HorizontalLine(this.Channel.Caps, 1f, ScottPlot.Color.FromHex("FF0000"), LinePattern.Dotted);
  62. this.PlotControl.Plot.Add.HorizontalLine(this.Channel.Floor, 1f, ScottPlot.Color.FromHex("FF0000"), LinePattern.Dotted);
  63. this.PlotControl.Plot.Add.HorizontalLine(this.Channel.CapsWarning, 1f, ScottPlot.Color.FromHex("FFA500"), LinePattern.Dotted);
  64. this.PlotControl.Plot.Add.HorizontalLine(this.Channel.FloorWarning, 1f, ScottPlot.Color.FromHex("FFA500"), LinePattern.Dotted);
  65. this.PlotControl.Plot.Add.HorizontalLine(this.Channel.SetPoint, 1f, ScottPlot.Color.FromHex("00FF00"), LinePattern.Dotted);
  66. Scatter mainScatter = this.PlotControl.Plot.Add.Scatter(_HistoryTime, _HistoryData, ScottPlot.Color.FromHex("0074c1"));
  67. mainScatter.MarkerStyle = MarkerStyle.None;
  68. mainScatter.LineWidth = 3f;
  69. this.PlotControl.Plot.Axes.DateTimeTicksBottom();
  70. this.PlotControl.Plot.Axes.AutoScale();
  71. this.PlotControl?.Refresh();
  72. }
  73. protected virtual void Dispose(bool disposing)
  74. {
  75. if (!_DisposedValue)
  76. {
  77. if (disposing)
  78. {
  79. this.PlotControl = null;
  80. }
  81. if (this.Channel is not null)
  82. this.Channel.OnPVChangedEvent -= OnPVChanged;
  83. _DisposedValue = true;
  84. }
  85. }
  86. ~RealtimeDataPlotHelper()
  87. {
  88. Dispose(disposing: false);
  89. }
  90. public void Dispose()
  91. {
  92. Dispose(disposing: true);
  93. GC.SuppressFinalize(this);
  94. }
  95. }