From 80fe6835e1331a3505bf533d5a6db36f0669e04e Mon Sep 17 00:00:00 2001 From: mzhifa Date: Mon, 28 Aug 2023 00:13:33 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=AD=A3=E5=B8=B8=E6=98=BE?= =?UTF-8?q?=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Models/WavesModel.cs | 4 +- .../Mseed2asciiApi.cs | 20 +- .../Service/RedisListService.cs | 6 +- .../ViewModels/ChartPlotRealDataViewModel.cs | 268 ++++++++++++------ .../Views/ChartPlotRealDataView.xaml | 4 +- StartServerWPF/StartServerWPF.csproj | 1 + StartServerWPF/Views/MainWindow.xaml | 2 +- 7 files changed, 207 insertions(+), 98 deletions(-) diff --git a/StartServerWPF.Modules.MseedChart/Models/WavesModel.cs b/StartServerWPF.Modules.MseedChart/Models/WavesModel.cs index ef3e3b7..5616eb9 100644 --- a/StartServerWPF.Modules.MseedChart/Models/WavesModel.cs +++ b/StartServerWPF.Modules.MseedChart/Models/WavesModel.cs @@ -25,7 +25,7 @@ namespace StartServerWPF.Modules.MseedChart.Models //添加Z分量波形 if (item.dz.Count > 0) { - axisY.SetRange(2000, 5000); + axisY.SetRange(0, 5000); } axisY.Title.Text = string.Format("Ch{0}.Z", item.Name); axisY.Title.DistanceToAxis = distancetoX; @@ -34,7 +34,7 @@ namespace StartServerWPF.Modules.MseedChart.Models axisY = new AxisY(curChart.ViewXY); if (item.dn.Count > 0) { - axisY.SetRange(2000, 5000); + axisY.SetRange(0, 5000); } axisY.Title.Text = string.Format("Ch{0}.N", item.Name); axisY.Title.DistanceToAxis = distancetoX; diff --git a/StartServerWPF.Modules.MseedChart/Mseed2asciiApi.cs b/StartServerWPF.Modules.MseedChart/Mseed2asciiApi.cs index 7a967d1..78d69fe 100644 --- a/StartServerWPF.Modules.MseedChart/Mseed2asciiApi.cs +++ b/StartServerWPF.Modules.MseedChart/Mseed2asciiApi.cs @@ -1,4 +1,5 @@ -using System; +using ServiceStack; +using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; @@ -37,4 +38,21 @@ namespace StartServerWPF.Modules.MseedChart public char samplesize; public System.IntPtr datasamples; //!< Data samples, \a numsamples of type \a sampletype } + public class ASCiiData + { + public int Index { set; get; } + public string sid { set; get; } + public double samprate { set; get; } + public Int64 numsamples { set; get; } + public Dictionary datas { get; }=new Dictionary(); + + public void AddData(double oaTime, double[] da) + { + if(datas.Count>=100) + { + datas.RemoveKey(0); + } + datas.Add(oaTime, da); + } + } } diff --git a/StartServerWPF.Modules.MseedChart/Service/RedisListService.cs b/StartServerWPF.Modules.MseedChart/Service/RedisListService.cs index c6b3420..76f491d 100644 --- a/StartServerWPF.Modules.MseedChart/Service/RedisListService.cs +++ b/StartServerWPF.Modules.MseedChart/Service/RedisListService.cs @@ -247,6 +247,7 @@ namespace ZhaoXi.Advanced.MyRedis.Service public void Subscribe(string channel, Action actionOnMessage) { var subscription = base.iClient.CreateSubscription(); + subscription.OnSubscribe = c => { Console.WriteLine($"订阅频道{c}"); @@ -260,13 +261,12 @@ namespace ZhaoXi.Advanced.MyRedis.Service }; subscription.OnMessageBytes += (c, s) => { - // ByteToFile(s, "test.mseed"); + // ByteToFile(s, "test.mseed"); actionOnMessage(c, s, subscription); }; Console.WriteLine($"开始启动监听 {channel}"); subscription.SubscribeToChannels(channel); //blocking } - public void UnSubscribeFromChannels(string channel) { var subscription = base.iClient.CreateSubscription(); @@ -274,7 +274,7 @@ namespace ZhaoXi.Advanced.MyRedis.Service //subscription.UnSubscribeFromAllChannels(); } - public static bool ByteToFile(byte[] byteArray, string fileName) + public bool ByteToFile(byte[] byteArray, string fileName) { bool result = false; try diff --git a/StartServerWPF.Modules.MseedChart/ViewModels/ChartPlotRealDataViewModel.cs b/StartServerWPF.Modules.MseedChart/ViewModels/ChartPlotRealDataViewModel.cs index 18ada42..4c6bec1 100644 --- a/StartServerWPF.Modules.MseedChart/ViewModels/ChartPlotRealDataViewModel.cs +++ b/StartServerWPF.Modules.MseedChart/ViewModels/ChartPlotRealDataViewModel.cs @@ -3,25 +3,20 @@ using Arction.Wpf.Charting.Axes; using Arction.Wpf.Charting.SeriesXY; using Arction.Wpf.Charting.Views.ViewXY; using Microsoft.Win32; -using StartServerWPF.Modules.MseedChart.Models; using Prism.Commands; -using Prism.Events; using Prism.Mvvm; -using SharpDX.Direct2D1; -using SharpDX.DirectWrite; +using Prism.Regions; +using ServiceStack; +using StartServerWPF.Assets; +using StartServerWPF.Modules.MseedChart.Models; using System; -using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Collections.ObjectModel; using System.ComponentModel; -using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.IO; using System.Linq; -using System.Net.Http.Headers; -using System.Reflection; -using System.Security.Cryptography; +using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows; @@ -29,18 +24,9 @@ using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Markup; using System.Windows.Media; -using System.Windows.Media.Imaging; using System.Windows.Threading; using System.Xml.Linq; -using Prism.Regions; -using static System.Collections.Specialized.BitVector32; using ZhaoXi.Advanced.MyRedis.Service; -using ServiceStack; -using ServiceStack.Redis; -using Arction.Licensing; -using System.Runtime.InteropServices; -using StartServerWPF.Assets; -using ServiceStack.Text; namespace StartServerWPF.Modules.MseedChart.ViewModels { @@ -71,6 +57,9 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels public ConcurrentQueue smList=new ConcurrentQueue(); public List _chartAxisY=new List(); + + // Dictionary cacheChartDic=new Dictionary(); + Dictionary subNameList; #endregion #region 属性 @@ -259,27 +248,25 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels public DelegateCommand OtimeSortCommand => new DelegateCommand(OtimeSort); public DelegateCommand IntervalSureCommand => new DelegateCommand(IntervalSure); public DelegateCommand RealTimeDataCommand => new DelegateCommand(RealTimeData); - - Dictionary subNameList; + private void Loaded() { //N08,N25,N26 - string station = "N05,N10"; var stations = GlobalData.StationNames;// station.Split(','); - smList = _wavesModel.ReadWavesFromJson(stations); + smList = _wavesModel.ReadWavesFromJson(stations); + subNameList = new Dictionary(); } private void UnLoaded() { time.Stop(); - using (RedisListService service = new RedisListService()) + if(subNameList == null) return; + foreach (var subName in subNameList) { - if (subNameList != null) + using (RedisListService service = new RedisListService()) { - foreach (var subName in subNameList) - { - service.UnSubscribeFromChannels(subName.Key); - } + //停止订阅 + service.Publish(subName.Key, "shutoff"); } } } @@ -488,14 +475,13 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels _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(StationsNameVisible) }).ToList(); - + if (_lChartAll != null) { bool isStartRealData = (Convert.ToBoolean(isCheck) == true); @@ -503,65 +489,70 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels { return; } - _lChartAll.BeginUpdate(); + _lChartAll.BeginUpdate(); if (isStartRealData) - { + { _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; - + time.Elapsed -= CompositionTarget_Rendering; time.Elapsed += CompositionTarget_Rendering; LChartALL.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.Scrolling; - time.Start(); + Task.Run(() => + { + Thread.Sleep(5000); + time.Start(); + }); using (RedisListService service = new RedisListService()) { - foreach (var subName in subNameList) - { - service.UnSubscribeFromChannels(subName.Key); - } + service.FlushAll(); } foreach (var subName in subNameList) { Task.Run(() => { - Debug.WriteLine($"注册{1}:{subName.Key}"); using (RedisListService service = new RedisListService()) { - service.Subscribe(subName.Key, (c, message, iRedisSubscription) => + Debug.WriteLine($"注册{1}:{subName.Key}"); { - Mseed2asciiApi.bufferMseedData(message.Length, message); - }); + 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 { time.Stop(); time.Elapsed -= CompositionTarget_Rendering; LChartALL.ViewXY.XAxes[0].ScrollMode = XAxisScrollMode.None; - using (RedisListService service = new RedisListService()) + foreach (var subName in subNameList) { - foreach (var subName in subNameList) + using (RedisListService service = new RedisListService()) { - service.UnSubscribeFromChannels(subName.Key); + service.Publish(subName.Key, "shutoff"); } } } - + _lChartAll.EndUpdate(); } } private void Mseed2AsciiEvent(AsciiDataStruct asciiData) { - DateTime startTime= Convert.ToDateTime(asciiData.endtime).AddHours(8); + DateTime startTime = Convert.ToDateTime(asciiData.endtime).AddHours(8); DateTime endTime = Convert.ToDateTime(asciiData.endtime).AddHours(8); - Debug.WriteLine($"注册{asciiData.sid}:{startTime}"); - var time = endTime - startTime; byte[] bytes = new byte[asciiData.numsamples * asciiData.samplesize]; // IntPtr bufferHandler = Marshal.AllocHGlobal((int)asciiData.datasize); Marshal.Copy(asciiData.datasamples, bytes, 0, bytes.Length); @@ -595,8 +586,8 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels lines.Add(b); } } - string lineStr= String.Join(",", lines); - + Debug.WriteLine($"接收:{asciiData.sid}:{startTime},count:{lines.Count}"); + string lineStr = String.Join(",", lines); using (RedisListService service = new RedisListService()) { service.LPush(name, lineStr); @@ -660,8 +651,7 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels private void StartChart() { - DisposeAllAndClear(_chartAxisY); - subNameList = new Dictionary(); + DisposeAllAndClear(_chartAxisY); ViewXY v = LChartALL.ViewXY; LChartALL.SizeChanged -= LChartALL_SizeChanged; LChartALL.SizeChanged += LChartALL_SizeChanged; @@ -702,7 +692,11 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels 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; @@ -755,7 +749,10 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels subName = $"HA.{name}.06.SHE"; series.LineStyle.Color = System.Windows.Media.Colors.ForestGreen; } - subNameList.Add(subName,i); + if (isAdd) + { + subNameList.Add(subName, new ASCiiData { Index = i, sid = subName }); + } series.LineStyle.Width = 0.2; series.ScrollModePointsKeepLevel = 1; //series.ScrollingStabilizing = true; @@ -867,73 +864,166 @@ namespace StartServerWPF.Modules.MseedChart.ViewModels { RenderNextFrame(); } + static double currentOATime = 0; + List tempData = new List(); private void RenderNextFrame() { - Debug.WriteLine("timeFrame:{0}", DateTime.Now); + Stopwatch stopwatch = Stopwatch.StartNew(); + string minName = string.Empty; if (_lChartAll == null) { return; } - using (RedisListService service = new RedisListService()) + List datasStr = new List(); + //计算数据中最小时间 + if (currentOATime == 0) { + double minTime = DateTime.Now.AddHours(1).ToOADate(); + string name = string.Empty; foreach (var item in subNameList) { - List dataDouList = new List(); + List dataDouList = new List(); + 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()) + { var data = service.Get(item.Key, 0, 0).FirstOrDefault(); - if( data != null) + if (data != null) { - IEnumerable datasStr = data.Split(',').Select(a => Convert.ToDouble(a)); - double oaTime = datasStr.First(); - if (oaTime < DateTime.Now.AddSeconds(-3).ToOADate()) + 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) { - //取出队列数据 service.RemoveStartFromList(item.Key); - var DouData = data.Split(',').Select(a => Convert.ToDouble(a)).ToList(); - DouData.RemoveAt(0); - dataDouList.AddRange(DouData); + _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 < 100) + { + // 不能超过缓存数, 更新数据 + var time = currentTime.AddSeconds(-offset); + var tem = item.Value.datas[time.ToOADate()]; + item.Value.datas[time.ToOADate()] = 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); + } } else { - break; + throw new Exception($"数据解析异常:{item.Key},{currentTime},{firstTime}"); } - //继续查看数据 - // data = service.Get(item.Key, 0, 0).FirstOrDefault(); - } - // data =service.BlockingDequeueItemFromList(item.Key, TimeSpan.FromMilliseconds(5)); - if (dataDouList.Count!=0) + } + else { - _data[item.Value] =dataDouList.ToArray(); + _data[item.Value.Index] = new double[500]; } } - } - // if (_data.ToList().Any(d => d != null)) + item.Value.AddData(currentOATime, _data[item.Value.Index]); + } + stopwatch.Stop(); + double time1 = stopwatch.ElapsedMilliseconds; + stopwatch.Start(); + bool isRefresh = false; + //有新数据开始刷新 + if (tempData.Count > 5) { - _dispatcher.Invoke(() => - { - FeedData(/*chartTitleText*/); - }); + List temDou = new List(); + foreach (var item in subNameList) + { + var d = item.Value.datas.Keys.OrderBy(a => a).ToArray(); + for (int i = 0; i < d.Count(); i++) + { + temDou.AddRange(item.Value.datas[d[i]]); + } + // _data[item.Value.Index] = temDou.ToArray(); + // DateTime time1 = DateTime.Now.AddMinutes(i++); + // _lChartAll.ViewXY.XAxes[0].SetRange(_lChartAll.ViewXY.XAxes[0].DateTimeToAxisValue(time1), + // _lChartAll.ViewXY.XAxes[0].DateTimeToAxisValue(time1.AddSeconds(60))); + } + // isRefresh = true; + tempData.Clear(); } - + _dispatcher.Invoke(() => + { + FeedData(isRefresh /*chartTitleText*/); + }); + stopwatch.Stop(); + double time2 = stopwatch.ElapsedMilliseconds; + Debug.WriteLine("timeFrame:{0},time1:{1},time1:{2}", DateTime.FromOADate(currentOATime), time1, time2); } int _iRound = 0; double _pointsAppended = 0; double[][] _data; - private void FeedData() + private void FeedData(bool isRefresh) { if (_lChartAll != null) { _lChartAll.BeginUpdate(); - + if(isRefresh) + { + for (int seriesIndex = 0; seriesIndex < _channelCount; seriesIndex++) + { + _lChartAll.ViewXY.SampleDataSeries[seriesIndex].Clear(); + } + } //Append data to series for (int seriesIndex = 0; seriesIndex < _channelCount; seriesIndex++) { double[] thisSeriesData = _data[seriesIndex]; - if (thisSeriesData == null) continue; + if(thisSeriesData==null) + { + + } _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); + // System.Diagnostics.Debug.WriteLine("***********index:{0}, pointCount:{1},time:{2}", seriesIndex, + // _lChartAll.ViewXY.SampleDataSeries[seriesIndex].PointCount, DateTime.Now); } //System.Threading.Tasks.Parallel.For(0, _channelCount, (seriesIndex) => //{ diff --git a/StartServerWPF.Modules.MseedChart/Views/ChartPlotRealDataView.xaml b/StartServerWPF.Modules.MseedChart/Views/ChartPlotRealDataView.xaml index bec9882..1faad34 100644 --- a/StartServerWPF.Modules.MseedChart/Views/ChartPlotRealDataView.xaml +++ b/StartServerWPF.Modules.MseedChart/Views/ChartPlotRealDataView.xaml @@ -45,9 +45,9 @@ - 时间间隔: + diff --git a/StartServerWPF/StartServerWPF.csproj b/StartServerWPF/StartServerWPF.csproj index 513348e..1e6d4c1 100644 --- a/StartServerWPF/StartServerWPF.csproj +++ b/StartServerWPF/StartServerWPF.csproj @@ -34,4 +34,5 @@ PreserveNewest + \ No newline at end of file diff --git a/StartServerWPF/Views/MainWindow.xaml b/StartServerWPF/Views/MainWindow.xaml index 27ebfd5..b5b08a5 100644 --- a/StartServerWPF/Views/MainWindow.xaml +++ b/StartServerWPF/Views/MainWindow.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:prism="http://prismlibrary.com/" WindowState="Maximized" - WindowStyle="None" WindowStartupLocation="CenterScreen" MouseDown="Window_MouseDown" + WindowStartupLocation="CenterScreen" MouseDown="Window_MouseDown" prism:ViewModelLocator.AutoWireViewModel="True" Closing="Window_Closing" Title="{Binding Title}" Height="900" Width="1700" >