RealTimeViewModel.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Drawing;
  5. using System.Linq;
  6. using System.Windows;
  7. using Aitex.Core.RT.Log;
  8. using Aitex.Core.Util;
  9. using Aitex.Core.Utilities;
  10. using MECF.Framework.Common.ControlDataContext;
  11. using MECF.Framework.Common.DataCenter;
  12. using MECF.Framework.Common.Utilities;
  13. using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory;
  14. using MECF.Framework.UI.Client.ClientBase;
  15. using MECF.Framework.UI.Client.ClientBase.Charting;
  16. using MECF.Framework.UI.Client.ClientBase.EventArgs;
  17. using MECF.Framework.UI.Client.ClientBase.Tree;
  18. using OpenSEMI.ClientBase;
  19. using SciChart.Charting.Visuals.Axes;
  20. using SciChart.Charting.Visuals.RenderableSeries;
  21. using SciChart.Core.Extensions;
  22. namespace MECF.Framework.UI.Client.CenterViews.Operations.RealTime
  23. {
  24. public class RealtimeViewModel : BusyIndicateableUiViewModelBase
  25. {
  26. #region Variables
  27. /// <summary>
  28. /// 允许监控的最大曲线数量
  29. /// </summary>
  30. private const int MAX_PARAMETERS_ALLOWED = 200;
  31. private readonly RealtimeProvider _provider = new RealtimeProvider();
  32. private bool _enableAutoZoom = true;
  33. private int _pointCount;
  34. private readonly PeriodicJob _thread;
  35. /// <summary>
  36. /// Monitor中添加数据点时直接向DataSeries对象添加,已实现跨线程操作。
  37. /// </summary>
  38. private readonly List<FastLineDataSeries> _dataSeriesList;
  39. /// <summary>
  40. /// 更新报告导出信息。
  41. /// </summary>
  42. private readonly IProgress<ProgressUpdatingEventArgs> _exportingProgressReporter;
  43. #endregion
  44. #region Constructors
  45. public RealtimeViewModel()
  46. {
  47. DisplayName = "Realtime";
  48. SelectedData = new ChartingLineSeriesCollection(DisplayName);
  49. ParameterNodes = new TreeNode(DisplayName)
  50. {
  51. MaxTerminalSelectionAllowed = MAX_PARAMETERS_ALLOWED
  52. };
  53. ParameterNodes.ChildNodes.AddRange(_provider.GetTreeNodeParameters());
  54. ParameterNodes.TerminalNodeSelectionChanged += OnNodeSelectionChanged;
  55. IntervalSaved = true;
  56. TrendInterval = 500;
  57. TimeSpanSaved = true;
  58. TrendTimeSpan = 60 * 5;
  59. _thread = new PeriodicJob(TrendInterval, MonitorData, "RealTime", true);
  60. _pointCount = Math.Max(TrendTimeSpan * 1000 / TrendInterval, 10);
  61. _dataSeriesList = new List<FastLineDataSeries>();
  62. _exportingProgressReporter = new Progress<ProgressUpdatingEventArgs>(e =>
  63. {
  64. BusyIndicatorContent = e.Message;
  65. });
  66. }
  67. #endregion
  68. #region Properties
  69. public bool IsPermission => this.Permission == 3;
  70. public TreeNode ParameterNodes { get; }
  71. public ChartingLineSeriesCollection SelectedData { get; set; }
  72. public AutoRange ChartAutoRange => EnableAutoZoom ? AutoRange.Always : AutoRange.Never;
  73. public bool EnableAutoZoom
  74. {
  75. get => _enableAutoZoom;
  76. set
  77. {
  78. _enableAutoZoom = value;
  79. NotifyOfPropertyChange(nameof(EnableAutoZoom));
  80. NotifyOfPropertyChange(nameof(ChartAutoRange));
  81. }
  82. }
  83. [IgnorePropertyChange]
  84. public int TrendInterval { get; set; }
  85. public bool IntervalSaved { get; set; }
  86. [IgnorePropertyChange]
  87. public int TrendTimeSpan { get; set; }
  88. public bool TimeSpanSaved { get; set; }
  89. private bool _IsHold;
  90. public bool IsHold
  91. {
  92. get { return _IsHold; }
  93. set
  94. {
  95. if (_IsHold!=value)
  96. {
  97. _IsHold = value;
  98. if (_IsHold) EnableAutoZoom = false;
  99. else EnableAutoZoom = true;
  100. NotifyOfPropertyChange(nameof(IsHold));
  101. }
  102. }
  103. }
  104. #endregion
  105. #region Methods
  106. protected bool MonitorData()
  107. {
  108. try
  109. {
  110. Dictionary<string, object> data = null;
  111. if (!IsHold&&SelectedData.Count > 0)
  112. {
  113. data = QueryDataClient.Instance.Service.PollData(SelectedData.Select(r => (r as FastLineSeries)?.DataName).ToList());
  114. AppendData(data);
  115. }
  116. for (var j = 0; j < ParameterNodes.ChildNodes.Count; j++)
  117. {
  118. var par = ParameterNodes.ChildNodes[j];
  119. par.IsVisibilityParentNode = Visibility.Hidden;
  120. }
  121. }
  122. catch (Exception ex)
  123. {
  124. LOG.Error(ex.Message);
  125. }
  126. return true;
  127. }
  128. public void AppendData(Dictionary<string, object> data)
  129. {
  130. if (data == null)
  131. return;
  132. var dt = DateTime.Now;
  133. foreach (var ds in _dataSeriesList)
  134. {
  135. if (ds == null || !data.ContainsKey(ds.SeriesName))
  136. continue;
  137. if (data[ds.SeriesName] is bool)
  138. {
  139. ds.Append(dt, ((bool)data[ds.SeriesName] ? 1 : 0) * ds.Factor + ds.Offset, new ParameterNodePoint(dt, ((bool)data[ds.SeriesName] ? 1 : 0)));
  140. continue;
  141. }
  142. if (!double.TryParse(data[ds.SeriesName].ToString(), out var value))
  143. continue;
  144. ds.Append(dt, value * ds.Factor + ds.Offset, new ParameterNodePoint(dt, value));
  145. }
  146. }
  147. private void UpdateFifoCapacity(int capacity)
  148. {
  149. foreach (var renderableSeries in SelectedData)
  150. {
  151. if (renderableSeries is FastLineSeries line)
  152. {
  153. var ds = line.GetDataSeries();
  154. var copyMetaData = ds.Metadata.Where(x => x != null && ((ParameterNodePoint)x).Time > DateTime.Now.AddSeconds(-TrendTimeSpan)).ToList();
  155. ds.FifoCapacity = capacity;
  156. foreach (ParameterNodePoint item in copyMetaData)
  157. {
  158. ds.Append(item.Time, item.Value);
  159. }
  160. }
  161. }
  162. }
  163. public void SetInterval()
  164. {
  165. _thread.ChangeInterval(TrendInterval);
  166. _pointCount = Math.Max(10, TrendTimeSpan * 1000 / TrendInterval);
  167. IntervalSaved = true;
  168. NotifyOfPropertyChange(nameof(IntervalSaved));
  169. UpdateFifoCapacity(_pointCount);
  170. }
  171. public void SetTimeSpan()
  172. {
  173. _pointCount = Math.Max(10, TrendTimeSpan * 1000 / TrendInterval);
  174. TimeSpanSaved = true;
  175. NotifyOfPropertyChange(nameof(TimeSpanSaved));
  176. UpdateFifoCapacity(_pointCount);
  177. }
  178. #endregion
  179. #region Events
  180. public void OnNodeSelectionChanged(object sender, TreeNodeSelectionChangedEventArgs e)
  181. {
  182. if (e.NewValue == true && SelectedData.Count >= MAX_PARAMETERS_ALLOWED)
  183. {
  184. e.Cancel = true;
  185. return;
  186. }
  187. var line = SelectedData.Cast<FastLineSeries>().FirstOrDefault(x => x.DataName == e.Source.FullName);
  188. switch (e.NewValue)
  189. {
  190. case false:
  191. {
  192. if (line != null)
  193. {
  194. _dataSeriesList.Remove(line.GetDataSeries());
  195. SelectedData.Remove(line);
  196. }
  197. break;
  198. }
  199. case true:
  200. {
  201. if (line == null)
  202. {
  203. var series = new FastLineSeries(e.Source.FullName)
  204. {
  205. BackendParameterNode = e.Source
  206. };
  207. series.GetDataSeries().FifoCapacity = _pointCount;
  208. SelectedData.Add(series);
  209. _dataSeriesList.Add(series.GetDataSeries());
  210. SelectedData.ResetColors();
  211. }
  212. break;
  213. }
  214. default:
  215. break;
  216. }
  217. }
  218. public void Deleted(object sender, RenderableSeriesDeletingEventArgs e)
  219. {
  220. var list = e.Source.Cast<FastLineSeries>().ToList();
  221. var total = SelectedData.Count;
  222. for (var i = total - 1; i >= 0; i--)
  223. {
  224. if (i < list.Count)
  225. {
  226. list[i].BackendParameterNode.IsSelected = false;
  227. }
  228. }
  229. _dataSeriesList.Clear();
  230. ((RealtimeView)View).tvParameterNodes.ClearPresetGroupSelectionOnly();
  231. }
  232. public void Exporting(object sender, EventArgs e)
  233. {
  234. BusyIndicatorContent = "Exporting ...";
  235. IsBusy = true;
  236. }
  237. public void Exported(object sender, EventArgs e)
  238. {
  239. IsBusy = false;
  240. }
  241. public void ProgressUpdating(object sender, ProgressUpdatingEventArgs e)
  242. {
  243. _exportingProgressReporter.Report(e);
  244. }
  245. public override void Cancel()
  246. {
  247. if (View is RealtimeView view)
  248. {
  249. view.dataGrid.CancelOperation();
  250. }
  251. }
  252. public void ArrowClick(string direction)
  253. {
  254. var view = GetView() as RealtimeView;
  255. switch (direction)
  256. {
  257. case "Up":
  258. view.sciChart.ChartModifier.YAxis.Scroll(50, SciChart.Charting.ClipMode.ClipAtMax);
  259. break;
  260. case "Down":
  261. view.sciChart.ChartModifier.YAxis.Scroll(-50, SciChart.Charting.ClipMode.ClipAtMin);
  262. break;
  263. case "Left":
  264. view.sciChart.ChartModifier.XAxis.Scroll(-50, SciChart.Charting.ClipMode.ClipAtMin);
  265. break;
  266. case "Right":
  267. view.sciChart.ChartModifier.XAxis.Scroll(50, SciChart.Charting.ClipMode.ClipAtMax);
  268. break;
  269. }
  270. }
  271. public void ZoomInClick(int index)
  272. {
  273. var view = GetView() as RealtimeView;
  274. index += 1;
  275. if ((index & 0x01) == 1)
  276. view.sciChart.ChartModifier.XAxis.ZoomBy(-0.1, -0.1);
  277. if ((index & 0x02) == 2)
  278. view.sciChart.ChartModifier.YAxis.ZoomBy(-0.1, -0.1);
  279. }
  280. public void ZoomOutClick(int index)
  281. {
  282. var view = GetView() as RealtimeView;
  283. index += 1;
  284. if ((index & 0x01) == 1)
  285. view.sciChart.ChartModifier.XAxis.ZoomBy(0.1, 0.1);
  286. if ((index & 0x02) == 2)
  287. view.sciChart.ChartModifier.YAxis.ZoomBy(0.1, 0.1);
  288. }
  289. #endregion
  290. }
  291. }