Browse Source

上传代码

l2736 3 months ago
parent
commit
359ee60aa4
26 changed files with 265 additions and 136 deletions
  1. 2 0
      Avalonia/ShakerApp/App.axaml
  2. 1 1
      Avalonia/ShakerApp/Convert/GreaterThanEqualConverter.cs
  3. 1 1
      Avalonia/ShakerApp/Convert/LessThanEqualConverter.cs
  4. 0 1
      Avalonia/ShakerApp/Program.cs
  5. 12 7
      Avalonia/ShakerApp/ViewModels/MainPage/RandomMainPageViewModel.cs
  6. 12 17
      Avalonia/ShakerApp/ViewModels/MainPage/SineMainPageViewModel.cs
  7. 1 1
      Avalonia/ShakerApp/ViewModels/ShakerConfig/AccelerationConfigViewModel.cs
  8. 48 20
      Avalonia/ShakerApp/ViewModels/ShakerConfig/RandomConfigViewModel.cs
  9. 48 0
      Avalonia/ShakerApp/ViewModels/ShakerConfig/RandomData.cs
  10. 8 0
      Avalonia/ShakerApp/ViewModels/ShakerConfig/RandomPlanItemViewModel.cs
  11. 8 0
      Avalonia/ShakerApp/ViewModels/ShakerConfig/ShakerConfigViewModel.cs
  12. 1 9
      Avalonia/ShakerApp/ViewModels/ShakerConfig/SweepConfigViewModel.cs
  13. 39 7
      Avalonia/ShakerApp/ViewModels/ShakerConfig/SweepData.cs
  14. 1 1
      Avalonia/ShakerApp/ViewModels/ShakerControl/ShakerControlViewModel.cs
  15. 22 14
      Avalonia/ShakerApp/Views/ShakerConfig/RandomConfigView.axaml
  16. 1 0
      Language/Zh-CN/Language.axaml
  17. 3 0
      Shaker.Model/Models/AllConfig.cs
  18. 3 0
      Shaker.Model/ShakerConstant.cs
  19. 8 0
      Shaker.Model/Tools/Tools.cs
  20. 1 8
      Shaker/Program.cs
  21. 3 1
      Shaker/Service.cs
  22. 1 0
      Shaker/ShakerService.Control.cs
  23. 29 26
      Shaker/ShakerService.ReadFifo.cs
  24. 8 8
      Shaker/ViewModel/ServiceRandomConfigViewModel.cs
  25. 3 14
      Shaker/ViewModel/ServiceRandomDataViewModel.cs
  26. 1 0
      Shaker/ViewModel/ServiceRandomIdentifyViewModel.cs

+ 2 - 0
Avalonia/ShakerApp/App.axaml

@@ -49,6 +49,7 @@
         </Style>
 
 
+
         <!--  Add the line below to get OxyPlot UI theme applied.  -->
 
 
@@ -56,5 +57,6 @@
         <StyleInclude Source="avares://OxyPlot.Avalonia/Themes/Default.axaml" />
         <StyleInclude Source="avares://Avalonia.Controls.ColorPicker/Themes/Fluent/Fluent.xaml" />
         <suki:SukiTheme ThemeColor="Blue" />
+
     </Application.Styles>
 </Application>

+ 1 - 1
Avalonia/ShakerApp/Convert/GreaterThanEqualConverter.cs

