You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1124 lines
45 KiB
C#

using Arction.Wpf.Charting;
using Arction.Wpf.Charting.Axes;
using Arction.Wpf.Charting.SeriesXY;
using Arction.Wpf.Charting.Views.ViewXY;
using Microsoft.Win32;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using ServiceStack;
using StartServerWPF.Assets;
using StartServerWPF.Modules.MseedChart.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Linq;
using ZhaoXi.Advanced.MyRedis.Service;
namespace StartServerWPF.Modules.MseedChart.ViewModels
{
public class ChartPlotRealDataViewModel : BindableBase, INavigationAware
{
Mseed2asciiApi.LoopCallbackHandler loopCallback;
public ChartPlotRealDataViewModel()
{
_dispatcher = Application.Current.Dispatcher;
_wavesModel = new WavesModel();
(Application.Current.MainWindow as System.Windows.Window).Closing += ApplicationClosingDispose;
1 year ago
IntervalTime=1000;
CreateChart();
loopCallback = new Mseed2asciiApi.LoopCallbackHandler(Mseed2AsciiEvent);
Mseed2asciiApi.MseedDatasCallFun(loopCallback);
GC.KeepAlive(loopCallback);
}
#region 字段
1 year ago
System.Timers.Timer time=new System.Timers.Timer(1000);
Dispatcher _dispatcher;
public int CurPoints;
int _channelCount = 0;
int _samplingFrequency = 500; // 采样频率 (Hz).
WavesModel _wavesModel;
private int _lChartCount = 1;
public ConcurrentQueue<StationModel> smList=new ConcurrentQueue<StationModel>();
public List<AxisY> _chartAxisY=new List<AxisY>();
// Dictionary<string, ASCiiData> cacheChartDic=new Dictionary<string, ASCiiData>();
Dictionary<string, ASCiiData> subNameList;
#endregion
#region 属性
private string _title = "数据中心";
public string Title
{
get { return _title; }
set
{
SetProperty(ref _title, value);
}
}
private bool _isRealtimeData =false;
public bool IsRealtimeData
{
get { return _isRealtimeData; }
set
{
SetProperty(ref _isRealtimeData, value);
}
}
private bool _isMultFiles;
public bool IsMultFiles
{
get { return _isMultFiles; }
set
{
SetProperty(ref _isMultFiles, value);
}
}
private int _xaisInterval;
public int XaisInterval
{
get { return _xaisInterval; }
set
{
SetProperty(ref _xaisInterval, value);
}
}
/// <summary>
/// 波形控件数量
/// </summary>
public int LChartCount
{
get { return _lChartCount; }
set { _lChartCount = value; }
}
private LightningChart _lChartAll;
/// <summary>
/// 所有波形
/// </summary>
public LightningChart LChartALL
{
get { return _lChartAll; }
set { _lChartAll = value; }
}
private FrameworkElement childContent;
public FrameworkElement ChildContent
{
get { return childContent; }
set { childContent = value; }
}
private Grid gridChart;
public Grid GridChart
{
get { return gridChart; }
set { gridChart = value; }
}
private StationEventJson _currentEventTime;
public StationEventJson CurrentEventTime
{
get { return _currentEventTime; }
set { _currentEventTime = value; }
}
private List<StationAxis> _stationsName;
public List<StationAxis> StationsName
{
get { return _stationsName; }
set {
SetProperty(ref _stationsName, value);
}
}
private string _currentTime;
public string CurrentTime
{
get { return _currentTime; }
set {
SetProperty(ref _currentTime, value);
}
}
private YAxisAutoPlacement _yaxisPlacement;
public YAxisAutoPlacement YaxisPlacement
{
get { return _yaxisPlacement; }
set
{
LChartALL.ViewXY.AxisLayout.YAxisAutoPlacement = value;
int distancetoX =_wavesModel.SetYasixPlacement(LChartALL);
foreach (var item in LChartALL.ViewXY.YAxes)
{
item.Title.DistanceToAxis = distancetoX;
}
SetProperty(ref _yaxisPlacement, value);
}
}
1 year ago
private int _IntervalTime=1000;
public int IntervalTime
{
get { return _IntervalTime; }
set
{
if (value >=10)
{
1 year ago
// time.Interval = value;
}
SetProperty(ref _IntervalTime, value);
}
}
private bool _SingleChannel=false;
public bool SingleChannel
{
get { return _SingleChannel; }
set
{
if(!value)
{
YasixZENVisible("SHZ", false);
YasixZENVisible("SHN", false);
YasixZENVisible("SHE", false);
}
else
{
YasixZENVisible("SHZ", true);
YasixZENVisible("SHN", true);
YasixZENVisible("SHE", true);
YasixZENVisible(SelectChannel, false);
}
SetProperty(ref _SingleChannel, value);
}
}
private string _SelectChannel;
public string SelectChannel
{
get { return _SelectChannel; }
set
{
if (SingleChannel)
{
//隐藏上当前轴
YasixZENVisible(_SelectChannel, true);
//显示选择轴
YasixZENVisible(value, false);
}
SetProperty(ref _SelectChannel, value);
}
}
#endregion
#region 事件
public DelegateCommand LoadedCommand => new DelegateCommand(Loaded);
public DelegateCommand UnloadedCommand => new DelegateCommand(UnLoaded);
public DelegateCommand<object> AxesYVisibleCommand => new DelegateCommand<object>(AxesYVisible);
public DelegateCommand<object> FileSelectorCommand => new DelegateCommand<object>(FileSelector);
public DelegateCommand<object> OtimeSortCommand => new DelegateCommand<object>(OtimeSort);
public DelegateCommand IntervalSureCommand => new DelegateCommand(IntervalSure);
public DelegateCommand<object> RealTimeDataCommand => new DelegateCommand<object>(RealTimeData);
private void Loaded()
{
1 year ago
//N08,N25,N26
1 year ago
var stations = GlobalData.StationNames;// station.Split(',');
smList = _wavesModel.ReadWavesFromJson(stations);
subNameList = new Dictionary<string, ASCiiData>();
}
private void UnLoaded()
{
1 year ago
time.Stop();
if(subNameList == null) return;
foreach (var subName in subNameList)
1 year ago
{
using (RedisListService service = new RedisListService())
1 year ago
{
//停止订阅
service.Publish(subName.Key, "shutoff");
1 year ago
}
}
}
private void AxesYVisible(object isCheck)
{
if (_lChartAll != null)
{
bool yAxesVisible = ((bool)isCheck == true);
_lChartAll.BeginUpdate();
foreach (AxisY yAxis in _lChartAll.ViewXY.YAxes)
{
yAxis.Visible = yAxesVisible;
}
_lChartAll.EndUpdate();
}
}
private void FileSelector(object obj)
{
IsMultFiles = Convert.ToBoolean(obj);
OpenFileDialog openFileDialog = new OpenFileDialog
{
RestoreDirectory = true,
Filter = ".mseed|*.mseed|.json|*.json|.txt|*.txt",
};
if (openFileDialog.ShowDialog() == true)
{
string asciiSavePath = openFileDialog.FileName.Replace("Mseed", "Txt");
asciiSavePath = Path.ChangeExtension(asciiSavePath, ".txt");
string JsonPath = Path.ChangeExtension(openFileDialog.FileName, "Json");
Stopwatch st = new Stopwatch();
st.Start();
//读取.json文件
CurrentEventTime = _wavesModel.ReadChartJsonFile(JsonPath);
//读取.mseed文件
smList = _wavesModel.ReadMseedFile(openFileDialog.FileName, asciiSavePath, IsMultFiles);
_channelCount = smList.Count * 3;
CurrentTime = smList.First().BeginTime.ToShortDateString();
StationsName = smList.Select(a => new StationAxis{Name= a.Name,IsChecked=true,SelectCommand =new DelegateCommand<object>(StationsNameVisible)}).ToList();
StartChart();
st.Stop();
Debug.WriteLine("统计时间StartChart************{0}", st.Elapsed);
FeedDatasToChart();
if (CurrentEventTime != null)
{
_wavesModel.CreateAxisYEventTime(CurrentEventTime, LChartALL.ViewXY, smList.ToList());
}
}
}
private void OtimeSort(object isCheck)
{
if (_lChartAll != null&& (_chartAxisY.Count!=0))
{
LChartALL.BeginUpdate();
bool yAxesVisible = ((bool)isCheck == true);
ViewXY v = _lChartAll.ViewXY;
IOrderedEnumerable<LineCollection> lines;
if (yAxesVisible)
{
lines = v.LineCollections.Where(a => a.Tag != null && a.Tag.ToString().Contains("SHZ")).OrderBy(a => a.Lines[0].AX);
}
else
{
lines = v.LineCollections.Where(a => a.Tag != null && a.Tag.ToString().Contains("SHZ")).OrderByDescending(b => b.Lines[0].AX); ;
}
int number = v.YAxes.Count / (_chartAxisY.Count / 3);
foreach (var item in lines.Reverse())
{
int index = item.AssignYAxisIndex;
for (int i = 0; i < number; i++)
{
if (index == -1) continue; //隐藏轴不需要处理
AxisY axisY = v.YAxes[index + i];
v.YAxes.RemoveAt(index + i);
v.YAxes.Insert(i, axisY);
}
}
LChartALL.EndUpdate();
}
}
/// <summary>
/// Y轴的显示和隐藏
/// </summary>
/// <param name="content">SHZ,SHN,SHE</param>
/// <param name="yAxesVisible">true 隐藏轴false显示轴</param>
private void YasixZENVisible(string content, bool yAxesVisible)
{
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
ViewXY v = _lChartAll.ViewXY;
string conStr = (content == "SHZ") ? ".Z" : (content == "SHN") ? ".N" : ".E";
for (int i = 0; i <_chartAxisY.Count; i++)
{
AxisY axisY = _chartAxisY[i];
if (axisY.Title.Text.Contains(conStr))
{
if (yAxesVisible)
{
//隐藏轴
v.YAxes.Remove(axisY);
}
else
{
//显示轴
var axis= v.YAxes.Where(y => y.Title.Text==axisY.Title.Text).FirstOrDefault();
if (axis != null)
{
//找到相同的轴不用处理
continue;
}
string str = axisY.Title.Text.Replace(conStr, "");
int yIndex = 0;
if (content == "SHZ")
{
yIndex = v.YAxes.FindIndex(y => y.Title.Text.Contains(str));
}
else if (content == "SHE")
{
yIndex = v.YAxes.FindLastIndex(y => y.Title.Text.Contains(str));
if (yIndex != -1) yIndex += 1;
}
else
{
yIndex = v.YAxes.FindIndex(y => y.Title.Text.Contains(str));
if (yIndex != -1)
{
if (v.YAxes[yIndex].Title.Text.Contains(".Z"))
{
yIndex = yIndex + 1;
}
}
}
//如果没有查到,直接添加到前面,如果为容器最大索引,只能添加到后面
if (yIndex == -1 || (yIndex == v.YAxes.Count))
{
yIndex = v.YAxes.Count;
v.YAxes.Add(axisY);
}
else
{
v.YAxes.Insert(yIndex, axisY);
}
int sampleIndex = v.SampleDataSeries.FindIndex(y => y.Title.Text == _chartAxisY[i].Title.Text);
v.SampleDataSeries[sampleIndex].AssignYAxisIndex = yIndex;
int lineIndex = v.LineCollections.FindIndex(a => a.Title.Text.Contains(_chartAxisY[i].Title.Text));
if (lineIndex != -1)
{
v.LineCollections[lineIndex].AssignYAxisIndex = yIndex;
}
}
}
}
_lChartAll.EndUpdate();
}
}
private void IntervalSure()
{
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
if (XaisInterval >= 2)
{
_lChartAll.ViewXY.XAxes[0].MajorDivCount = XaisInterval;
}
_lChartAll.EndUpdate();
}
}
private void StationsNameVisible(object obj)
{
var station = obj as StationAxis;
if (_lChartAll != null)
{
_lChartAll.BeginUpdate();
bool yAxesVisible = (station.IsChecked == false);
ViewXY v = _lChartAll.ViewXY;
var yAxisList= _chartAxisY.Where(y => y.Title.Text.Contains(station.Name));
foreach (var item in yAxisList)
{
if (yAxesVisible)
{
v.YAxes.Remove(item);
}
else
{
v.YAxes.Add(item);
//SampleDataSeries查找数据对应的Y轴索引, 重新分配到对应的轴
int sampleIndex = v.SampleDataSeries.FindIndex(s => s.Title.Text == item.Title.Text);
v.SampleDataSeries[sampleIndex].AssignYAxisIndex = v.YAxes.Count()-1;
//LineCollections查找数据对应的Y轴索引, 重新分配到对应的轴
int lineIndex = v.LineCollections.FindIndex(s => s.Title.Text.Contains(item.Title.Text));
if (lineIndex != -1)
{
v.LineCollections[lineIndex].AssignYAxisIndex = v.YAxes.Count() - 1;
}
}
}
_lChartAll.EndUpdate();
}
}
int i = 1;
private void RealTimeData(object isCheck)
{
_channelCount = smList.Count * 3;
CurrentTime = smList.First().BeginTime.ToShortDateString();
StationsName = smList.Select(a => new StationAxis { Name = a.Name, IsChecked = true, SelectCommand = new DelegateCommand<object>(StationsNameVisible) }).ToList();
if (_lChartAll != null)
{
bool isStartRealData = (Convert.ToBoolean(isCheck) == true);
if (smList.Count == 0)
{
return;
}
_lChartAll.BeginUpdate();
if (isStartRealData)
{
currentOATime = 0;
1 year ago
_data = new double[smList.Count * 3][];
StartChart();
//Set real-time monitoring automatic old data destruction
LChartALL.ViewXY.DropOldSeriesData = true;
_pointsAppended = LChartALL.ViewXY.XAxes[0].Minimum;
1 year ago
time.Elapsed -= CompositionTarget_Rendering;
time.Elapsed += CompositionTarget_Rendering;
LChartALL.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.Scrolling;
Task.Run(() =>
{
Thread.Sleep(5000);
time.Start();
});
using (RedisListService service = new RedisListService())
{
service.FlushAll();
}
foreach (var subName in subNameList)
{
Task.Run(() =>
{
using (RedisListService service = new RedisListService())
{
Debug.WriteLine($"注册{1}:{subName.Key}");
{
service.Subscribe(subName.Key, (c, message, iRedisSubscription) =>
{
if(message.Length==7 && System.Text.Encoding.Default.GetString(message)== "shutoff")
{
iRedisSubscription.UnSubscribeFromChannels(subName.Key);
}
Mseed2asciiApi.bufferMseedData(message.Length, message);
});
}
}
});
}
}
else
{
1 year ago
time.Stop();
time.Elapsed -= CompositionTarget_Rendering;
LChartALL.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.None;
foreach (var subName in subNameList)
{
using (RedisListService service = new RedisListService())
{
service.Publish(subName.Key, "shutoff");
}
}
}
_lChartAll.EndUpdate();
}
}
private void Mseed2AsciiEvent(AsciiDataStruct asciiData)
{
DateTime startTime = Convert.ToDateTime(asciiData.endtime).AddHours(8);
1 year ago
DateTime endTime = Convert.ToDateTime(asciiData.endtime).AddHours(8);
byte[] bytes = new byte[asciiData.numsamples * asciiData.samplesize];
// IntPtr bufferHandler = Marshal.AllocHGlobal((int)asciiData.datasize);
Marshal.Copy(asciiData.datasamples, bytes, 0, bytes.Length);
List<double> lines = new List<double>();
1 year ago
//时间添加到开始
lines.Add(startTime.ToOADate());
string[] sid = asciiData.sid.Split('_');
string name = $"HA.{sid[1]}.{sid[2]}.{sid[3]}{sid[4]}{sid[5]}";
if (asciiData.sampletype == 'i')
{
for (int index = 0; index < bytes.Length; index += 4)
{
var a = BitConverter.ToInt32(bytes, index);
lines.Add(a);
}
}
1 year ago
else if (asciiData.sampletype == 'f')
{
for (int index = 0; index < bytes.Length; index += 4)
{
var b = BitConverter.ToSingle(bytes, index);
lines.Add(b);
}
}
else if (asciiData.sampletype == 'd')
{
for (int index = 0; index < bytes.Length; index += 8)
{
var b = BitConverter.ToDouble(bytes, index);
lines.Add(b);
}
}
Debug.WriteLine($"接收:{asciiData.sid}:{startTime},count:{lines.Count}");
string lineStr = String.Join(",", lines);
using (RedisListService service = new RedisListService())
{
1 year ago
service.LPush(name, lineStr);
}
}
#endregion
private void CreateChart()
{
if (LChartALL != null)
{
LChartALL = null;
}
LChartALL = new LightningChart();
LChartALL.Title.Align = ChartTitleAlignment.TopCenter;
LChartALL.ChartRenderOptions.DeviceType = RendererDeviceType.AutoPreferD11;
LChartALL.ChartRenderOptions.LineAAType2D = LineAntiAliasingType.QLAA;
LChartALL.Title.Text = "事件波形";
LChartALL.Title.Font = new WpfFont("等线", 20);
//轴属性和布局
LChartALL.ViewXY.AxisLayout.YAxesLayout = YAxesLayout.Stacked;
LChartALL.ViewXY.AxisLayout.SegmentsGap = 0;
LChartALL.ViewXY.ZoomPanOptions.PanDirection = PanDirection.Horizontal;
LChartALL.ViewXY.ZoomPanOptions.WheelZooming = WheelZooming.Horizontal;
LChartALL.ViewXY.AxisLayout.YAxisAutoPlacement = YAxisAutoPlacement.AllRight;
LChartALL.ViewXY.AxisLayout.YAxisTitleAutoPlacement = false;
LChartALL.ViewXY.AxisLayout.AutoAdjustMargins = false;
LChartALL.ViewXY.ZoomPanOptions.DevicePrimaryButtonAction = UserInteractiveDeviceButtonAction.Pan;
LChartALL.ViewXY.ZoomPanOptions.DeviceSecondaryButtonAction = UserInteractiveDeviceButtonAction.None;
LChartALL.ViewXY.ZoomPanOptions.WheelZooming = WheelZooming.Horizontal;
// 反锯齿系数。值0和1都不会应用反锯齿
LChartALL.ChartRenderOptions.AntiAliasLevel = 0;
//X轴设置
LChartALL.ViewXY.XAxes[0].AllowScrolling = true;
LChartALL.ViewXY.XAxes[0].PanningEnabled = true;
LChartALL.ViewXY.XAxes[0].MajorGrid.Pattern = LinePattern.Solid;
LChartALL.ViewXY.XAxes[0].ValueType = AxisValueType.DateTime;
LChartALL.ViewXY.XAxes[0].KeepDivCountOnRangeChange = true;
//LChartALL.ViewXY.XAxes[0].MajorDiv =6;
LChartALL.ViewXY.XAxes[0].LabelsColor = Colors.Black;
LChartALL.ViewXY.XAxes[0].AutoDivSpacing = false;
LChartALL.ViewXY.XAxes[0].MajorDivCount = 5;
XaisInterval = 5;
//图表背景颜色
LChartALL.ViewXY.GraphBackground.Color = Colors.White;
LChartALL.ViewXY.GraphBackground.GradientColor = Colors.White;
LChartALL.ChartBackground.GradientFill = GradientFill.Solid;
LChartALL.ChartBackground.Color = Color.FromArgb(0, 0, 0, 0);
GridChart = new Grid();
GridChart.ColumnDefinitions.Add(new ColumnDefinition());
GridChart.Name = "chartGrid";
GridChart.Children.Add(LChartALL);
this.ChildContent = GridChart;
}
private void StartChart()
{
DisposeAllAndClear(_chartAxisY);
ViewXY v = LChartALL.ViewXY;
LChartALL.SizeChanged -= LChartALL_SizeChanged;
LChartALL.SizeChanged += LChartALL_SizeChanged;
LChartALL.ViewXY.Zoomed -= ViewXY_Zoomed;
LChartALL.ViewXY.Zoomed += ViewXY_Zoomed;
LChartALL.ViewXY.Panned -= ViewXY_Panned;
LChartALL.ViewXY.Panned += ViewXY_Panned;
DisposeAllAndClear(v.YAxes);
DisposeAllAndClear(v.SampleDataSeries);
DisposeAllAndClear(v.LineCollections);
v.Margins=new Thickness(60, 30, 60, 60);
v.YAxes.AddRange(_wavesModel.CreateYAxisChart(smList.ToList(), LChartALL));
v.LegendBoxes[0].Position = LegendBoxPositionXY.RightCenter;
v.LegendBoxes[0].Offset.SetValues(-10, 180);
v.LegendBoxes[0].Layout = LegendBoxLayout.Vertical;
v.LegendBoxes[0].Visible = false;
v.LegendBoxes[0].Shadow.Color = Colors.Transparent;
v.LegendBoxes[0].BorderColor = Colors.Transparent;
v.AutoSpaceLegendBoxes = true;
v.AxisLayout.SegmentsGap = 3;
v.LegendBoxes[0].Shadow.Visible = false;
StationModel stationModel = smList.First();
var beginTime= stationModel.BeginTime;
if (AxisValueType.DateTime == v.XAxes[0].ValueType)
{
//设置X轴的开始时间
v.XAxes[0].AutoFormatLabels = false;
v.XAxes[0].LabelsTimeFormat = "HH:mm:ss.ff";
v.XAxes[0].DateOriginYear = beginTime.Year;
v.XAxes[0].DateOriginDay = beginTime.Day;
v.XAxes[0].DateOriginMonth = beginTime.Month;
DateTime MaxDateTime = beginTime.AddSeconds(_samplingFrequency == 500 ? 30 : 60);
v.XAxes[0].SetRange(v.XAxes[0].DateTimeToAxisValue(beginTime), v.XAxes[0].DateTimeToAxisValue(MaxDateTime));
}
double firstSampleTimeStamp = v.XAxes[0].DateTimeToAxisValue(beginTime);
int count = stationModel.Dzne.Count;
int number= smList.Count*3;
bool isAdd = false;
if (subNameList.Count == 0)
{
isAdd = true;
}
for (int i = 0; i < number; i++)
{
int seriesIndex = i;
AxisY axisY = v.YAxes[seriesIndex];
axisY.LabelsColor = Colors.Black;
axisY.Title.Shadow.DropColor = Colors.Transparent;
// axisY.Title.Shadow.ContrastColor = Colors.Transparent;
axisY.Title.AllowDragging = true;
axisY.AllowAutoYFit = true;
axisY.Units.Visible = false;
axisY.LabelsFont.Size = 10;
axisY.Title.Angle = 0;
axisY.MinorGrid.Visible = false;
axisY.AutoDivSpacing = false;
axisY.MajorDivCount = 2;
// axisY.MajorDiv = 1;
axisY.MinorDivTickStyle.Visible = false;
axisY.MajorGrid.Visible = true;
axisY.MajorGrid.Pattern = LinePattern.Solid;
axisY.MajorDivTickStyle.Alignment = seriesIndex % 2 == 0 ? Alignment.Near : Alignment.Far;
// axisY.MajorDivTickStyle.LineLength = 6;
axisY.MajorDivTickStyle.Color = Colors.Black;
axisY.Title.Color = Colors.Black;
axisY.Title.Font = new WpfFont("Segoe UI", 10, false, false);
axisY.PanningEnabled = false;
axisY.AllowScrolling = true;
axisY.AllowScaling = true;
SampleDataSeries series = new SampleDataSeries(v, v.XAxes[0], axisY);
series.ShowInLegendBox = false;
series.FirstSampleTimeStamp = firstSampleTimeStamp;
series.SamplingFrequency = _samplingFrequency;
series.Title.Text = axisY.Title.Text;
series.SampleFormat = SampleFormat.DoubleFloat;
string subName = string.Empty;
string name = axisY.Title.Text.Substring(2,3);
if (seriesIndex % 3 == 0)
{
subName = $"HA.{name}.06.SHZ";
series.LineStyle.Color = System.Windows.Media.Colors.DeepSkyBlue;
}
else if (seriesIndex % 3 == 1)
{
subName = $"HA.{name}.06.SHN";
series.LineStyle.Color = System.Windows.Media.Colors.OrangeRed;
}
else if (seriesIndex % 3 == 2)
{
subName = $"HA.{name}.06.SHE";
series.LineStyle.Color = System.Windows.Media.Colors.ForestGreen;
}
if (isAdd)
{
subNameList.Add(subName, new ASCiiData { Index = i, sid = subName });
}
series.LineStyle.Width = 0.2;
series.ScrollModePointsKeepLevel = 1;
//series.ScrollingStabilizing = true;
v.SampleDataSeries.Add(series);
_chartAxisY.Add(axisY);
}
}
private void ViewXY_Panned(object sender, PannedXYEventArgs e)
{
foreach (var item in LChartALL.ViewXY.LineCollections)
{
double b = LChartALL.ViewXY.XAxes[0].ValueToCoordD(item.Lines[0].AX) - 80;
item.Title.Offset.SetValues((int)b, 3);
}
}
private void ViewXY_Zoomed(object sender, ZoomedXYEventArgs e)
{
foreach (var item in LChartALL.ViewXY.LineCollections)
{
double b = LChartALL.ViewXY.XAxes[0].ValueToCoordD(item.Lines[0].AX) - 80;
item.Title.Offset.SetValues((int)b, 3);
}
}
private void LChartALL_SizeChanged(object sender, SizeChangedEventArgs e)
{
int distancetoX = _wavesModel.SetYasixPlacement(LChartALL);
foreach (var item in LChartALL.ViewXY.YAxes)
{
item.Title.DistanceToAxis = distancetoX;
}
foreach (var item in LChartALL.ViewXY.LineCollections)
{
double b = LChartALL.ViewXY.XAxes[0].ValueToCoordD(item.Lines[0].AX)-80;
item.Title.Offset.SetValues((int)b, 3);
}
}
private void FeedDatasToChart()
{
_data = new double[smList.Count * 3][];
try
{
for (int channelIndex = 0; channelIndex < smList.Count; channelIndex++)
{
_data[channelIndex * 3] = smList.ElementAt(channelIndex).dz.ToArray();
_data[channelIndex * 3 + 1] = smList.ElementAt(channelIndex).dn.ToArray();
_data[channelIndex * 3 + 2] = smList.ElementAt(channelIndex).de.ToArray();
}
// Invoke FeedNewDataToChart.
_dispatcher.Invoke(() =>
{
LChartALL.BeginUpdate();
for (int channelIndex = 0; channelIndex < _channelCount; channelIndex++)
{
LChartALL.ViewXY.SampleDataSeries[channelIndex].AddSamples(_data[channelIndex], true);
}
LChartALL.EndUpdate();
});
}
catch (Exception ex)
{
throw ex;
}
}
private void ApplicationClosingDispose(object sender, CancelEventArgs e)
{
if (LChartALL != null)
{
LChartALL.Dispose();
LChartALL = null;
}
}
private void DisposeAllAndClear<T>(List<T> list) where T : IDisposable
{
if (list == null)
{
return;
}
while (list.Count > 0)
{
int lastInd = list.Count - 1;
T item = list[lastInd]; // take item ref from list.
list.RemoveAt(lastInd); // remove item first
if (item != null)
{
(item as IDisposable).Dispose(); // then dispose it.
}
}
}
public void Dispose()
{
gridChart.Children.Clear();
if (LChartALL != null)
{
LChartALL.Dispose();
LChartALL = null;
}
}
#region 实时数据
1 year ago
private void CompositionTarget_Rendering(object sender, System.Timers.ElapsedEventArgs e)
{
RenderNextFrame();
}
static double currentOATime = 0;
List<string> tempData = new List<string>();
private void RenderNextFrame()
{
Stopwatch stopwatch = Stopwatch.StartNew();
string minName = string.Empty;
if (_lChartAll == null)
{
return;
}
List<double> datasStr = new List<double>();
//计算数据中最小时间
if (currentOATime == 0)
{
double minTime = DateTime.Now.AddHours(1).ToOADate();
string name = string.Empty;
1 year ago
foreach (var item in subNameList)
{
List<double> dataDouList = new List<double>();
using (RedisListService service = new RedisListService())
{
var data = service.Get(item.Key, 0, 0).FirstOrDefault();
if (data != null)
{
datasStr = data.Split(',').Select(a => Convert.ToDouble(a)).ToList();
double oaTime = datasStr.First();
if (oaTime < minTime)
{
minTime = oaTime;
currentOATime = oaTime;
name=item.Key;
}
}
}
}
if (currentOATime == 0) return;
Debug.WriteLine("currentTimeFirst:{0},now:{1},sid:{2},count:{3}", DateTime.FromOADate(currentOATime),DateTime.Now, name, datasStr.Count);
}
else
{
//更新图表数据时间,每秒刷新一次
currentOATime = DateTime.FromOADate(currentOATime).AddSeconds(1).ToOADate();
}
foreach (var item in subNameList)
{
using (RedisListService service = new RedisListService())
{
1 year ago
var data = service.Get(item.Key, 0, 0).FirstOrDefault();
if (data != null)
{
datasStr = data.Split(',').Select(a => Convert.ToDouble(a)).ToList();
DateTime firstTime = DateTime.FromOADate(datasStr.First());
DateTime currentTime = DateTime.FromOADate(currentOATime);
datasStr.RemoveAt(0);
if (Math.Abs((currentTime - firstTime).TotalSeconds) < 1 && firstTime.Second == currentTime.Second)
1 year ago
{
service.RemoveStartFromList(item.Key);
_data[item.Value.Index] = datasStr.ToArray();
}
else if ((currentTime - firstTime).TotalSeconds < 0)
{
_data[item.Value.Index] = new double[datasStr.Count];
}
else if ((currentTime - firstTime).TotalSeconds > 0)
{
firstTime.AddMilliseconds(-firstTime.Millisecond);
//出更数据需要重新绘图表点
_data[item.Value.Index] = new double[datasStr.Count];
int offset = (int)(currentTime - firstTime).TotalSeconds;
while (offset > 0)
{
service.RemoveStartFromList(item.Key);
tempData.Add(item.Key+ firstTime);
if (offset < 60)
{
// 不能超过缓存数, 更新数据
var time = currentTime.AddSeconds(-offset);
int iCount= item.Value.datas.Count;
if (iCount - offset > 0)
{
item.Value.datas[iCount - offset] = datasStr.ToArray();
}
}
data = service.Get(item.Key, 0, 0).FirstOrDefault();
if (data == null) break;
datasStr = data.Split(',').Select(a => Convert.ToDouble(a)).ToList();
firstTime = DateTime.FromOADate(datasStr.First());
offset = (int)(currentTime - firstTime).TotalSeconds;
datasStr.RemoveAt(0);
Debug.WriteLine("timeMinData:{0},Time1:{1},sid:{2},offset:{3}", currentTime, firstTime, item.Key, offset);
}
1 year ago
}
else
{
throw new Exception($"数据解析异常:{item.Key},{currentTime},{firstTime}");
1 year ago
}
}
else
{
_data[item.Value.Index] = new double[500];
}
}
item.Value.AddData(currentOATime, _data[item.Value.Index]);
}
stopwatch.Stop();
double time1 = stopwatch.ElapsedMilliseconds;
stopwatch.Start();
bool isRefresh = false;
//有新数据开始刷新
if (tempData.Count > 5)
1 year ago
{
DateTime startTime = DateTime.Today;
foreach (var item in subNameList)
{
List<double> temDou = new List<double>();
var number = item.Value.datas.Count;
for (int i = 0; i < number; i++)
{
temDou.AddRange(item.Value.datas[i]);
}
_data[item.Value.Index] = temDou.ToArray();
if (startTime == DateTime.Today)
{
startTime = DateTime.FromOADate(item.Value.StartOATime).AddSeconds(-item.Value.datas.Count);
}
}
_lChartAll.ViewXY.XAxes[0].SetRange(_lChartAll.ViewXY.XAxes[0].DateTimeToAxisValue(startTime),
_lChartAll.ViewXY.XAxes[0].DateTimeToAxisValue(startTime.AddSeconds(30)));
LChartALL.ViewXY.DropOldSeriesData = true;
_pointsAppended = LChartALL.ViewXY.XAxes[0].Minimum;
isRefresh = true;
tempData.Clear();
1 year ago
}
_dispatcher.Invoke(() =>
{
FeedData(isRefresh /*chartTitleText*/);
});
stopwatch.Stop();
double time2 = stopwatch.ElapsedMilliseconds;
Debug.WriteLine("timeFrame:{0},time1:{1},time1:{2}", DateTime.FromOADate(currentOATime), time1, time2);
}
1 year ago
double _pointsAppended = 0;
double[][] _data;
private void FeedData(bool isRefresh)
{
if (_lChartAll == null) return;
_lChartAll.BeginUpdate();
if (isRefresh)
{
1 year ago
for (int seriesIndex = 0; seriesIndex < _channelCount; seriesIndex++)
{
_lChartAll.ViewXY.SampleDataSeries[seriesIndex].Clear();
}
//foreach (var item in subNameList.Values)
//{
// startTime = DateTime.FromOADate(item.StartOATime).AddSeconds(item.datas.Count);
// _lChartAll.ViewXY.XAxes[0].SetRange(_lChartAll.ViewXY.XAxes[0].DateTimeToAxisValue(startTime),
// _lChartAll.ViewXY.XAxes[0].DateTimeToAxisValue(startTime.AddSeconds(60)));
// LChartALL.ViewXY.DropOldSeriesData = true;
// _pointsAppended = LChartALL.ViewXY.XAxes[0].Minimum;
// var number = item.datas.Count;
// for (int i = 0; i < number; i++)
// {
// foreach (var d in subNameList)
// {
// double[] thisSeriesData = subNameList[d.Key].datas[i];
// _lChartAll.ViewXY.SampleDataSeries[d.Value.Index].AddSamples(thisSeriesData, false);
// }
// _pointsAppended += 1;
// //Set X axis real-time scrolling position
// double last = _pointsAppended;
// _lChartAll.ViewXY.XAxes[0].ScrollPosition = last;
// }
// break;
//}
}
//Append data to series
for (int seriesIndex = 0; seriesIndex < _channelCount; seriesIndex++)
{
double[] thisSeriesData = _data[seriesIndex];
_lChartAll.ViewXY.SampleDataSeries[seriesIndex].AddSamples(thisSeriesData, false);
_data[seriesIndex] = null;
// System.Diagnostics.Debug.WriteLine("***********index:{0}, pointCount:{1},time:{2}", seriesIndex,
// _lChartAll.ViewXY.SampleDataSeries[seriesIndex].PointCount, DateTime.Now);
}
_pointsAppended += 1;
//Set X axis real-time scrolling position
double lastX = _pointsAppended;
_lChartAll.ViewXY.XAxes[0].ScrollPosition = lastX;
//Update sweep bands
if (_lChartAll.ViewXY.XAxes[0].ScrollMode == XAxisScrollMode.Sweeping)
{
//Dark band of old page fading away
double pageLen = _lChartAll.ViewXY.XAxes[0].Maximum - _lChartAll.ViewXY.XAxes[0].Minimum;
double sweepGapWidth = pageLen / 20.0;
_lChartAll.ViewXY.Bands[0].SetValues(lastX - pageLen, lastX - pageLen + sweepGapWidth);
if (_lChartAll.ViewXY.Bands[0].Visible == false)
{
_lChartAll.ViewXY.Bands[0].Visible = true;
}
//Bright new page band
_lChartAll.ViewXY.Bands[1].SetValues(lastX - sweepGapWidth / 6, lastX);
if (_lChartAll.ViewXY.Bands[1].Visible == false)
{
_lChartAll.ViewXY.Bands[1].Visible = true;
}
}
else
{
//Hide sweeping bands if not in sweeping mode
//if (_lChartAll.ViewXY.Bands[0].Visible == true)
//{
// _lChartAll.ViewXY.Bands[0].Visible = false;
//}
//if (_lChartAll.ViewXY.Bands[1].Visible == true)
//{
// _lChartAll.ViewXY.Bands[1].Visible = false;
//}
}
_lChartAll.EndUpdate();
}
public void OnNavigatedTo(NavigationContext navigationContext)
{
var str= navigationContext.Parameters.GetValue<string>("model");
if(str == "实时波形")
{
IsRealtimeData = true;
}
else
{
IsRealtimeData = false;
}
}
public bool IsNavigationTarget(NavigationContext navigationContext)
{
return true;
}
public void OnNavigatedFrom(NavigationContext navigationContext)
{
}
#endregion
}
}