123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Drawing;
- using System.Linq;
- using System.Windows;
- using Aitex.Core.RT.Log;
- using Aitex.Core.Util;
- using Aitex.Core.Utilities;
- using MECF.Framework.Common.ControlDataContext;
- using MECF.Framework.Common.DataCenter;
- using MECF.Framework.Common.Utilities;
- using MECF.Framework.UI.Client.CenterViews.DataLogs.ProcessHistory;
- using MECF.Framework.UI.Client.ClientBase;
- using MECF.Framework.UI.Client.ClientBase.Charting;
- using MECF.Framework.UI.Client.ClientBase.EventArgs;
- using MECF.Framework.UI.Client.ClientBase.Tree;
- using OpenSEMI.ClientBase;
- using SciChart.Charting.Visuals.Axes;
- using SciChart.Charting.Visuals.RenderableSeries;
- using SciChart.Core.Extensions;
- namespace MECF.Framework.UI.Client.CenterViews.Operations.RealTime
- {
- public class RealtimeViewModel : BusyIndicateableUiViewModelBase
- {
- #region Variables
- /// <summary>
- /// 允许监控的最大曲线数量
- /// </summary>
- private const int MAX_PARAMETERS_ALLOWED = 200;
- private readonly RealtimeProvider _provider = new RealtimeProvider();
- private bool _enableAutoZoom = true;
- private int _pointCount;
- private readonly PeriodicJob _thread;
- /// <summary>
- /// Monitor中添加数据点时直接向DataSeries对象添加,已实现跨线程操作。
- /// </summary>
- private readonly List<FastLineDataSeries> _dataSeriesList;
- /// <summary>
- /// 更新报告导出信息。
- /// </summary>
- private readonly IProgress<ProgressUpdatingEventArgs> _exportingProgressReporter;
- #endregion
- #region Constructors
- public RealtimeViewModel()
- {
- DisplayName = "Realtime";
- SelectedData = new ChartingLineSeriesCollection(DisplayName);
- ParameterNodes = new TreeNode(DisplayName)
- {
- MaxTerminalSelectionAllowed = MAX_PARAMETERS_ALLOWED
- };
- ParameterNodes.ChildNodes.AddRange(_provider.GetTreeNodeParameters());
- ParameterNodes.TerminalNodeSelectionChanged += OnNodeSelectionChanged;
- IntervalSaved = true;
- TrendInterval = 500;
- TimeSpanSaved = true;
- TrendTimeSpan = 60 * 5;
- _thread = new PeriodicJob(TrendInterval, MonitorData, "RealTime", true);
- _pointCount = Math.Max(TrendTimeSpan * 1000 / TrendInterval, 10);
- _dataSeriesList = new List<FastLineDataSeries>();
- _exportingProgressReporter = new Progress<ProgressUpdatingEventArgs>(e =>
- {
- BusyIndicatorContent = e.Message;
- });
- }
- #endregion
- #region Properties
- public bool IsPermission => this.Permission == 3;
- public TreeNode ParameterNodes { get; }
- public ChartingLineSeriesCollection SelectedData { get; set; }
- public AutoRange ChartAutoRange => EnableAutoZoom ? AutoRange.Always : AutoRange.Never;
- public bool EnableAutoZoom
- {
- get => _enableAutoZoom;
- set
- {
- _enableAutoZoom = value;
- NotifyOfPropertyChange(nameof(EnableAutoZoom));
- NotifyOfPropertyChange(nameof(ChartAutoRange));
- }
- }
- [IgnorePropertyChange]
- public int TrendInterval { get; set; }
- public bool IntervalSaved { get; set; }
- [IgnorePropertyChange]
- public int TrendTimeSpan { get; set; }
- public bool TimeSpanSaved { get; set; }
- private bool _IsHold;
- public bool IsHold
- {
- get { return _IsHold; }
- set
- {
- if (_IsHold!=value)
- {
- _IsHold = value;
- if (_IsHold) EnableAutoZoom = false;
- else EnableAutoZoom = true;
- NotifyOfPropertyChange(nameof(IsHold));
- }
- }
- }
- #endregion
- #region Methods
- protected bool MonitorData()
- {
- try
- {
- Dictionary<string, object> data = null;
- if (!IsHold&&SelectedData.Count > 0)
- {
- data = QueryDataClient.Instance.Service.PollData(SelectedData.Select(r => (r as FastLineSeries)?.DataName).ToList());
- AppendData(data);
- }
- for (var j = 0; j < ParameterNodes.ChildNodes.Count; j++)
- {
- var par = ParameterNodes.ChildNodes[j];
- par.IsVisibilityParentNode = Visibility.Hidden;
- }
- }
- catch (Exception ex)
- {
- LOG.Error(ex.Message);
- }
- return true;
- }
- public void AppendData(Dictionary<string, object> data)
- {
- if (data == null)
- return;
- var dt = DateTime.Now;
- foreach (var ds in _dataSeriesList)
- {
- if (ds == null || !data.ContainsKey(ds.SeriesName))
- continue;
- if (data[ds.SeriesName] is bool)
- {
- ds.Append(dt, ((bool)data[ds.SeriesName] ? 1 : 0) * ds.Factor + ds.Offset, new ParameterNodePoint(dt, ((bool)data[ds.SeriesName] ? 1 : 0)));
- continue;
- }
- if (!double.TryParse(data[ds.SeriesName].ToString(), out var value))
- continue;
- ds.Append(dt, value * ds.Factor + ds.Offset, new ParameterNodePoint(dt, value));
- }
- }
- private void UpdateFifoCapacity(int capacity)
- {
- foreach (var renderableSeries in SelectedData)
- {
- if (renderableSeries is FastLineSeries line)
- {
- var ds = line.GetDataSeries();
- var copyMetaData = ds.Metadata.Where(x => x != null && ((ParameterNodePoint)x).Time > DateTime.Now.AddSeconds(-TrendTimeSpan)).ToList();
- ds.FifoCapacity = capacity;
- foreach (ParameterNodePoint item in copyMetaData)
- {
- ds.Append(item.Time, item.Value);
- }
- }
- }
- }
- public void SetInterval()
- {
- _thread.ChangeInterval(TrendInterval);
- _pointCount = Math.Max(10, TrendTimeSpan * 1000 / TrendInterval);
- IntervalSaved = true;
- NotifyOfPropertyChange(nameof(IntervalSaved));
- UpdateFifoCapacity(_pointCount);
- }
- public void SetTimeSpan()
- {
- _pointCount = Math.Max(10, TrendTimeSpan * 1000 / TrendInterval);
- TimeSpanSaved = true;
- NotifyOfPropertyChange(nameof(TimeSpanSaved));
- UpdateFifoCapacity(_pointCount);
- }
- #endregion
- #region Events
- public void OnNodeSelectionChanged(object sender, TreeNodeSelectionChangedEventArgs e)
- {
- if (e.NewValue == true && SelectedData.Count >= MAX_PARAMETERS_ALLOWED)
- {
- e.Cancel = true;
- return;
- }
- var line = SelectedData.Cast<FastLineSeries>().FirstOrDefault(x => x.DataName == e.Source.FullName);
- switch (e.NewValue)
- {
- case false:
- {
- if (line != null)
- {
- _dataSeriesList.Remove(line.GetDataSeries());
- SelectedData.Remove(line);
- }
- break;
- }
- case true:
- {
- if (line == null)
- {
- var series = new FastLineSeries(e.Source.FullName)
- {
- BackendParameterNode = e.Source
- };
- series.GetDataSeries().FifoCapacity = _pointCount;
- SelectedData.Add(series);
- _dataSeriesList.Add(series.GetDataSeries());
- SelectedData.ResetColors();
- }
- break;
- }
- default:
- break;
- }
- }
- public void Deleted(object sender, RenderableSeriesDeletingEventArgs e)
- {
- var list = e.Source.Cast<FastLineSeries>().ToList();
- var total = SelectedData.Count;
- for (var i = total - 1; i >= 0; i--)
- {
- if (i < list.Count)
- {
- list[i].BackendParameterNode.IsSelected = false;
- }
- }
- _dataSeriesList.Clear();
- ((RealtimeView)View).tvParameterNodes.ClearPresetGroupSelectionOnly();
- }
- public void Exporting(object sender, EventArgs e)
- {
- BusyIndicatorContent = "Exporting ...";
- IsBusy = true;
- }
- public void Exported(object sender, EventArgs e)
- {
- IsBusy = false;
- }
- public void ProgressUpdating(object sender, ProgressUpdatingEventArgs e)
- {
- _exportingProgressReporter.Report(e);
- }
- public override void Cancel()
- {
- if (View is RealtimeView view)
- {
- view.dataGrid.CancelOperation();
- }
- }
- public void ArrowClick(string direction)
- {
- var view = GetView() as RealtimeView;
- switch (direction)
- {
- case "Up":
- view.sciChart.ChartModifier.YAxis.Scroll(50, SciChart.Charting.ClipMode.ClipAtMax);
- break;
- case "Down":
- view.sciChart.ChartModifier.YAxis.Scroll(-50, SciChart.Charting.ClipMode.ClipAtMin);
- break;
- case "Left":
- view.sciChart.ChartModifier.XAxis.Scroll(-50, SciChart.Charting.ClipMode.ClipAtMin);
- break;
- case "Right":
- view.sciChart.ChartModifier.XAxis.Scroll(50, SciChart.Charting.ClipMode.ClipAtMax);
- break;
- }
- }
- public void ZoomInClick(int index)
- {
- var view = GetView() as RealtimeView;
- index += 1;
- if ((index & 0x01) == 1)
- view.sciChart.ChartModifier.XAxis.ZoomBy(-0.1, -0.1);
- if ((index & 0x02) == 2)
- view.sciChart.ChartModifier.YAxis.ZoomBy(-0.1, -0.1);
- }
- public void ZoomOutClick(int index)
- {
- var view = GetView() as RealtimeView;
- index += 1;
- if ((index & 0x01) == 1)
- view.sciChart.ChartModifier.XAxis.ZoomBy(0.1, 0.1);
- if ((index & 0x02) == 2)
- view.sciChart.ChartModifier.YAxis.ZoomBy(0.1, 0.1);
- }
- #endregion
- }
- }
|