ShakerDataViewModel.cs 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. using OxyPlot;
  2. using Shaker.Models;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics.CodeAnalysis;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Runtime.CompilerServices;
  9. using System.Text;
  10. using System.Threading.Tasks;
  11. namespace ShakerApp.ViewModels
  12. {
  13. internal class ShakerDataViewModel:DisplayViewModelBase<IModel>
  14. {
  15. public TDMS.ITDMSFile File => tdmsfile;
  16. [AllowNull]
  17. private TDMS.ITDMSFile tdmsfile;
  18. private object _datalocker = new object();
  19. private Dictionary<Shaker.Models.AnalogType, List<(List<DataPoint>,Models.StatisticsModel)>> AnalogDataCache = new Dictionary<AnalogType, List<(List<DataPoint>, Models.StatisticsModel)>>();
  20. private ShakerDataViewModel()
  21. {
  22. GetEvent<AllConfig>().Subscrip((sender, args) =>
  23. {
  24. CommunicationViewModel.Instance.LocalCommunication.GetEvent(Topic.DATA)?.Subscrip((sender, args) =>
  25. {
  26. if(args.Data.Length>=3 && args.Data[0] is byte[] v && args.Data[1] is uint row && args.Data[2] is uint col)
  27. {
  28. ReceiveData(v, row, col);
  29. }
  30. });
  31. });
  32. }
  33. private void ReceiveData(byte[] data, uint row, uint col)
  34. {
  35. if (row == 0 || col == 0) return;
  36. data = Shaker.Models.Tools.Tools.DecompressionBytes(data);
  37. switch (ViewModels.ShakerStatusViewModel.Instance.RTStatus)
  38. {
  39. case RTStatus.SignalGen:
  40. {
  41. if (tdmsfile == null)
  42. {
  43. tdmsfile = TDMS.TDMSDataBuilder.BuildNew(System.IO.Path.Combine(ViewModels.ShakerSettingViewModel.Instance.DataDirectory, $"{DateTime.Now:yyyy-MM-dd HH-mm-ss}.tdms"),"Data");
  44. Dictionary<string, string> config = new Dictionary<string, string>();
  45. ShakerControlViewModel.Instance.SaveTdmsConfig(tdmsfile);
  46. MainPageViewModel.Instance.SaveTdmsConfig(tdmsfile);
  47. DeviceMangerViewModel.Instance.CurrentDevice?.SaveTdmsConfig(tdmsfile);
  48. }
  49. }
  50. break;
  51. default:
  52. if (tdmsfile != null)
  53. {
  54. tdmsfile.Save();
  55. tdmsfile.Close();
  56. tdmsfile.Dispose();
  57. tdmsfile = null;
  58. }
  59. break;
  60. }
  61. CalcAnalog(data, row, col);
  62. if (ShakerStatusViewModel.Instance.RTStatus == RTStatus.SignalGen && tdmsfile != null)
  63. {
  64. MainPageViewModel.Instance.SaveTestData(tdmsfile);
  65. tdmsfile.Save();
  66. }
  67. CommunicationViewModel.Instance.ServiceCommunication?.GetEvent(Topic.DATA)?.Publish(this, null);
  68. }
  69. static ShakerDataViewModel()
  70. {
  71. }
  72. public List<(List<DataPoint>, Models.StatisticsModel)> GetAnalogData(AnalogType analogType)
  73. {
  74. lock(_datalocker)
  75. {
  76. if(AnalogDataCache.TryGetValue(analogType,out var list))
  77. {
  78. if (list == null) return new List<(List<DataPoint>, Models.StatisticsModel)>();
  79. return list;
  80. }
  81. return new List<(List<DataPoint>, Models.StatisticsModel)>();
  82. }
  83. }
  84. public List<double[]> GetAnalogRawData(AnalogType analogType)
  85. {
  86. lock (_datalocker)
  87. {
  88. if (AnalogDataCache.TryGetValue(analogType, out var list))
  89. {
  90. if (list == null) return new List<double[]>();
  91. return list.Select(x=>x.Item1.Select(x=>x.Y).ToArray()).ToList();
  92. }
  93. return new List<double[]>();
  94. }
  95. }
  96. public double[] GetAnalogRawData(int index)
  97. {
  98. lock (_datalocker)
  99. {
  100. if (index >= ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Count) return new double[0];
  101. var type = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[index].AnalogType;
  102. int seindex = 0;
  103. if (index > 0)
  104. {
  105. seindex = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs.Take(index).Count(x => x.AnalogType == type);
  106. }
  107. return AnalogDataCache[type][seindex].Item1.Select(x => x.Y).ToArray();
  108. }
  109. }
  110. private void CalcAnalog(byte[] data,uint row,uint col)
  111. {
  112. if (data.Length == 0 || row == 0 || col == 0) return;
  113. int bytecount = Unsafe.SizeOf<float>();
  114. lock (_datalocker)
  115. {
  116. AnalogDataCache.Clear();
  117. for (int i = 0; i < ShakerConfigViewModel.Instance.AnalogSignals.Count; i++)
  118. {
  119. if (i >= row) break;
  120. List<DataPoint> dataPoints = new List<DataPoint>();
  121. float max = float.MinValue;
  122. float min = float.MaxValue;
  123. float v = 0;
  124. for (int j= 0; j < col; j++)
  125. {
  126. float tempv = Unsafe.As<byte, float>(ref data[j * bytecount + i * col * bytecount]);
  127. dataPoints.Add(new DataPoint(1.0 / ShakerConfigViewModel.Instance.SampleRate * j, tempv));
  128. max = tempv > max ? tempv : max;
  129. min = tempv < min ? tempv : min;
  130. v += tempv;
  131. }
  132. Models.StatisticsModel model = new Models.StatisticsModel()
  133. {
  134. Name = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Name,
  135. Max = max,
  136. Min = min,
  137. RMS = MainViewModel.Default.Calc.Sum.Rms(ref Unsafe.As<byte,float>(ref data[i*bytecount*col]), col),
  138. Average = v/ col,
  139. Unit = ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].Unit,
  140. };
  141. if (AnalogDataCache.TryGetValue(ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].AnalogType,out var list))
  142. {
  143. if (list == null) list = new List<(List<DataPoint>, Models.StatisticsModel)>();
  144. list.Add((dataPoints,model));
  145. }
  146. else
  147. {
  148. AnalogDataCache[ShakerConfigViewModel.Instance.Model.AnalogSignalConfigs[i].AnalogType] = new List<(List<DataPoint>, Models.StatisticsModel)> { (dataPoints,model) };
  149. }
  150. }
  151. }
  152. GetEvent(Topic.DATA).Publish(this,null);
  153. }
  154. public static ShakerDataViewModel Instance { get; } = new ShakerDataViewModel();
  155. }
  156. }