@@ -12,7 +12,7 @@ namespace ShakerApp.Convert
     {
         public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
-            if(value is int v && parameter is int v1)
+            if(value is int v && int.TryParse(parameter!.ToString(),out var v1))
             {
                 return v <= v1;
             }

+ 1 - 1
Avalonia/ShakerApp/Convert/LessThanEqualConverter.cs

@@ -12,7 +12,7 @@ namespace ShakerApp.Convert
     {
         public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
-            if(value is int v && parameter is int v1)
+            if(value is int v && int.TryParse(parameter!.ToString(), out var v1))
             {
                 return v <= v1;
             }

+ 0 - 1
Avalonia/ShakerApp/Program.cs

@@ -19,7 +19,6 @@ namespace ShakerApp
         public static AppBuilder BuildAvaloniaApp()
             => AppBuilder.Configure<App>()
                 .UsePlatformDetect()
-                .UseFontAlibaba()
                 .LogToTrace();
     }
     public static class FontExtensions

+ 12 - 7
Avalonia/ShakerApp/ViewModels/MainPage/RandomMainPageViewModel.cs

@@ -16,10 +16,10 @@ namespace ShakerApp.ViewModels
     internal class RandomMainPageViewModel:ViewModelBase<RandomDataModel>,IMainPageViewModel
     {
         public AvaloniaList<LineSeries> LineSeries { get; } = new AvaloniaList<LineSeries>();
-        List<OxyColor> oxyColors = new List<OxyColor>() { OxyColors.Black, OxyColors.Green, OxyColors.Red, OxyColors.Red, OxyColors.Yellow, OxyColors.Yellow };
-        List<LineStyle> lineStyles = new List<LineStyle>() { LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.LongDashDotDot, LineStyle.LongDashDotDot };
-        List<string> properties = new List<string>() { nameof(SweepData.Acceleration), nameof(SweepData.TargetAcceleration), nameof(SweepData.UpStopAcceleration), nameof(SweepData.DownStopAcceleration), nameof(SweepData.UpWarnAcceleration), nameof(SweepData.DownWarnAcceleration) };
-        List<SweepData> datas = new List<SweepData>();
+        List<OxyColor> oxyColors = new List<OxyColor>() {OxyColors.Blue, OxyColors.Black, OxyColors.Green, OxyColors.Red, OxyColors.Red, OxyColors.Yellow, OxyColors.Yellow };
+        List<LineStyle> lineStyles = new List<LineStyle>() { LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.LongDashDotDot, LineStyle.LongDashDotDot };
+        List<string> properties = new List<string>() {nameof(RandomData.Driver), nameof(RandomData.Acceleration), nameof(RandomData.TargetAcceleration), nameof(RandomData.UpStopAcceleration), nameof(RandomData.DownStopAcceleration), nameof(RandomData.UpWarnAcceleration), nameof(RandomData.DownWarnAcceleration) };
+        List<RandomData> datas = new List<RandomData>();
         private RandomMainPageViewModel()
         {
             Content = typeof(Views.RandomMainPage);
@@ -47,7 +47,7 @@ namespace ShakerApp.ViewModels
             for (int i = 0; i < oxyColors.Count; i++)
             {
                 LineSeries line = new LineSeries();
-                line.Title = App.Current?.FindResource(ShakerConstant.ShowSweepAccelerationSpectrumNames[i]) + "";
+                line.Title = App.Current?.FindResource(ShakerConstant.ShowRandomAccelerationSpectrumNames[i]) + "";
                 line.Color = oxyColors[i];
                 line.StrokeThickness = 1;
                 line.DataFieldX = nameof(SweepData.Frequency);
@@ -97,7 +97,12 @@ namespace ShakerApp.ViewModels
         public override void UpDateModel(RandomDataModel model)
         {
             base.UpDateModel(model);
-
+            int startindex = (int)(RandomConfigViewModel.Instance.MinFrequency / RandomConfigViewModel.Instance.FrequencyResolution);
+            for(int i=0;i<datas.Count;i++)
+            {
+                datas[i].SetAcceleration(model.CurrentAccelerationSynthesisPSD[i + startindex]);
+                datas[i].SetDriver(model.DriverPSD[i + startindex]);
+            }
         }
 
         public void UpdateData(List<IResultDataModel> model)
@@ -107,7 +112,7 @@ namespace ShakerApp.ViewModels
                 UpDateModel(randomdata);
             }
         }
-        public void SetRefSpectrum(List<SweepData> data)
+        public void SetRefSpectrum(List<RandomData> data)
         {
             datas.Clear();
             datas.AddRange(data);

+ 12 - 17
Avalonia/ShakerApp/ViewModels/MainPage/SineMainPageViewModel.cs

@@ -10,6 +10,7 @@ using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net.Http.Headers;
+using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -137,7 +138,7 @@ namespace ShakerApp.ViewModels
         {
             models.ForEach(sine =>
             {
-                double targetacc = Shaker.Models.Tools.Tools.VoltageToQuantities(sine.CurrentAcceleration, ShakerConfigViewModel.Instance.AccelerationSensitivity);
+                double currentacc = Shaker.Models.Tools.Tools.VoltageToQuantities(sine.CurrentAcceleration, ShakerConfigViewModel.Instance.AccelerationSensitivity);
                 uint currentfreq = (uint)(sine.CurrentFrequency * 1000_000);
                 int index = -1;
                 for (int i = 0; i < datas.Count; i++)
@@ -146,15 +147,15 @@ namespace ShakerApp.ViewModels
                     if (tempfreq == currentfreq)
                     {
                         index = i;
-                        
-                        datas[i].Acceleration = targetacc; 
+                        datas[i].SetAcceleration(currentacc); 
                         if (sine.SweepDirection == Shaker.Models.SweepDirection.Up)
                         {
                             for (int j = i - 1; j >= 0; j--)
                             {
+                                if (datas[j].Frequency > SweepConfigViewModel.Instance.EndFrequency) break;
                                 if (double.IsNaN(datas[j].Acceleration))
                                 {
-                                    datas[j].Acceleration = targetacc;
+                                    datas[j].SetAcceleration(currentacc);
                                 }
                                 else break;
                             }
@@ -163,9 +164,10 @@ namespace ShakerApp.ViewModels
                         {
                             for (int j = i + 1; j < datas.Count; j++)
                             {
+                                if (datas[j].Frequency < SweepConfigViewModel.Instance.StartFrequency) break;
                                 if (double.IsNaN(datas[j].Acceleration))
                                 {
-                                    datas[j].Acceleration = targetacc;
+                                    datas[j].SetAcceleration(currentacc);
                                 }
                                 else break;
                             }
@@ -187,9 +189,10 @@ namespace ShakerApp.ViewModels
                 {
                     for (int j = index; j >= 0; j--)
                     {
+                        if (datas[j].Frequency > SweepConfigViewModel.Instance.EndFrequency) break;
                         if (double.IsNaN(datas[j].Acceleration))
                         {
-                            datas[j].Acceleration = targetacc;
+                            datas[j].SetAcceleration(currentacc);
                         }
                         else break;
                     }
@@ -198,25 +201,17 @@ namespace ShakerApp.ViewModels
                 {
                     for (int j = index + 1; j < datas.Count; j++)
                     {
+                        if (datas[j].Frequency < SweepConfigViewModel.Instance.StartFrequency) break;
                         if (double.IsNaN(datas[j].Acceleration))
                         {
-                            datas[j].Acceleration = targetacc;
+                            datas[j].SetAcceleration(currentacc);
                         }
                         else break;
                     }
                 }
                 double value = 0; double upstop = 0; double upwarn = 0; double downstop = 0; double downwarn = 0;
                 SweepConfigViewModel.Instance.Model.CalcAmpt(sine.CurrentFrequency, ref value, ref upstop, ref upwarn, ref downstop, ref downwarn);
-                datas.Insert(index + 1, new SweepData()
-                {
-                    Acceleration = targetacc,
-                    Frequency = sine.CurrentFrequency,
-                    TargetAcceleration = value,
-                    UpStopAcceleration = upstop,
-                    UpWarnAcceleration = upwarn,
-                    DownStopAcceleration = downstop,
-                    DownWarnAcceleration = downwarn,
-                });
+                datas.Insert(index + 1, new SweepData(sine.CurrentFrequency,currentacc, value,  upstop, downstop, upwarn, downwarn));
             });
         }
         private void UpPlot()

+ 1 - 1
Avalonia/ShakerApp/ViewModels/ShakerConfig/AccelerationConfigViewModel.cs

@@ -19,7 +19,7 @@ namespace ShakerApp.ViewModels
 
         }
         [PropertyAssociation(nameof(AccelerationConfigModel.Weight))]
-        public float Weight { get => Model.Weight; set => SetProperty(ref Model.Weight, value); }
+        public float Weight { get => Model.Weight; set => SetProperty(ref Model.Weight,Math.Clamp(value,0,1)); }
         [PropertyAssociation(nameof(AccelerationConfigModel.Sensitivity))]
         public float Sensitivity { get => Model.Sensitivity;set=> SetProperty(ref Model.Sensitivity, value); }
         [PropertyAssociation(nameof(AccelerationConfigModel.Polarity))]

+ 48 - 20
Avalonia/ShakerApp/ViewModels/ShakerConfig/RandomConfigViewModel.cs

@@ -19,7 +19,7 @@ namespace ShakerApp.ViewModels
 {
     internal class RandomConfigViewModel : ViewModelBase<Shaker.Models.RandomConfigModel>
     {
-        public List<SweepData> RefSpectrum => datas;
+        public List<RandomData> RefSpectrum => datas;
         private RandomConfigViewModel()
         {
             Content = typeof(Views.RandomConfigView);
@@ -160,12 +160,20 @@ namespace ShakerApp.ViewModels
                 displacement.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + "";
                 DisplacementModel.InvalidatePlot(true);
             });
-            CommunicationViewModel.Intance.LocalCommunication?.GetEvent<RandomConfigModel>()?.Subscrip((sender, args) =>
+            GetEvent<AllConfig>().Subscrip((sender, args) =>
             {
-                UpDateModel(args.Data);
-                Refresh();
-
-                CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<RandomConfigModel>()?.Publish(this, args.Data);
+                UpDateModel(args.Data.RandomConfig);
+                if (CommunicationViewModel.Intance.ServiceIsStart)
+                {
+                    CommunicationViewModel.Intance.ServiceCommunication.GetEvent<RandomConfigModel>().Publish(this, args.Data.RandomConfig);
+                }
+                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<RandomConfigModel>()?.Subscrip((sender, args) =>
+                {
+                    UpDateModel(args.Data);
+                    Refresh();
+                    RandomMainPageViewModel.Instance.SetRefSpectrum(datas);
+                    CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<RandomConfigModel>()?.Publish(this, Model);
+                });
             });
         }
         static RandomConfigViewModel()
@@ -195,8 +203,8 @@ namespace ShakerApp.ViewModels
         List<DataPoint> displacementdata = new List<DataPoint>();
         List<OxyColor> oxyColors = new List<OxyColor>() { OxyColors.Green, OxyColors.Red, OxyColors.Red, OxyColors.Yellow, OxyColors.Yellow };
         List<LineStyle> lineStyles = new List<LineStyle>() { LineStyle.Solid, LineStyle.Solid, LineStyle.Solid, LineStyle.LongDashDotDot, LineStyle.LongDashDotDot };
-        List<string> properties = new List<string>() { nameof(SweepData.TargetAcceleration), nameof(SweepData.UpStopAcceleration), nameof(SweepData.DownStopAcceleration), nameof(SweepData.UpWarnAcceleration), nameof(SweepData.DownWarnAcceleration) };
-        List<SweepData> datas = new List<SweepData>();
+        List<string> properties = new List<string>() { nameof(RandomData.TargetAcceleration), nameof(RandomData.UpStopAcceleration), nameof(RandomData.DownStopAcceleration), nameof(RandomData.UpWarnAcceleration), nameof(RandomData.DownWarnAcceleration) };
+        List<RandomData> datas = new List<RandomData>();
         private double rmsAcceleration = 0;
         private double maxDisplacement;
         private double maxVelocity;
@@ -266,15 +274,36 @@ namespace ShakerApp.ViewModels
         public double RMSAcceleration { get => rmsAcceleration; set =>SetProperty(ref rmsAcceleration , value); }
 
         public ICommand AddCommand => new RelayCommand(Add);
+        public override void UpDateModel(RandomConfigModel model)
+        {
+            SpectrumItems.Clear();
+            PlanItems.Clear();
+            for(int i=0;i<model.SpectrumItems.Count;i++)
+            {
+                SpectrumItems.Add(new IndexValueItemViewModel<RandomSpectrumItemViewModel>(i + 1, new RandomSpectrumItemViewModel(model.SpectrumItems[i])));
+            }
+            for(int i=0;i<model.PlanItems.Count;i++)
+            {
+                PlanItems.Add(new IndexValueItemViewModel<RandomPlanItemViewModel>(i + 1, new RandomPlanItemViewModel(model.PlanItems[i])));
+            }
+            base.UpDateModel(model);
+
+        }
         private void Add()
         {
             if (SpectrumItems.Count >= SpectrumItemsCount) return;
-            SpectrumItems.Add(new IndexValueItemViewModel<RandomSpectrumItemViewModel>(SpectrumItems.Count + 1, new RandomSpectrumItemViewModel()));
+            if (Model.SpectrumItems.Count == 0) Model.SpectrumItems.Add(new RandomSpectrumItemModel());
+            else Model.SpectrumItems.Add(Model.SpectrumItems[^1].CloneBase());
+            SpectrumItems.Add(new IndexValueItemViewModel<RandomSpectrumItemViewModel>(SpectrumItems.Count + 1, new RandomSpectrumItemViewModel(Model.SpectrumItems[^1])));
         }
         public ICommand DeleteCommand => new RelayCommand(Delete);
         private void Delete()
         {
             if (SpectrumItems.Count == 0) return;
+            if(Model.SpectrumItems.Count>0)
+            {
+                Model.SpectrumItems.RemoveAt(Model.SpectrumItems.Count - 1);
+            }
             SpectrumItems.RemoveAt(SpectrumItems.Count - 1);
         }
         public ICommand ResetRMSCommand=>new RelayCommand(ResetRMSExecute);
@@ -285,6 +314,7 @@ namespace ShakerApp.ViewModels
             for(int i=0;i<SpectrumItems.Count;i++)
             {
                 SpectrumItems[i].Value.Value *= (ResetRMS*ResetRMS)/(RMSAcceleration * RMSAcceleration);
+                Model.SpectrumItems[0].Value = SpectrumItems[i].Value.Value;
             }
             CanResetRMS = false;
         }
@@ -293,13 +323,19 @@ namespace ShakerApp.ViewModels
         public ICommand AddPlanCommand => new RelayCommand(AddPlan);
         private void AddPlan()
         {
-            if (PlanItems.Count >= 10) return;
-            PlanItems.Add(new IndexValueItemViewModel<RandomPlanItemViewModel>(PlanItems.Count + 1, new RandomPlanItemViewModel()));
+            if (PlanItems.Count >= 10 || Model.PlanItems.Count>=10) return;
+            if (Model.PlanItems.Count == 0) Model.PlanItems.Add(new RandomPlanItemModel());
+            else Model.PlanItems.Add(Model.PlanItems[^1].CloneBase());
+            PlanItems.Add(new IndexValueItemViewModel<RandomPlanItemViewModel>(PlanItems.Count + 1, new RandomPlanItemViewModel(Model.PlanItems[^1])));
         }
         public ICommand DeletePlanCommand => new RelayCommand(DeletePlan);
         private void DeletePlan()
         {
             if (PlanItems.Count == 0) return;
+            if(Model.PlanItems.Count==0)
+            {
+                Model.PlanItems.RemoveAt(Model.PlanItems.Count - 1);
+            }
             PlanItems.RemoveAt(PlanItems.Count - 1);
         }
         public ICommand RefreshPlanCommand => new RelayCommand(RefreshPlan);
@@ -349,15 +385,7 @@ namespace ShakerApp.ViewModels
             displacementdata.Clear();
             for (int i=0;i<f.Length;i++)
             {
-                datas.Add(new SweepData()
-                {
-                    Frequency = f[i],
-                    TargetAcceleration = spectrumdata[0, i],
-                    UpStopAcceleration = spectrumdata[1, i],
-                    UpWarnAcceleration = spectrumdata[2, i],
-                    DownStopAcceleration = spectrumdata[3, i],
-                    DownWarnAcceleration = spectrumdata[4, i]
-                });
+                datas.Add(new RandomData(f[i],double.NaN, double.NaN, spectrumdata[0, i], spectrumdata[1, i], spectrumdata[3, i], spectrumdata[2, i], spectrumdata[4,i]));
                 velocitydata.Add(new DataPoint(f[i], Shaker.Models.Tools.Tools.AccelerationToVelocity(spectrumdata[0, i], f[i])));
                 displacementdata.Add(new DataPoint(f[i], Shaker.Models.Tools.Tools.AccelerationToDisplacement(spectrumdata[0, i], f[i])));
             }

+ 48 - 0
Avalonia/ShakerApp/ViewModels/ShakerConfig/RandomData.cs

@@ -0,0 +1,48 @@
+namespace ShakerApp.ViewModels
+{
+    public class RandomData
+    {
+        public RandomData()
+        {
+
+        }
+
+        public RandomData(double frequency,double driver, double acceleration, double targetAcceleration, double upStopAcceleration, double downStopAcceleration, double upWarnAcceleration, double downWarnAcceleration)
+        {
+            this.driver = driver;
+            this.frequency = frequency;
+            this.acceleration = acceleration;
+            this.targetAcceleration = targetAcceleration;
+            this.upStopAcceleration = upStopAcceleration;
+            this.downStopAcceleration = downStopAcceleration;
+            this.upWarnAcceleration = upWarnAcceleration;
+            this.downWarnAcceleration = downWarnAcceleration;
+        }
+
+        public void SetFrequency(double freq)
+        {
+            frequency = freq;
+        }
+        public void SetAcceleration(double acc)
+        {
+            acceleration = acc;
+        }
+        public void SetDriver(double driver)=>this.driver = driver;
+        private double frequency = double.NaN;
+        private double acceleration = double.NaN;
+        private double targetAcceleration = double.NaN;
+        private double upStopAcceleration = double.NaN;
+        private double downStopAcceleration = double.NaN;
+        private double upWarnAcceleration = double.NaN;
+        private double downWarnAcceleration = double.NaN;
+        private double driver = double.NaN;
+        public double Driver => driver;
+        public double Frequency => frequency;
+        public double Acceleration => acceleration;
+        public double TargetAcceleration => targetAcceleration;
+        public double UpStopAcceleration => upStopAcceleration;
+        public double DownStopAcceleration => downStopAcceleration;
+        public double UpWarnAcceleration => upWarnAcceleration;
+        public double DownWarnAcceleration => downWarnAcceleration;
+    }
+}

+ 8 - 0
Avalonia/ShakerApp/ViewModels/ShakerConfig/RandomPlanItemViewModel.cs

@@ -4,6 +4,14 @@ namespace ShakerApp.ViewModels
 {
     public class RandomPlanItemViewModel:ViewModelBase<RandomPlanItemModel>
     {
+        public RandomPlanItemViewModel() : base()
+        {
+
+        }
+        public RandomPlanItemViewModel(RandomPlanItemModel model):base(model)
+        {
+
+        }
         [PropertyAssociation(nameof(RandomPlanItemModel.Level))]
         public float Level { get => Model.Level; set => SetProperty(ref Model.Level, value); }
         [PropertyAssociation(nameof(RandomPlanItemModel.Time))]

+ 8 - 0
Avalonia/ShakerApp/ViewModels/ShakerConfig/ShakerConfigViewModel.cs

@@ -1,4 +1,5 @@
 using Avalonia.Collections;
+using Avalonia.Controls;
 using Shaker.Models;
 using System;
 using System.Collections.Generic;
@@ -105,6 +106,7 @@ namespace ShakerApp.ViewModels
             GetEvent<AllConfig>().Subscrip((sender, args) =>
             {
                 UpDateModel(args.Data.ShakerConfig);
+                OnPropertyChanged(nameof(AccelerationSensorCount));
                 if(CommunicationViewModel.Intance.ServiceIsStart)
                 {
                     CommunicationViewModel.Intance.ServiceCommunication.GetEvent<Shaker.Models.ShakerConfigModel>().Publish(this, args.Data.ShakerConfig);
@@ -113,6 +115,7 @@ namespace ShakerApp.ViewModels
                 {
                     if (args.Data == null) return;
                     UpDateModel(args.Data);
+                    OnPropertyChanged(nameof(AccelerationSensorCount));
                     CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<Shaker.Models.ShakerConfigModel>()?.Publish(this, args.Data);
                 });
                 GetEvent(Models.Topic.InitSeries).Publish(this, null);
@@ -143,6 +146,11 @@ namespace ShakerApp.ViewModels
         public static ShakerConfigViewModel Instance { get; } = new ShakerConfigViewModel();
         protected override void Save()
         {
+            if(SynthesisType == AccelerationSynthesisType.Synthesis && MathF.Abs(Accelerations.Sum(x=>x.Value.Weight) -1f)>0.0001f)
+            {
+                ShowError(string.Format(App.Current?.FindResource("AccelerationWeightSumError") + "", 1));
+                return;
+            }
             base.Save();
             CommunicationViewModel.Intance.LocalCommunication?.GetEvent<Shaker.Models.ShakerConfigModel>()?.Publish(this, Model);
             CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<Shaker.Models.ShakerConfigModel>()?.Publish(this, Model);

+ 1 - 9
Avalonia/ShakerApp/ViewModels/ShakerConfig/SweepConfigViewModel.cs

@@ -424,15 +424,7 @@ namespace ShakerApp.ViewModels
                 double downstop = 0;
                 double downwarn = 0;
                 Model.CalcAmpt(freq, ref acc, ref upstop, ref upwarn, ref downstop, ref downwarn);
-                datas.Add(new SweepData()
-                {
-                    Frequency =freq,
-                    TargetAcceleration= Math.Round(acc,4),
-                    UpStopAcceleration = upstop,
-                    UpWarnAcceleration = upwarn,
-                    DownStopAcceleration = downstop,
-                    DownWarnAcceleration = downwarn,
-                });
+                datas.Add(new SweepData(freq,double.NaN,Math.Round(acc,4),upstop,downstop,upwarn,downwarn));
                 velocitydata.Add(new DataPoint(freq,Math.Round(Shaker.Models.Tools.Tools.AccelerationToVelocity(acc,freq),4)));
                 displacementdata.Add(new DataPoint(freq,Math.Round(Shaker.Models.Tools.Tools.AccelerationToDisplacement(acc, freq),4)));
             }

+ 39 - 7
Avalonia/ShakerApp/ViewModels/ShakerConfig/SweepData.cs

@@ -2,12 +2,44 @@
 {
     public class SweepData
     {
-        public double Frequency { get; set; } = double.NaN;
-        public double Acceleration { get; set; } = double.NaN;
-        public double TargetAcceleration { get; set; } = double.NaN;
-        public double UpStopAcceleration { get; set; } = double.NaN;
-        public double DownStopAcceleration { get; set; } = double.NaN;
-        public double UpWarnAcceleration { get; set; } = double.NaN;
-        public double DownWarnAcceleration { get; set; } = double.NaN;
+        public SweepData()
+        {
+
+        }
+
+        public SweepData(double frequency, double acceleration, double targetAcceleration, double upStopAcceleration, double downStopAcceleration, double upWarnAcceleration, double downWarnAcceleration)
+        {
+            this.frequency = frequency;
+            this.acceleration = acceleration;
+            this.targetAcceleration = targetAcceleration;
+            this.upStopAcceleration = upStopAcceleration;
+            this.downStopAcceleration = downStopAcceleration;
+            this.upWarnAcceleration = upWarnAcceleration;
+            this.downWarnAcceleration = downWarnAcceleration;
+        }
+
+        public void SetFrequency(double freq)
+        {
+            frequency = freq;
+        }
+        public void SetAcceleration(double acc)
+        {
+            acceleration = acc;
+        }
+        private double frequency = double.NaN;
+        private double acceleration = double.NaN;
+        private double targetAcceleration = double.NaN;
+        private double upStopAcceleration = double.NaN;
+        private double downStopAcceleration = double.NaN;
+        private double upWarnAcceleration = double.NaN;
+        private double downWarnAcceleration = double.NaN;
+
+        public double Frequency => frequency;
+        public double Acceleration => acceleration;
+        public double TargetAcceleration => targetAcceleration;
+        public double UpStopAcceleration => upStopAcceleration;
+        public double DownStopAcceleration => downStopAcceleration;
+        public double UpWarnAcceleration => upWarnAcceleration;
+        public double DownWarnAcceleration => downWarnAcceleration;
     }
 }

+ 1 - 1
Avalonia/ShakerApp/ViewModels/ShakerControl/ShakerControlViewModel.cs

@@ -69,7 +69,7 @@ namespace ShakerApp.ViewModels
             set
             {
                 SetProperty(ref Model.PageType, value);
-                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<ShakerControlModel>()?.Publish(this, Model);
+                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<MainPageType>()?.Publish(this, value);
             }
         }
         [PropertyAssociation(nameof(ShakerControlModel.MaxControlItemCount))]

+ 22 - 14
Avalonia/ShakerApp/Views/ShakerConfig/RandomConfigView.axaml

@@ -321,24 +321,32 @@
                             <ItemsControl ItemsSource="{Binding Source={x:Static vm:ShakerConfigViewModel.Instance}, Path=Accelerations}">
                                 <ItemsControl.ItemTemplate>
                                     <DataTemplate>
-                                        <StackPanel>
-                                            <StackPanel>
-                                                <TextBlock Text="{DynamicResource Weight}" />
-                                                <NumericUpDown
-                                                    Maximum="1"
-                                                    Minimum="0"
-                                                    Value="{Binding Value.Weight}" />
-                                            </StackPanel>
-                                            <TextBlock>
+                                        <Grid RowDefinitions="auto,auto,auto">
+                                            <TextBlock
+                                                Height="{StaticResource ItemHeight}"
+                                                HorizontalAlignment="Center"
+                                                VerticalAlignment="Center">
+                                                <Run Text="{DynamicResource Acceleration}" />
+                                                <Run Text="{Binding Index}" />
+                                            </TextBlock>
+                                            <NumericUpDown
+                                                Grid.Row="1"
+                                                Height="{StaticResource ItemHeight}"
+                                                Margin="10,0,0,0"
+                                                VerticalContentAlignment="Center"
+                                                Maximum="1"
+                                                Minimum="0"
+                                                Value="{Binding Value.Weight}" />
+                                            <TextBlock
+                                                Grid.Row="2"
+                                                Height="{StaticResource ItemHeight}"
+                                                HorizontalAlignment="Center"
+                                                VerticalAlignment="Center">
                                                 <Run Text="{DynamicResource Sensitivity}" />
                                                 <Run Text="{Binding Value.Sensitivity}" />
                                                 <Run Text="mV/g" />
                                             </TextBlock>
-                                            <StackPanel>
-                                                <TextBlock Text="{DynamicResource Sensitivity}" />
-                                                <TextBlock Text="{Binding Value.Sensitivity}" />
-                                            </StackPanel>
-                                        </StackPanel>
+                                        </Grid>
                                     </DataTemplate>
                                 </ItemsControl.ItemTemplate>
                                 <ItemsControl.ItemsPanel>

+ 1 - 0
Language/Zh-CN/Language.axaml

@@ -149,6 +149,7 @@
     <s:String x:Key="DeviceFoundCount">已发现{0}个设备</s:String>
     <s:String x:Key="DeviceConnecting">正在连接设备</s:String>
     <s:String x:Key="DeviceConnectSuccess">设备连接成功</s:String>
+    <s:String x:Key="AccelerationWeightSumError">加速度传感器权重之和必须为{0}</s:String>
 
 
     <s:String x:Key="Start">启动</s:String>

+ 3 - 0
Shaker.Model/Models/AllConfig.cs

@@ -21,5 +21,8 @@ namespace Shaker.Models
         public SweepConfigModel SweepConfig { get; set; }
         [AllowNull]
         public ShakerConfigModel ShakerConfig { get; set; }
+        [AllowNull]
+
+        public RandomConfigModel RandomConfig { get; set; }
     }
 }

+ 3 - 0
Shaker.Model/ShakerConstant.cs

@@ -15,6 +15,7 @@ namespace Shaker.Models
         public static readonly string DisplacementKey = "Displacement";
         public static readonly string AccelerationSpectrumKey = "AccelerationSpectrum";
         public static readonly string AccelerationKey = "Acceleration";
+        public static readonly string DriverKey = "ValveDriveSignal";
         public static readonly string TargetAccelerationKey = "TargetAcceleration";
         public static readonly string UpStopAccelerationKey = "UpStopAcceleration";
         public static readonly string DownStopAccelerationKey = "DownStopAcceleration";
@@ -22,5 +23,7 @@ namespace Shaker.Models
         public static readonly string DownWarnAccelerationKey = "DownWarnAcceleration";
         public static readonly List<string> SweepAccelerationSpectrumNames = new List<string>() { TargetAccelerationKey, UpStopAccelerationKey, DownStopAccelerationKey, UpWarnAccelerationKey, DownWarnAccelerationKey };
         public static readonly List<string> ShowSweepAccelerationSpectrumNames= new List<string>() {AccelerationKey, TargetAccelerationKey, UpStopAccelerationKey, DownStopAccelerationKey, UpWarnAccelerationKey, DownWarnAccelerationKey };
+        public static readonly List<string> RandomAccelerationSpectrumNames = new List<string>() { TargetAccelerationKey, UpStopAccelerationKey, DownStopAccelerationKey, UpWarnAccelerationKey, DownWarnAccelerationKey };
+        public static readonly List<string> ShowRandomAccelerationSpectrumNames = new List<string>() { DriverKey, AccelerationKey, TargetAccelerationKey, UpStopAccelerationKey, DownStopAccelerationKey, UpWarnAccelerationKey, DownWarnAccelerationKey };
     }
 }

+ 8 - 0
Shaker.Model/Tools/Tools.cs

@@ -232,6 +232,14 @@ namespace Shaker.Models.Tools
                 }
             }
         }
+        public static double CalcLevel(double currentlevel,double level)
+        {
+            return Math.Pow(10, level / 20) * currentlevel;
+        }
+        public static float CalcLevel(float currentlevel, float level)
+        {
+            return MathF.Pow(10, level / 20) * currentlevel;
+        }
         /// <summary>
         /// 解交织
         /// </summary>

+ 1 - 8
Shaker/Program.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
+using System.Numerics;
 using System.Runtime.CompilerServices;
 using System.Runtime.Intrinsics;
 
@@ -9,14 +10,6 @@ namespace ShakerService
         static  void Main(string[] args)
         {
             Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
-
-//#if DEBUG
-//            while (!Debugger.IsAttached)
-//            {
-//                Task.Delay(100).Wait();
-//            }
-//            Debugger.Break();
-//#endif
             Service service = new Service();
             service.Init();
             service.StartService();

+ 3 - 1
Shaker/Service.cs

@@ -23,7 +23,7 @@ namespace ShakerService
         public Service()
         {
             var path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
-            DateTime dateTime = File.GetLastWriteTime(Assembly.GetEntryAssembly().Location);
+            DateTime dateTime = File.GetLastWriteTime(Assembly.GetEntryAssembly()!.Location);
             Log.Default.Debug($"程序生成时间:{dateTime:F}" );
             Communication.Instance.StartService("0,0,0,0",ServiceConfigViewModel.Instance.Port);
             Log.Default.Info($"监听端口{ServiceConfigViewModel.Instance.Port}");
@@ -48,7 +48,9 @@ namespace ShakerService
         private Haukcode.HighResolutionTimer.HighResolutionTimer ReadConfigTimer = new Haukcode.HighResolutionTimer.HighResolutionTimer();
         private AutoResetEvent WaitTriggerLock = new AutoResetEvent(false);
         private AutoResetEvent WaitRandomDataLocker = new AutoResetEvent(false);
+        [AllowNull]
         private Thread UpAmpttimerThread;
+        [AllowNull]
         private Thread ReadConfigTimerThread;
         /// <summary>
         /// 设备发生主循环

+ 1 - 0
Shaker/ShakerService.Control.cs

@@ -58,6 +58,7 @@ namespace ShakerService
                     ShakerConfig = ServiceShakerConfigViewModel.Instance.Model,
                     ShakerControl = ServiceShakerControlViewModel.Instance.Model,
                     ShakerStatus = ServiceShakerStatusViewModel.Instance.Model,
+                    RandomConfig = ServiceRandomConfigViewModel.Instance.Model,
                 };
                 Log.Default.Info("同步参数");
                 return config;

+ 29 - 26
Shaker/ShakerService.ReadFifo.cs

@@ -81,24 +81,25 @@ namespace ShakerService
                         case RandomTestStep.Up:
                             {
                                 ServiceRandomConfigViewModel.Instance.RandomData.RandomStatus = RandomStatus.Up;
-                                int i = 0;
-                                var accrms = Enumerable.Range(0, ServiceConfigViewModel.Instance.AnalogCount)
-                                    .Where(x => ServiceShakerConfigViewModel.Instance.AnalogSignals[x].AnalogType == AnalogType.DivideAcceleration)
-                                    .Select(x=>
+                                int index = 0;
+                                for(int i=0;i< ServiceConfigViewModel.Instance.AnalogCount;i++)
+                                {
+                                    if(ServiceShakerConfigViewModel.Instance.AnalogSignals[i].AnalogType == AnalogType.DivideAcceleration)
                                     {
-                                        var data = ServiceDataCacheViewModel.Instance.GetAnalogData(x).Select(x => (double)x).ToArray();
-                                        data = ServiceRandomConfigViewModel.Instance.RandomData.CalcPSD(data);
-                                        data = ServiceRandomConfigViewModel.Instance.RandomData.AddAccelerationPSD(i, data, false);
-                                        i++;
-                                        return ServiceRandomConfigViewModel.Instance.SpectrumRMS(data);
-                                    });
+                                        var tempdata = ServiceDataCacheViewModel.Instance.GetAnalogData(i).Select(x => (double)x).ToArray();
+                                        tempdata = ServiceRandomConfigViewModel.Instance.RandomData.CalcPSD(tempdata);
+                                        tempdata = ServiceRandomConfigViewModel.Instance.RandomData.AddAccelerationPSD(index, tempdata, false);
+                                        index++;
+                                        ServiceRandomConfigViewModel.Instance.SpectrumRMS(tempdata);
+                                    }
+                                }
                                 ServiceRandomConfigViewModel.Instance.RandomData.SynthesisAcceleration();
-                                i = ServiceShakerConfigViewModel.Instance.AnalogSignals.FindIndex(x => x.AnalogType == AnalogType.GivenDriver);
-                                var data = ServiceDataCacheViewModel.Instance.GetAnalogData(i).Select(x => (double)x).ToArray();
+                                index = ServiceShakerConfigViewModel.Instance.AnalogSignals.FindIndex(x => x.AnalogType == AnalogType.GivenDriver);
+                                var data = ServiceDataCacheViewModel.Instance.GetAnalogData(index).Select(x => (double)x).ToArray();
                                 data = ServiceRandomConfigViewModel.Instance.RandomData.CalcPSD(data);
                                 ServiceRandomConfigViewModel.Instance.RandomData.AddDriverPSD(data, false);
 
-                                if(ServiceRandomConfigViewModel.Instance.RandomData.CurrentAccelerationSynthesisSpectrumRMS<ServiceRandomConfigViewModel.Instance.Identify.EndLevel)
+                                if (ServiceRandomConfigViewModel.Instance.RandomData.CurrentAccelerationSynthesisSpectrumRMS < ServiceRandomConfigViewModel.Instance.Identify.EndDisplacement)
                                 {
                                     ServiceRandomConfigViewModel.Instance.RandomData.CurrentTestLevel = (ServiceRandomConfigViewModel.Instance.Identify.UpLevel + 1) * ServiceRandomConfigViewModel.Instance.RandomData.CurrentTestLevel;
                                 }
@@ -110,6 +111,7 @@ namespace ShakerService
                                 double[] drive = ServiceRandomConfigViewModel.Instance.RandomData.CalcIdentifyDriver(RandomTestStep.Identify, ServiceRandomConfigViewModel.Instance.RandomData.CurrentTestLevel); 
                                 uint count = 0;
                                 ShakerFpga.Instance.Read.Write(ref drive[0], 0, (uint)drive.Length, ref count);
+                                ServiceRandomConfigViewModel.Instance.RandomData.SendData();
                             }
                             break;
                         case RandomTestStep.Stop:
@@ -121,24 +123,25 @@ namespace ShakerService
                         case RandomTestStep.Identify:
                             {
                                 ServiceRandomConfigViewModel.Instance.RandomData.RandomStatus = RandomStatus.Identify;
-                                int i = 0;
-                                var accrms = Enumerable.Range(0, ServiceConfigViewModel.Instance.AnalogCount)
-                                    .Where(x => ServiceShakerConfigViewModel.Instance.AnalogSignals[x].AnalogType == AnalogType.DivideAcceleration)
-                                    .Select(x =>
+                                int index = 0;
+                                for (int i = 0; i < ServiceConfigViewModel.Instance.AnalogCount; i++)
+                                {
+                                    if (ServiceShakerConfigViewModel.Instance.AnalogSignals[i].AnalogType == AnalogType.DivideAcceleration)
                                     {
-                                        var data = ServiceDataCacheViewModel.Instance.GetAnalogData(x).Select(x => (double)x).ToArray();
-                                        data = ServiceRandomConfigViewModel.Instance.RandomData.CalcPSD(data);
-                                        data = ServiceRandomConfigViewModel.Instance.RandomData.AddAccelerationPSD(i, data, true);
-                                        i++;
-                                        return ServiceRandomConfigViewModel.Instance.SpectrumRMS(data);
-                                    });
+                                        var tempdata = ServiceDataCacheViewModel.Instance.GetAnalogData(i).Select(x => (double)x).ToArray();
+                                        tempdata = ServiceRandomConfigViewModel.Instance.RandomData.CalcPSD(tempdata);
+                                        tempdata = ServiceRandomConfigViewModel.Instance.RandomData.AddAccelerationPSD(index, tempdata, false);
+                                        index++;
+                                        ServiceRandomConfigViewModel.Instance.SpectrumRMS(tempdata);
+                                    }
+                                }
                                 ServiceRandomConfigViewModel.Instance.RandomData.SynthesisAcceleration();
-                                i = ServiceShakerConfigViewModel.Instance.AnalogSignals.FindIndex(x => x.AnalogType == AnalogType.GivenDriver);
-                                var data = ServiceDataCacheViewModel.Instance.GetAnalogData(i).Select(x => (double)x).ToArray();
+                                index = ServiceShakerConfigViewModel.Instance.AnalogSignals.FindIndex(x => x.AnalogType == AnalogType.GivenDriver);
+                                var data = ServiceDataCacheViewModel.Instance.GetAnalogData(index).Select(x => (double)x).ToArray();
                                 data = ServiceRandomConfigViewModel.Instance.RandomData.CalcPSD(data);
                                 ServiceRandomConfigViewModel.Instance.RandomData.AddDriverPSD(data, true);
                                 ServiceRandomConfigViewModel.Instance.RandomData.IdentifyIndex++;
-                                if(ServiceRandomConfigViewModel.Instance.RandomData.IdentifyIndex>=ServiceRandomConfigViewModel.Instance.Identify.IdentifyFrameCount)
+                                if (ServiceRandomConfigViewModel.Instance.RandomData.IdentifyIndex >= ServiceRandomConfigViewModel.Instance.Identify.IdentifyFrameCount)
                                 {
                                     ServiceRandomConfigViewModel.Instance.RandomData.RandomTestStep = RandomTestStep.Stop;
                                     ServiceRandomConfigViewModel.Instance.RandomData.RandomStatus = RandomStatus.Stop;

+ 8 - 8
Shaker/ViewModel/ServiceRandomConfigViewModel.cs

@@ -22,13 +22,13 @@ namespace ShakerService.ViewModel
         public double FrequencyResolution { get; private set; }
         public uint RandomSampleRate => Model.RandomSampleRate;
         public uint RandomFrameCount => FFTFrameLength / RandomSampleRate;
-        public double[] HanningWindow { get; private set; }
+        public double[] HanningWindow { get; private set; } = new double[0];
         public int MaxFrequency => (int)Model.MaxFrequency;
         public AccelerationSynthesisType SynthesisType => Model.SynthesisType;
         public double MinFrequency => Model.MinFrequency;
         public uint SpectrumLines => (uint)Model.SpectrumLines;
-        public double[] StartWindow { get;private set; }
-        public double[] StopWindow { get; private set; }
+        public double[] StartWindow { get; private set; } = new double[0];
+        public double[] StopWindow { get; private set; } = new double[0];
         public double Sigma =>Model.Sigma;
         public List<ServiceRandomSpectralTableViewModel> SpectralTables { get; } = new List<ServiceRandomSpectralTableViewModel>();
         public ServiceRandomIdentifyViewModel Identify { get; } = new ServiceRandomIdentifyViewModel();
@@ -75,16 +75,16 @@ namespace ShakerService.ViewModel
             try
             {
                 Communication.Instance.DbConnection.DeleteAll<RandomIdentifyModel>(nameof(Identify));
-                Communication.Instance.DbConnection.Insert(Model.Identify, nameof(Identify));
+                Communication.Instance.DbConnection.Insert(Model.Identify,tableName: nameof(Identify));
 
                 Communication.Instance.DbConnection.DeleteAll<RandomSpectrumItemModel>(nameof(SpectrumItems));
-                Communication.Instance.DbConnection.InsertAll(Model.SpectrumItems, nameof(SpectrumItems));
+                Communication.Instance.DbConnection.InsertAll(Model.SpectrumItems, tableName: nameof(SpectrumItems));
 
                 Communication.Instance.DbConnection.DeleteAll<RandomPlanItemModel>(nameof(PlanItems));
-                Communication.Instance.DbConnection.InsertAll(Model.PlanItems, nameof(PlanItems));
+                Communication.Instance.DbConnection.InsertAll(Model.PlanItems, tableName: nameof(PlanItems));
 
                 Communication.Instance.DbConnection.DeleteAll<RandomSpectralTableModel>(nameof(SpectralTables));
-                Communication.Instance.DbConnection.InsertAll(Model.SpectralTables, nameof(SpectralTables));
+                Communication.Instance.DbConnection.InsertAll(Model.SpectralTables, tableName: nameof(SpectralTables));
             }catch(Exception ex)
             {
 
@@ -113,7 +113,7 @@ namespace ShakerService.ViewModel
             FrequencyResolution = MaxFrequency / (double)SpectrumLines;
             FFTFrameLength = (uint)((double)RandomSampleRate / MaxFrequency * SpectrumLines);
             FFTHalfFrameLength = FFTFrameLength >> 1;
-            PSDWindow = Enumerable.Range(0, (int)FFTHalfFrameLength).Select(x => (x * FrequencyResolution >= MinFrequency || x * FrequencyResolution <= MaxFrequency) ? 1d : 0d).ToArray();
+            PSDWindow = Enumerable.Range(0, (int)FFTHalfFrameLength).Select(x => (x * FrequencyResolution >= MinFrequency && x * FrequencyResolution <= MaxFrequency) ? 1d : 0d).ToArray();
             FixedWindow = Enumerable.Repeat(1d, (int)FFTFrameLength).ToArray();
             StartWindow = new double[RandomSampleRate];
             StopWindow = new double[RandomSampleRate];

+ 3 - 14
Shaker/ViewModel/ServiceRandomDataViewModel.cs

@@ -1,5 +1,6 @@
 using Shaker.Models;
 using System.Numerics;
+using System.Runtime.CompilerServices;
 
 namespace ShakerService.ViewModel
 {
@@ -73,7 +74,7 @@ namespace ShakerService.ViewModel
             return DriverPSD;
         }
 
-        public void InitCache()
+        public void ClearCache()
         {
             AccelerationPSDCache.Clear();
             AccelerationPSDCache.AddRange(Enumerable.Range(0, ServiceShakerConfigViewModel.Instance.AccelerationSensorCount).Select(x => new PSDCache()));
@@ -84,18 +85,6 @@ namespace ShakerService.ViewModel
             DriverCache.Clear();
             lastrms.Clear();
         }
-        public void ClearCache()
-        {
-            AccelerationPSDCache.ForEach(x => x.Clear());
-            CurrentAccelerationPSD = Enumerable.Range(0, ServiceShakerConfigViewModel.Instance.AccelerationSensorCount).Select(x => new double[0]).ToList();
-            DriverCache.Clear();
-            HastIdentifyFirstDriver = false;
-            IdentifyIndex++;
-            CurrentAccelerationSpectrumRMS.Clear();
-            CurrentAccelerationSpectrumRMS.AddRange(Enumerable.Repeat(0d, ServiceShakerConfigViewModel.Instance.AccelerationSensorCount));
-            RandomStatus = RandomStatus.Start;
-            lastrms.Clear();
-        }
         public double[] CalcIdentifyFirstDriver()
         {
             if (HastIdentifyFirstDriver) return IdentifyFirstDriver;
@@ -126,7 +115,7 @@ namespace ShakerService.ViewModel
             Complex[] random = Enumerable.Range(0, (int)ServiceRandomConfigViewModel.Instance.FFTHalfFrameLength).Select(x => Complex.Exp(new Complex(0, rdm.NextDouble() * 4 * Math.PI)) * tempvalue[x]).ToArray();
             Complex[] value = new Complex[ServiceRandomConfigViewModel.Instance.FFTFrameLength];
             value[0] = new Complex(tempvalue[0], 0);
-            Array.Copy(random, 0, value, 1, value.Length);
+            Unsafe.CopyBlock(ref Unsafe.As<Complex, byte>(ref value[1]), ref Unsafe.As<Complex, byte>(ref random[0]), (uint)(random.Length * Unsafe.SizeOf<Complex>()));
             for (int i = 1; i < random.Length; i++)
             {
                 value[^i] = new Complex(random[i].Real, -random[i].Imaginary);

+ 1 - 0
Shaker/ViewModel/ServiceRandomIdentifyViewModel.cs

@@ -9,5 +9,6 @@ namespace ShakerService.ViewModel
         public float EndLevel => Model.EndLevel;
         public float MaxDisplacement => Model.MaxDisplacement;
         public uint IdentifyFrameCount => Model.IdentifyFrameCount;
+        public float EndDisplacement => Shaker.Models.Tools.Tools.CalcLevel(StartDisplacement, EndLevel);
     }
 }