Переглянути джерело

上下位机已正常通信

l2736 3 місяців тому
батько
коміт
ccb3b1d7a2
100 змінених файлів з 2250 додано та 1339 видалено
  1. 7 7
      Avalonia/ShakerApp/Convert/EnumToDescription.cs
  2. 5 5
      Avalonia/ShakerApp/Convert/Type2ViewConverter.cs
  3. 1 1
      Avalonia/ShakerApp/Models/IndexValueItemModel.cs
  4. 1 3
      Avalonia/ShakerApp/Models/ShakerSettingModel.cs
  5. 2 2
      Avalonia/ShakerApp/Tools/PluginsLoader.cs
  6. 2 2
      Avalonia/ShakerApp/Tools/Tools.cs
  7. 4 0
      Avalonia/ShakerApp/ViewModels/About/AboutViewModel.cs
  8. 5 1
      Avalonia/ShakerApp/ViewModels/CommunicationViewModel.cs
  9. 24 13
      Avalonia/ShakerApp/ViewModels/DeviceManger/DeviceMangerViewModel.cs
  10. 4 7
      Avalonia/ShakerApp/ViewModels/DialogsViewModel.cs
  11. 2 2
      Avalonia/ShakerApp/ViewModels/File/LoadConfigViewModel.cs
  12. 2 2
      Avalonia/ShakerApp/ViewModels/File/SaveConfigViewModel.cs
  13. 2 0
      Avalonia/ShakerApp/ViewModels/InputPassWord/InputPassWordViewModel.cs
  14. 2 0
      Avalonia/ShakerApp/ViewModels/MainPage/MainPageViewModel.cs
  15. 4 1
      Avalonia/ShakerApp/ViewModels/MainPage/OutSignalMainPageViewModel.cs
  16. 1 0
      Avalonia/ShakerApp/ViewModels/MainPage/SineMainPageViewModel.cs
  17. 18 2
      Avalonia/ShakerApp/ViewModels/MainViewModel.cs
  18. 12 3
      Avalonia/ShakerApp/ViewModels/Oil/OilSourceStatusViewModel.cs
  19. 4 3
      Avalonia/ShakerApp/ViewModels/Setting/ShakerSettingViewModel.cs
  20. 21 12
      Avalonia/ShakerApp/ViewModels/ShakerConfig/ShakerConfigViewModel.cs
  21. 13 5
      Avalonia/ShakerApp/ViewModels/ShakerConfig/SweepConfigViewModel.cs
  22. 22 50
      Avalonia/ShakerApp/ViewModels/ShakerControl/ShakerControlViewModel.cs
  23. 18 0
      Avalonia/ShakerApp/ViewModels/ShakerControl/ValveConfigItemViewModel.cs
  24. 0 16
      Avalonia/ShakerApp/ViewModels/ShakerSensitivityViewModel.cs
  25. 11 5
      Avalonia/ShakerApp/ViewModels/ShakerStatus/ShakerStatusViewModel.cs
  26. 4 2
      Avalonia/ShakerApp/ViewModels/ViewModelBase.cs
  27. 74 131
      Avalonia/ShakerApp/Views/DebugView/DebugView.axaml
  28. 27 9
      Avalonia/ShakerApp/Views/MainWindow.axaml
  29. 20 2
      Avalonia/ShakerApp/Views/ShakerConfig/ShakerConfigView.axaml
  30. 3 3
      Avalonia/ShakerApp/Views/TimeControl.axaml.cs
  31. 1 1
      Communication/TcpEventBus/MsgTool.cs
  32. 1 1
      Communication/TcpEventBus/TcpEventBus.cs
  33. 1 0
      Language/Zh-CN/Language.axaml
  34. 272 30
      NIFPGA/FPGA.cs
  35. 31 0
      NIFPGA/FPGAArrayFXPReadProperty.cs
  36. 38 0
      NIFPGA/FPGAArrayFXPWriteProperty.cs
  37. 62 0
      NIFPGA/FPGAArrayReadProperty.cs
  38. 79 0
      NIFPGA/FPGAArrayWriteProperty.cs
  39. 26 0
      NIFPGA/FPGAFXPReadProperty.cs
  40. 34 0
      NIFPGA/FPGAFXPWriteProperty.cs
  41. 0 250
      NIFPGA/FPGAProperty.cs
  42. 60 0
      NIFPGA/FPGAReadProperty.cs
  43. 4 0
      NIFPGA/FPGASession.cs
  44. 85 0
      NIFPGA/FPGAWriteProperty.cs
  45. 8 1
      NIFPGA/NIFPGA.projitems
  46. 13 0
      NIFPGA/lvbitx/Bitfile.cs
  47. 1 2
      Shaker.Model/Model/AmptIdentifyConfigModel.cs
  48. 4 1
      Shaker.Model/Model/CircuitModel.cs
  49. 1 2
      Shaker.Model/Model/DeviceInfoModel.cs
  50. 4 1
      Shaker.Model/Model/ErrorInfoModel.cs
  51. 2 5
      Shaker.Model/Model/IModel.cs
  52. 21 0
      Shaker.Model/Model/LevelLogic.cs
  53. 1 3
      Shaker.Model/Model/OilSourceAnalogModel.cs
  54. 3 12
      Shaker.Model/Model/OilSourceModel.cs
  55. 4 1
      Shaker.Model/Model/SearchDeviceModel.cs
  56. 0 31
      Shaker.Model/Model/ShakerConfigModel.cs
  57. 11 7
      Shaker.Model/Model/ShakerControlModel.cs
  58. 4 1
      Shaker.Model/Model/ShakerSecurityModel.cs
  59. 4 1
      Shaker.Model/Model/ShakerSensitivityModel.cs
  60. 4 3
      Shaker.Model/Model/ShakerStatusModel.cs
  61. 4 1
      Shaker.Model/Model/SweepControlItemModel.cs
  62. 1 2
      Shaker.Model/Model/SweepFreqConfigModel.cs
  63. 4 1
      Shaker.Model/Model/SweepItemModel.cs
  64. 13 0
      Shaker.Model/Model/ValveConfigItemModel.cs
  65. 4 0
      Shaker.Model/Models/AccelerationConfigModel.cs
  66. 4 3
      Shaker.Model/Models/AllConfig.cs
  67. 4 0
      Shaker.Model/Models/AnalogSignalConfigModel.cs
  68. 4 1
      Shaker.Model/Models/RandomConfigModel.cs
  69. 4 1
      Shaker.Model/Models/RandomIdentifyModel.cs
  70. 4 1
      Shaker.Model/Models/RandomPlanItemModel.cs
  71. 4 1
      Shaker.Model/Models/RandomSpectrumItemModel.cs
  72. 6 3
      Shaker.Model/Models/ShakerConfigModel.cs
  73. 4 3
      Shaker.Model/Models/SineDataModel.cs
  74. 6 1
      Shaker.Model/Models/SweepConfigModel.cs
  75. 0 10
      Shaker/BitAddressConfig.cs
  76. 5 38
      Shaker/Communication.cs
  77. 23 0
      Shaker/Data/TestType.cs
  78. 18 0
      Shaker/OilSource/BitAddressConfig.cs
  79. 55 2
      Shaker/OilSource/OilSource.cs
  80. 4 0
      Shaker/OilSource/OilSourceConfig.cs
  81. 12 35
      Shaker/Service.RTInit.cs
  82. 13 14
      Shaker/Service.cs
  83. 36 3
      Shaker/ServiceConfig.cs
  84. 412 332
      Shaker/ShakerFpga.cs
  85. 11 9
      Shaker/ShakerService.CalcDisplacement.cs
  86. 20 15
      Shaker/ShakerService.Control.cs
  87. 35 33
      Shaker/ShakerService.ReadConfig.cs
  88. 5 5
      Shaker/ShakerService.ReadFifo.cs
  89. 0 1
      Shaker/ShakerService.WaitTrigger.cs
  90. 28 79
      Shaker/ShakerService.WriteConfig.cs
  91. 0 64
      Shaker/Tools/ServiceConfigTool.cs
  92. 15 1
      Shaker/ViewModel/BaseServiceViewModel.cs
  93. 18 0
      Shaker/ViewModel/SerivceValveConfigItemViewModel.cs
  94. 19 0
      Shaker/ViewModel/ServiceAccelerationConfigViewModel.cs
  95. 20 0
      Shaker/ViewModel/ServiceAnalogSignalConfigViewModel.cs
  96. 0 21
      Shaker/ViewModel/ServiceMainViewModel.cs
  97. 1 0
      Shaker/ViewModel/ServiceRandomConfigViewModel.cs
  98. 159 0
      Shaker/ViewModel/ServiceShakerConfigViewModel.cs
  99. 117 0
      Shaker/ViewModel/ServiceShakerControlViewModel.cs
  100. 64 17
      Shaker/ViewModel/ServiceShakerStatusViewModel.cs

+ 7 - 7
Avalonia/ShakerApp/Convert/EnumToDescription.cs

@@ -28,13 +28,14 @@ namespace ShakerApp.Convert
     }
     public class EnumToDescription : IValueConverter
     {
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
             if (value == null || value == AvaloniaProperty.UnsetValue || !value.GetType().IsEnum) return "";
-            return ((Enum)value)?.Description();
+            if( value is Enum e) return e.Description();
+            return "";
         }
 
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
             throw new NotImplementedException();
         }
@@ -45,13 +46,12 @@ namespace ShakerApp.Convert
         public static string Value { get; } = nameof(ValueDescription.Value);
         public static string Key { get; } = nameof(ValueDescription.Key);
 
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
             if (value == null || value == AvaloniaProperty.UnsetValue || !value.GetType().IsEnum) return null;
             try
             {
-                string parstr = "";
-                if (parameter != null) parstr = parameter.ToString();
+                string parstr = (parameter ==null ?"":parameter.ToString())!;
                 List<Enum> showValues = new List<Enum>();
                 if (!string.IsNullOrEmpty(parstr)) showValues = parstr.Split(",".ToCharArray()).Select(x => (Enum)Enum.ToObject(value.GetType(), int.Parse(x))).ToList();
                 List<ValueDescription> valueDescriptions = new List<ValueDescription>();
@@ -71,7 +71,7 @@ namespace ShakerApp.Convert
             return null;
         }
 
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
             return null;
         }

+ 5 - 5
Avalonia/ShakerApp/Convert/Type2ViewConverter.cs

@@ -13,17 +13,17 @@ namespace ShakerApp.Convert
     public class Type2ViewConverter : IValueConverter
     {
         ConcurrentDictionary<RuntimeTypeHandle, Control> Views = new ConcurrentDictionary<RuntimeTypeHandle,Control>();
-        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
             if (value is Type type)
             {
-                if (parameter != null) return (Control)Activator.CreateInstance(type);
+                if (parameter != null) return (Control)Activator.CreateInstance(type)!;
                 else
                 {
                     if (Views.TryGetValue(type.TypeHandle, out var view)) return view;
                     else
                     {
-                        view = (Control)Activator.CreateInstance(type);
+                        view = (Control)Activator.CreateInstance(type)!;
                         Views[type.TypeHandle] = view;
                         return view;
                     }
@@ -40,7 +40,7 @@ namespace ShakerApp.Convert
                             if (Views.TryGetValue(x.TypeHandle, out var view)) return view;
                             else
                             {
-                                view = (Control)Activator.CreateInstance(x);
+                                view = (Control)Activator.CreateInstance(x)!;
                                 Views[x.TypeHandle] = view;
                                 return view;
                             }
@@ -50,7 +50,7 @@ namespace ShakerApp.Convert
             return null;
         }
 
-        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
         {
             throw new NotImplementedException();
         }

+ 1 - 1
Avalonia/ShakerApp/Models/IndexValueItemModel.cs

@@ -23,7 +23,7 @@ namespace ShakerApp.Models
         public int Index = 0;
         [AllowNull]
         public T Value = default;
-        public object Clone()
+        public override object Clone()
         {
             return new IndexValueItemModel<T>()
             {

+ 1 - 3
Avalonia/ShakerApp/Models/ShakerSettingModel.cs

@@ -13,9 +13,7 @@ namespace ShakerApp.Models
         public RemoteControlModel RemoteControlModel = RemoteControlModel.Lan;
         public bool EnabledRemote = false;
         public bool AutoStartService = false;
-
-
-        public object Clone()
+        public override object Clone()
         {
             return this.CloneBase();
         }

+ 2 - 2
Avalonia/ShakerApp/Tools/PluginsLoader.cs

@@ -42,7 +42,7 @@ namespace ShakerApp.Tools
                             var types = assembly.GetTypes();
                             return types.Where(x => x.GetInterface(typeof(T).FullName!) != null && x.IsAnsiClass && !x.IsAbstract);
                         }
-                        catch (Exception ex)
+                        catch 
                         {
                         }
                         return new Type[0];
@@ -96,7 +96,7 @@ namespace ShakerApp.Tools
             }
             else
             {
-                var results = AllDlls.Where(x => x.IndexOf(arg2.Name) >= 0).ToList();
+                var results = AllDlls.Where(x => x.IndexOf(arg2.Name!) >= 0).ToList();
                 results.ForEach(x =>
                 {
                     try

+ 2 - 2
Avalonia/ShakerApp/Tools/Tools.cs

@@ -82,13 +82,13 @@ namespace ShakerApp.Tools
                 if (ViewCache.TryGetValue(type.TypeHandle, out var control)) return control;
                 else
                 {
-                    ViewCache[type.TypeHandle] = (Control)Activator.CreateInstance(type);
+                    ViewCache[type.TypeHandle] = (Control)Activator.CreateInstance(type)!;
                     return ViewCache[type.TypeHandle];
                 }
             }
             else
             {
-                return (Control)Activator.CreateInstance(type);
+                return (Control)Activator.CreateInstance(type)!;
             }
         }
     }

+ 4 - 0
Avalonia/ShakerApp/ViewModels/About/AboutViewModel.cs

@@ -14,11 +14,15 @@ namespace ShakerApp.ViewModels
         private AboutViewModel()
         {
             Content = typeof(Views.AboutView);
+            ButtonVisibily = false;
         }
         static AboutViewModel()
         {
 
         }
+        public override double Width => 600;
+        public override double Height => 420;
+        public override bool CanResize => false;
         public string OSVersion => Environment.OSVersion.VersionString;
         public string FrameworkVersion => RuntimeInformation.FrameworkDescription;
         public string MachineName => Environment.MachineName;

+ 5 - 1
Avalonia/ShakerApp/ViewModels/CommunicationViewModel.cs

@@ -1,6 +1,7 @@
 using Shaker.Model;
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 using System.Text;
@@ -19,7 +20,7 @@ namespace ShakerApp.ViewModels
         private CommunicationViewModel()
         {
             Tools.PluginsLoader.Defalut.Load<ICommunication.ICommunication>(PlugnsPath)
-                .Select(x => (x.GetType().GetCustomAttribute<ICommunication.CommunicationTypeAttribute>().IsLan, x.GetType()))
+                .Select(x => (x.GetType().GetCustomAttribute<ICommunication.CommunicationTypeAttribute>()!.IsLan, x.GetType()))
                 .ToList()
                 .ForEach(x => CommunicationViewModelTypes[x.IsLan] =x.Item2);
         }
@@ -42,6 +43,7 @@ namespace ShakerApp.ViewModels
                     LocalCommunication = (ICommunication.ICommunication)Activator.CreateInstance(CommunicationViewModelTypes[ShakerSettingViewModel.Instance.RemoteControlModel == Models.RemoteControlModel.Lan])!;
                 }
                 LocalCommunication.Connect(ip, port);
+                MainViewModel.Default.SyncConfig();
             }
             catch
             {
@@ -94,7 +96,9 @@ namespace ShakerApp.ViewModels
             ServiceCommunication?.Close();
         }
         public static CommunicationViewModel Intance { get; } = new CommunicationViewModel();
+        [AllowNull]
         public ICommunication.ICommunication LocalCommunication { get; private set; }
+        [AllowNull]
 
         public ICommunication.ICommunication ServiceCommunication { get; private set; }
         public bool LocalIsConnect { get => localIsConnect; set =>SetProperty(ref localIsConnect , value); }

+ 24 - 13
Avalonia/ShakerApp/ViewModels/DeviceManger/DeviceMangerViewModel.cs

@@ -1,6 +1,7 @@
 using Avalonia.Controls;
 using Shaker.Model;
 using ShakerApp.Tools;
+using SukiUI.Toasts;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -31,7 +32,7 @@ namespace ShakerApp.ViewModels
         }
         public static DeviceMangerViewModel Instance { get; } = new DeviceMangerViewModel();
         [AllowNull]
-        private DeviceInfoViewModel currentDevice;
+        private DeviceInfoViewModel? currentDevice;
 
         public ObservableCollection<IndexValueItemViewModel<DeviceInfoViewModel>> Devices { get; } = new ObservableCollection<IndexValueItemViewModel<DeviceInfoViewModel>>();
         public ICommand SearchDeviceCommand => new CommunityToolkit.Mvvm.Input.RelayCommand(() =>
@@ -41,6 +42,14 @@ namespace ShakerApp.ViewModels
         });
         public bool SearchEnabled { get => searchEnabled; set => SetProperty(ref searchEnabled, value); }
         private CancellationTokenSource source = new CancellationTokenSource();
+        private void WaitMsg(int timeout, CancellationTokenSource source)
+        {
+            Task.Run(async () =>
+            {
+                await Task.Delay(timeout, source.Token);
+                source.Cancel();
+            });
+        }
         private async void SearchDevice()
         {
             int timeout = 10000;
@@ -52,12 +61,8 @@ namespace ShakerApp.ViewModels
             DateTime start = DateTime.Now;
             System.Net.Sockets.UdpClient udpClient = new System.Net.Sockets.UdpClient(Topic.DISCOVERYPORT - 1);
             source = new CancellationTokenSource();
-            Task.Run(() => SendBroadcastMsg());
-            Task.Run(async () =>
-            {
-                await Task.Delay(timeout, source.Token);
-                source.Cancel();
-            });
+            SendBroadcastMsg();
+            WaitMsg(timeout, source);
             while (true)
             {
                 try
@@ -95,7 +100,10 @@ namespace ShakerApp.ViewModels
                 SearchEnabled = true;
                 if (Devices.Count == 0)
                 {
-                    Dialogs.Warning(App.Current?.FindResource("DeviceNoFound") + "");
+                    ToastManager.CreateSimpleInfoToast()
+                    .WithTitle(App.Current?.FindResource("PromptTitle") + "")
+                    .WithContent(App.Current?.FindResource("DeviceNoFound") + "")
+                    .Queue();
                 }
             });
         }
@@ -119,7 +127,7 @@ namespace ShakerApp.ViewModels
             CurrentDevice = null;
 
         }
-        public DeviceInfoViewModel CurrentDevice
+        public DeviceInfoViewModel? CurrentDevice
         {
             get => currentDevice;
             set => SetProperty(ref currentDevice, value);
@@ -127,10 +135,13 @@ namespace ShakerApp.ViewModels
 
         private void SendBroadcastMsg()
         {
-            System.Net.Sockets.UdpClient udpClient = new System.Net.Sockets.UdpClient();
-            Shaker.Model.SearchDeviceModel search = new Shaker.Model.SearchDeviceModel();
-            udpClient.Send(search.GetBytes(), new System.Net.IPEndPoint(IPAddress.Broadcast, Topic.DISCOVERYPORT));
-            udpClient.Close();
+            Task.Run(()=>
+            {
+                System.Net.Sockets.UdpClient udpClient = new System.Net.Sockets.UdpClient();
+                Shaker.Model.SearchDeviceModel search = new Shaker.Model.SearchDeviceModel();
+                udpClient.Send(search.GetBytes(), new System.Net.IPEndPoint(IPAddress.Broadcast, Topic.DISCOVERYPORT));
+                udpClient.Close();
+            });
         }
 
     }

+ 4 - 7
Avalonia/ShakerApp/ViewModels/DialogsViewModel.cs

@@ -9,20 +9,17 @@ namespace ShakerApp.ViewModels
 {
     public class DialogsViewModel
     {
-        private string Caption => (string)App.Current.FindResource("PromptTitle");
-        private string Yes => (string)App.Current.FindResource("PromptYes");
-        private string No => (string)App.Current.FindResource("PromptNo");
+        private string Caption => (string)(App.Current?.FindResource("PromptTitle") ?? "");
+        private string Yes => (string)(App.Current?.FindResource("PromptYes") ?? "");
+        private string No => (string)(App.Current?.FindResource("PromptNo") ?? "");
 
         [AllowNull]
         private ISukiDialogManager _DialogManager;
 
-        [AllowNull]
-        private ISukiToastManager _ToastManager;
 
-        public DialogsViewModel(ISukiDialogManager dialogManager,ISukiToastManager toastManager)
+        public DialogsViewModel(ISukiDialogManager dialogManager)
         {
             _DialogManager = dialogManager;
-            _ToastManager = toastManager;
         }
 
         public bool Error(string msg)

+ 2 - 2
Avalonia/ShakerApp/ViewModels/File/LoadConfigViewModel.cs

@@ -48,10 +48,10 @@ namespace ShakerApp.ViewModels
                 var folder = await TopLevel.GetTopLevel(desktop.MainWindow)!.StorageProvider.OpenFilePickerAsync(new Avalonia.Platform.Storage.FilePickerOpenOptions()
                 {
                     AllowMultiple = false,
-                    Title = App.Current?.FindResource(p) + "",
+                    Title = p == null ? "" : App.Current?.FindResource(p) + "",
                     FileTypeFilter = new FilePickerFileType[]
                     {
-                        new FilePickerFileType($"{App.Current?.FindResource(p)}"){ Patterns = new []{"*.cfg" } }
+                        new FilePickerFileType($"{(p ==null ?"": App.Current?.FindResource(p) + "")}"){ Patterns = new []{"*.cfg" } }
                     }
                 });
                 if (folder != null && folder.Count>0)

+ 2 - 2
Avalonia/ShakerApp/ViewModels/File/SaveConfigViewModel.cs

@@ -47,10 +47,10 @@ namespace ShakerApp.ViewModels
             {
                 var folder = await TopLevel.GetTopLevel(desktop.MainWindow)!.StorageProvider.SaveFilePickerAsync(new Avalonia.Platform.Storage.FilePickerSaveOptions()
                 {
-                    Title = App.Current?.FindResource(p) + "",
+                    Title = p == null ? "" : App.Current?.FindResource(p) + "",
                     FileTypeChoices = new FilePickerFileType[]
                     {
-                        new FilePickerFileType($"{App.Current?.FindResource(p)}"){ Patterns = new []{"*.cfg" } }
+                        new FilePickerFileType($"{(p ==null ?"": App.Current?.FindResource(p) + "")}"){ Patterns = new []{"*.cfg" } }
                     }
                 });
                 if (folder != null)

+ 2 - 0
Avalonia/ShakerApp/ViewModels/InputPassWord/InputPassWordViewModel.cs

@@ -3,6 +3,7 @@ using Shaker.Model;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -46,6 +47,7 @@ namespace ShakerApp.ViewModels
                 SaveIsEnabled = !string.IsNullOrEmpty(PassWord);
             }
         }
+        [AllowNull]
         public Action<string> InputAction { get; set; }
     }
 }

+ 2 - 0
Avalonia/ShakerApp/ViewModels/MainPage/MainPageViewModel.cs

@@ -4,6 +4,7 @@ using Shaker.Models;
 using ShakerApp.Views;
 using System;
 using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
 using System.Text;
@@ -58,6 +59,7 @@ namespace ShakerApp.ViewModels
                 MainPage = MainPageViewModels.First(x => x.PageType == value);
             }
         }
+        [AllowNull]
         public IMainPageViewModel MainPage { get; private set; }
         public static MainPageViewModel Instance { get; } = new MainPageViewModel();
     }

+ 4 - 1
Avalonia/ShakerApp/ViewModels/MainPage/OutSignalMainPageViewModel.cs

@@ -7,6 +7,8 @@ using ShakerApp.Tools;
 using ShakerApp.Views;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
@@ -17,7 +19,8 @@ namespace ShakerApp.ViewModels
     {
         public MainPageType PageType => MainPageType.OutSignal;
 
-        private TimeDomainMenuViewModel selectedType;
+        [AllowNull]
+        private  TimeDomainMenuViewModel selectedType;
 
         private OutSignalMainPageViewModel()
         {

+ 1 - 0
Avalonia/ShakerApp/ViewModels/MainPage/SineMainPageViewModel.cs

@@ -185,6 +185,7 @@ namespace ShakerApp.ViewModels
         public float CurrentFrequency { get => Model.CurrentFrequency; set => SetProperty(ref Model.CurrentFrequency, value); }
         public float CurrentAcceleration { get => Model.CurrentAcceleration; set => SetProperty(ref Model.CurrentAcceleration, value); }
         public SweepDirection SweepDirection { get => Model.SweepDirection; set => SetProperty(ref Model.SweepDirection, value); }
+        public uint SweepIndex { get => Model.SweepIndex; set => SetProperty(ref Model.SweepIndex, value); }
         public MainPageType PageType => Model.MainPageType;
 
         public OxyPlot.PlotModel PlotModel { get; private set; } = new OxyPlot.PlotModel();

+ 18 - 2
Avalonia/ShakerApp/ViewModels/MainViewModel.cs

@@ -2,6 +2,7 @@
 using Avalonia.Collections;
 using Avalonia.Controls;
 using Avalonia.Controls.ApplicationLifetimes;
+using Avalonia.Controls.Documents;
 using Avalonia.Threading;
 using CommunityToolkit.Mvvm.Input;
 using FxpConvert.Common;
@@ -13,6 +14,7 @@ using SukiUI.Dialogs;
 using SukiUI.Toasts;
 using System;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using System.Windows.Input;
 
 namespace ShakerApp.ViewModels;
@@ -20,7 +22,7 @@ namespace ShakerApp.ViewModels;
 public class MainViewModel : ViewModelBase<IModel>
 {
     public ICalc Calc { get; } = new SIMDFxpConvert.SIMDCalc();
-    private AvaloniaDictionary<string, Window> OpenedWindows = new AvaloniaDictionary<string, Window>();
+    private AvaloniaDictionary<string, Window?> OpenedWindows = new AvaloniaDictionary<string, Window?>();
     private bool canDebug = false;
 
     private MainViewModel()
@@ -205,7 +207,7 @@ public class MainViewModel : ViewModelBase<IModel>
                 window?.Close();
                 if(pass != "123456")
                 {
-                    Dialogs.Info(App.Current?.FindResource("PassWordError")+"");
+                    ToastManager.CreateSimpleInfoToast().WithTitle(App.Current?.FindResource("PromptTitle")+"").WithContent(App.Current?.FindResource("PassWordError") + "").Queue();
                     return;
                 }
                 ShowDebug(p);
@@ -290,5 +292,19 @@ public class MainViewModel : ViewModelBase<IModel>
         };
         window.Show();
     }
+    public void SyncConfig()
+    {
+       var config= CommunicationViewModel.Intance.LocalCommunication.GetEvent<Shaker.Model.AllConfig>(Shaker.Model.Topic.SYNCCONFIG).Publish(this);
+        if(config ==null)
+        {
+            base.ToastManager.CreateSimpleInfoToast()
+                .WithTitle(App.Current?.FindResource("PromptTitle") + "")
+                .WithContent(App.Current?.FindResource("GetConfigError")+"")
+                .Queue();
+            CommunicationViewModel.Intance.LocalCommunication.Close();
+            return;
+        }
+        GetEvent<AllConfig>().Publish(this, config);
+    }
     public static MainViewModel Default { get; } = new MainViewModel();
 }

+ 12 - 3
Avalonia/ShakerApp/ViewModels/Oil/OilSourceStatusViewModel.cs

@@ -10,6 +10,7 @@ namespace ShakerApp.ViewModels
 {
     public class OilSourceStatusViewModel : ViewModelBase<OilSourceStatusModel>
     {
+        public LevelLogic LevelLogic => Model.LevelLogic;
         public override double Width => 1300;
         public override double Height => 800;
         public override bool CanResize => false;
@@ -32,10 +33,18 @@ namespace ShakerApp.ViewModels
             }
             Forerunner.UpDateModel(Model.Forerunner);
             Assistant?.UpDateModel(Model.Assistant);
-            CommunicationViewModel.Intance.LocalCommunication?.GetEvent<OilSourceStatusModel>()?.Subscrip((sender, args) =>
+            GetEvent<AllConfig>().Subscrip((sender, args) =>
             {
-                UpDateModel(args.Data);
-                CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<OilSourceStatusModel>()?.Publish(this, args.Data);
+                UpDateModel(args.Data.OilSource);
+                if(CommunicationViewModel.Intance.ServiceIsStart)
+                {
+                    CommunicationViewModel.Intance.ServiceCommunication.GetEvent<OilSourceStatusModel>().Publish(this, args.Data.OilSource);
+                }
+                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<OilSourceStatusModel>()?.Subscrip((sender, args) =>
+                {
+                    UpDateModel(args.Data);
+                    CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<OilSourceStatusModel>()?.Publish(this, args.Data);
+                });
             });
         }
         static OilSourceStatusViewModel()

+ 4 - 3
Avalonia/ShakerApp/ViewModels/Setting/ShakerSettingViewModel.cs

@@ -88,7 +88,7 @@ namespace ShakerApp.ViewModels
             {
                 var folder = await TopLevel.GetTopLevel(desktop.MainWindow)!.StorageProvider.OpenFolderPickerAsync(new Avalonia.Platform.Storage.FolderPickerOpenOptions()
                 {
-                    Title = App.Current?.FindResource(p) + "",
+                    Title = p ==null ?"": App.Current?.FindResource(p) + "",
                     AllowMultiple = false,
                 });
                 if(folder!=null && folder.Count>0)
@@ -140,7 +140,7 @@ namespace ShakerApp.ViewModels
         {
             Content = typeof(Views.ShakerSettingView);
             Pages.AddRange(this.GetType().Assembly.GetTypes()
-                .Where(x => x.GetInterface(typeof(Views.ISettingPageView).FullName) != null && x.IsAnsiClass && !x.IsAbstract && x.GetCustomAttribute<SettingPageAttribute>()!=null)
+                .Where(x => x.GetInterface(typeof(Views.ISettingPageView).FullName!) != null && x.IsAnsiClass && !x.IsAbstract && x.GetCustomAttribute<SettingPageAttribute>()!=null)
                 .Select(x=>
                 {
                     var att = x.GetCustomAttribute<SettingPageAttribute>();
@@ -149,7 +149,7 @@ namespace ShakerApp.ViewModels
                 .OrderBy(x=>x.Index)
                 .Select(x=>x.x));
             var fileinfp = new FileInfo(ConfigPath);
-            if (!System.IO.Directory.Exists(fileinfp.DirectoryName)) Directory.CreateDirectory(fileinfp.DirectoryName);
+            if (!System.IO.Directory.Exists(fileinfp.DirectoryName)) Directory.CreateDirectory(fileinfp.DirectoryName!);
             var model = Tools.Tools.ReadConfig<Models.ShakerSettingModel>(ConfigPath);
             if (model == null)
             {
@@ -179,6 +179,7 @@ namespace ShakerApp.ViewModels
         }
         protected override void Save()
         {
+            base.Save();
             Tools.Tools.SaveConfig(Model, ConfigPath);
         }
         protected override bool SkipProperty(string? propertyName)

+ 21 - 12
Avalonia/ShakerApp/ViewModels/ShakerConfig/ShakerConfigViewModel.cs

@@ -26,7 +26,7 @@ namespace ShakerApp.ViewModels
         public float InitialLocation { get => Model.InitialLocation; set => SetProperty(ref Model.InitialLocation, value); }
         public uint SampleRate => Model.SampleRate;
         public uint FPGAClock => Model.FPGAClock;
-        public int ChannelCount => Model.AnalogSignalConfigs.Length;
+        public int ChannelCount => Model.AnalogSignalConfigs.Count;
         public float MaxFrequency { get => Model.MaxFrequency; set => SetProperty(ref Model.MaxFrequency, value); }
         public float MinFrequency { get => Model.MinFrequency; set => SetProperty(ref Model.MinFrequency, value); }
 
@@ -37,20 +37,15 @@ namespace ShakerApp.ViewModels
         public float MaxJitterAcceleration { get => Model.MaxJitterAcceleration; set => SetProperty(ref Model.MaxJitterAcceleration, value); }
         public float MaxJitterDisplacement { get => Model.MaxJitterDisplacement; set => SetProperty(ref Model.MaxJitterDisplacement, value); }
         public float MaxVelocity { get => Model.MaxVelocity; set => SetProperty(ref Model.MaxVelocity, value); }
-        public int AccelerationSensorCount => Model.AccelerationConfigs.Length;
+        public int AccelerationSensorCount => Model.AccelerationConfigs.Count;
         public AvaloniaList<IndexValueItemViewModel<AnalogSignalConfigViewModel>> AnalogSignals { get; } = new AvaloniaList<IndexValueItemViewModel<AnalogSignalConfigViewModel>>();
         public AvaloniaList<IndexValueItemViewModel<AccelerationConfigViewModel>> Accelerations { get; } = new AvaloniaList<IndexValueItemViewModel<AccelerationConfigViewModel>>();
         public float DisplacementSensitivity { get => Model.DisplacementSensitivity; set => SetProperty(ref Model.DisplacementSensitivity, value); }
         private ShakerConfigViewModel()
         {
-            CommunicationViewModel.Intance.LocalCommunication?.GetEvent<Shaker.Models.ShakerConfigModel>()?.Subscrip((sender, args) =>
-            {
-                if (args.Data == null) return;
-                UpDateModel(args.Data);
-                CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<Shaker.Models.ShakerConfigModel>()?.Publish(this, args.Data);
-            });
+            
             Content = typeof(Views.ShakerConfigView);
-            for(int i=0;i<Model.AccelerationConfigs.Length;i++)
+            for(int i=0;i<Model.AccelerationConfigs.Count;i++)
             {
                 Accelerations.Add(new IndexValueItemViewModel<AccelerationConfigViewModel>(i + 1,new AccelerationConfigViewModel(Model.AccelerationConfigs[i])));
                 Accelerations[^1].Value.PropertyChanged += (sender, args) =>
@@ -58,10 +53,24 @@ namespace ShakerApp.ViewModels
                     SaveIsEnabled = true;
                 };
             }
-            for(int i=0;i<Model.AnalogSignalConfigs.Length;i++)
+            for(int i=0;i<Model.AnalogSignalConfigs.Count;i++)
             {
                 AnalogSignals.Add(new IndexValueItemViewModel<AnalogSignalConfigViewModel>(i + 1, new AnalogSignalConfigViewModel(Model.AnalogSignalConfigs[i])));
             }
+            GetEvent<AllConfig>().Subscrip((sender, args) =>
+            {
+                UpDateModel(args.Data.ShakerConfig);
+                if(CommunicationViewModel.Intance.ServiceIsStart)
+                {
+                    CommunicationViewModel.Intance.ServiceCommunication.GetEvent<Shaker.Models.ShakerConfigModel>().Publish(this, args.Data.ShakerConfig);
+                }
+                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<Shaker.Models.ShakerConfigModel>()?.Subscrip((sender, args) =>
+                {
+                    if (args.Data == null) return;
+                    UpDateModel(args.Data);
+                    CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<Shaker.Models.ShakerConfigModel>()?.Publish(this, args.Data);
+                });
+            });
         }
         static ShakerConfigViewModel()
         {
@@ -71,7 +80,7 @@ namespace ShakerApp.ViewModels
         {
             base.UpDateModel(model);
             Accelerations.Clear();
-            for(int i=0;i<model.AccelerationConfigs.Length;i++)
+            for(int i=0;i<model.AccelerationConfigs.Count;i++)
             {
                 Accelerations.Add(new IndexValueItemViewModel<AccelerationConfigViewModel>(i + 1, new AccelerationConfigViewModel(model.AccelerationConfigs[i])));
                 Accelerations[^1].Value.PropertyChanged += (sender, args) =>
@@ -80,7 +89,7 @@ namespace ShakerApp.ViewModels
                 };
             }
             AnalogSignals.Clear();
-            for(int i=0;i<model.AnalogSignalConfigs.Length;i++)
+            for(int i=0;i<model.AnalogSignalConfigs.Count;i++)
             {
                 AnalogSignals.Add(new IndexValueItemViewModel<AnalogSignalConfigViewModel>(i + 1, new AnalogSignalConfigViewModel(model.AnalogSignalConfigs[i])));
             }

+ 13 - 5
Avalonia/ShakerApp/ViewModels/ShakerConfig/SweepConfigViewModel.cs

@@ -175,12 +175,20 @@ namespace ShakerApp.ViewModels
                 displacement.Title = App.Current?.FindResource(ShakerConstant.DisplacementKey) + "";
                 DisplacementModel.InvalidatePlot(true);
             });
-            CommunicationViewModel.Intance.LocalCommunication?.GetEvent<SweepConfigModel>()?.Subscrip((sender, args) =>
+            GetEvent<AllConfig>().Subscrip((sender, args) =>
             {
-                UpDateModel(args.Data);
-                Refresh();
-                SineMainPageViewModel.Instance.SetRefSpectrum(datas);
-                CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<SweepConfigModel>()?.Publish(this, Model);
+                UpDateModel(args.Data.SweepConfig);
+                if(CommunicationViewModel.Intance.ServiceIsStart)
+                {
+                    CommunicationViewModel.Intance.ServiceCommunication.GetEvent<SweepConfigModel>().Publish(this, args.Data.SweepConfig);
+                }
+                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<SweepConfigModel>()?.Subscrip((sender, args) =>
+                {
+                    UpDateModel(args.Data);
+                    Refresh();
+                    SineMainPageViewModel.Instance.SetRefSpectrum(datas);
+                    CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<SweepConfigModel>()?.Publish(this, Model);
+                });
             });
         }
         static SweepConfigViewModel()

+ 22 - 50
Avalonia/ShakerApp/ViewModels/ShakerControl/ShakerControlViewModel.cs

@@ -1,4 +1,5 @@
 using Shaker.Model;
+using Shaker.Models;
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
@@ -23,8 +24,7 @@ namespace ShakerApp.ViewModels
         {
             for (int i = 0; i < ServoValveCount; i++)
             {
-                ServoValveBias.Add(new IndexValueItemViewModel<float>(i + 1, 0));
-                OpenLoopDisplacement.Add(new IndexValueItemViewModel<float>(i + 1, 0));
+                ValveConfig.Add(new IndexValueItemViewModel<ValveConfigItemViewModel>(i + 1, new ValveConfigItemViewModel(Model.ValveConfig[i])));
             }
             ControlItems.CollectionChanged += (sender, args) =>
             {
@@ -38,59 +38,32 @@ namespace ShakerApp.ViewModels
                 }
                 Model.ControlItems = ControlItems.Select(x => x.Value.Model).ToList();
             };
-            ServoValveBias.CollectionChanged += (_, _) =>
+            ValveConfig.CollectionChanged += (_, _) =>
             {
-                Model.ServoValveBias = ServoValveBias.Select(x => x.Value).ToArray();
+                Model.ValveConfig = ValveConfig.Select(x => x.Value.Model).ToList();
             };
-            OpenLoopDisplacement.CollectionChanged += (_, _) =>
+            GetEvent<AllConfig>().Subscrip((sender, args) =>
             {
-                Model.OpenLoopDisplacement = OpenLoopDisplacement.Select(x => x.Value).ToArray();
-            };
-            CommunicationViewModel.Intance.LocalCommunication?.GetEvent<ShakerControlModel>()?.Subscrip((sender, args) =>
-            {
-                UpDateModel(args.Data);
-                CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<ShakerControlModel>()?.Publish(this, args.Data);
+                UpDateModel(args.Data.ShakerControl);
+                if(CommunicationViewModel.Intance.ServiceIsStart)
+                {
+                    CommunicationViewModel.Intance.ServiceCommunication.GetEvent<ShakerControlModel>().Publish(this, args.Data.ShakerControl);
+                }
+                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<ShakerControlModel>()?.Subscrip((sender, args) =>
+                {
+                    UpDateModel(args.Data);
+                    CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<ShakerControlModel>()?.Publish(this, args.Data);
+                });
             });
         }
         public override void UpDateModel(ShakerControlModel model)
         {
             base.UpDateModel(model);
-            var bias = model.ServoValveBias;
-            var disp = model.OpenLoopDisplacement;
-            int count = ServoValveBias.Count;
-            if (count > ServoValveCount)
-            {
-                for (int i = 0; i < count - ServoValveCount; i++)
-                {
-                    ServoValveBias.RemoveAt(ServoValveBias.Count - 1);
-                }
-            }
-            else if (count < ServoValveCount)
-            {
-                for (int i = 0; i < ServoValveCount - count; i++)
-                {
-                    ServoValveBias.Add(new IndexValueItemViewModel<float>(i + 1, 0));
-                }
-            }
-            count = OpenLoopDisplacement.Count;
-            if (count > ServoValveCount)
-            {
-                for (int i = 0; i < count - ServoValveCount; i++)
-                {
-                    OpenLoopDisplacement.RemoveAt(OpenLoopDisplacement.Count - 1);
-                }
-            }
-            else if (count < ServoValveCount)
-            {
-                for (int i = 0; i < ServoValveCount - count; i++)
-                {
-                    OpenLoopDisplacement.Add(new IndexValueItemViewModel<float>(i + 1, 0));
-                }
-            }
-            for (int i = 0; i < ServoValveCount; i++)
+
+            ValveConfig.Clear();
+            for(int i=0;i<model.ValveConfig.Count;i++)
             {
-                ServoValveBias[i].Value = bias[i];
-                OpenLoopDisplacement[i].Value = disp[i];
+                ValveConfig.Add(new IndexValueItemViewModel<ValveConfigItemViewModel>(i + 1, new ValveConfigItemViewModel(model.ValveConfig[i])));
             }
             if (model.ControlItems == null)
             {
@@ -106,27 +79,26 @@ namespace ShakerApp.ViewModels
                 }
             }
         }
+        public MainPageType PageType { get => Model.PageType; set => SetProperty(ref Model.PageType, value); }
         public int MaxControlItemCount => Model.MaxControlItemCount;
         public float MaxDisplacementVoltage => Model.MaxDisplacementVoltage;
         public float MinDisplacementVoltage => Model.MinDisplacementVoltage;
         public float MaxValveVoltage => Model.MaxValveVoltage;
         public float MinValveVoltage => Model.MinValveVoltage;
         public Polarity ValvePolarity { get => Model.ValvePolarity; set => SetProperty(ref Model.ValvePolarity, value); }
-        public Polarity AccelerationPolarity { get => Model.AccelerationPolarity; set => SetProperty(ref Model.AccelerationPolarity, value); }
         public bool SelfLoop { get => Model.SelfLoop; set => SetProperty(ref Model.SelfLoop, value); }
         public bool Debug { get => Model.Debug; set => SetProperty(ref Model.SelfLoop, value); }
         public float DisplacementP { get => Model.DisplacementP; set => SetProperty(ref Model.DisplacementP, value); }
         public float DisplacementI { get => Model.DisplacementI; set => SetProperty(ref Model.DisplacementI, value); }
         public float FlutterFrequency { get => Model.FlutterFrequency; set => SetProperty(ref Model.FlutterFrequency, value); }
         public float FlutterAmpt { get => Model.FlutterAmpt; set => SetProperty(ref Model.FlutterAmpt, value); }
-        public int ServoValveCount => ShakerControlModel.ServoValveCount;
+        public int ServoValveCount => Model.ValveConfig.Count;
         public float MaxDisplacementIntegral { get => Model.MaxDisplacementIntegral; set => SetProperty(ref Model.MaxDisplacementIntegral, value); }
         public float DisplacementBias { get => Model.DisplacementBias; set => SetProperty(ref Model.DisplacementBias, value); }
-        public ObservableCollection<IndexValueItemViewModel<float>> ServoValveBias { get; } = new ObservableCollection<IndexValueItemViewModel<float>>();
+        public ObservableCollection<IndexValueItemViewModel<ValveConfigItemViewModel>> ValveConfig { get; } = new ObservableCollection<IndexValueItemViewModel<ValveConfigItemViewModel>>();
         public bool OilStopped { get => Model.OilStopped; set => SetProperty(ref Model.OilStopped, value); }
         public bool DisplacementOpenLoop { get => Model.DisplacementOpenLoop; set => SetProperty(ref Model.DisplacementOpenLoop, value); }
         public ObservableCollection<IndexValueItemViewModel<SweepControlItemViewModel>> ControlItems { get; } = new ObservableCollection<IndexValueItemViewModel<SweepControlItemViewModel>>();
-        public ObservableCollection<IndexValueItemViewModel<float>> OpenLoopDisplacement { get; } = new ObservableCollection<IndexValueItemViewModel<float>>();
         public bool OutSignal { get => Model.OutSignal; set => SetProperty(ref Model.OutSignal, value); }
         public bool AddEnabled => ControlItems.Count < SweepFreqConfigModel.MAXITEM;
         public bool RemoveEnabled => ControlItems.Count > 0;

+ 18 - 0
Avalonia/ShakerApp/ViewModels/ShakerControl/ValveConfigItemViewModel.cs

@@ -0,0 +1,18 @@
+using Shaker.Model;
+
+namespace ShakerApp.ViewModels
+{
+    public class ValveConfigItemViewModel:ViewModelBase<ValveConfigItemModel>
+    {
+        public ValveConfigItemViewModel():base()
+        {
+
+        }
+        public ValveConfigItemViewModel(ValveConfigItemModel model):base(model)
+        {
+
+        }
+        public float Bias { get => Model.Bias; set => SetProperty(ref Model.Bias, value); }
+        public float OpenLoopDrive { get => Model.OpenLoopDrive; set => SetProperty(ref Model.OpenLoopDrive, value); }
+    }
+}

+ 0 - 16
Avalonia/ShakerApp/ViewModels/ShakerSensitivityViewModel.cs

@@ -1,16 +0,0 @@
-using Shaker.Model;
-using ShakerApp.ViewModels;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ShakerControl.ViewModels
-{
-    public class ShakerSensitivityViewModel:ViewModelBase<ShakerSensitivityModel>
-    {
-        public float Displacement { get => Model.Displacement; set => SetProperty(ref Model.Displacement, value); }
-        public float Acceleration { get => Model.Acceleration; set => SetProperty(ref Model.Acceleration, value); }
-    }
-}

+ 11 - 5
Avalonia/ShakerApp/ViewModels/ShakerStatus/ShakerStatusViewModel.cs

@@ -29,7 +29,6 @@ namespace ShakerApp.ViewModels
 
         public RTStatus RTStatus { get => Model.RTStatus; set => SetProperty(ref Model.RTStatus, value); }
         public bool Start { get => Model.Start; set => SetProperty(ref Model.Start, value); }
-        public float SynthesisAmplitude { get => Model.SynthesisAmplitude; set => SetProperty(ref Model.SynthesisAmplitude, value); }
         public bool IsTableRised { get => Model.IsTableRised; set => SetProperty(ref Model.IsTableRised, value); }
         public bool IsTableDroped { get => Model.IsTableDroped; set => SetProperty(ref Model.IsTableDroped, value); }
         public bool IsFaultRelease { get => Model.IsFaultRelease; set => SetProperty(ref Model.IsFaultRelease, value); }
@@ -45,7 +44,6 @@ namespace ShakerApp.ViewModels
         public ushort ErrorCode { get => Model.ErrorCode; set => SetProperty(ref Model.ErrorCode, value); }
 
 
-        public bool ValvePower { get => Model.ValvePower; set => SetProperty(ref Model.ValvePower, value); }
         public float WorkPosition { get => workPosition; set =>SetProperty(ref workPosition , value); }
         private ShakerStatusViewModel()
         {
@@ -63,10 +61,18 @@ namespace ShakerApp.ViewModels
                 ServoValveModel.Axes[1].Title = App.Current?.FindResource("Ampt") + "";
                 ServoValveModel.Title = App.Current?.FindResource("ValveDriveSignal") + "";
             });
-            CommunicationViewModel.Intance.LocalCommunication?.GetEvent<Shaker.Model.ShakerStatusModel>()?.Subscrip((sender, args) =>
+            GetEvent<AllConfig>().Subscrip((sender, args) =>
             {
-                UpDateModel(args.Data);
-                CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<Shaker.Model.ShakerStatusModel>()?.Publish(this, args.Data);
+                UpDateModel(args.Data.ShakerStatus);
+                if(CommunicationViewModel.Intance.ServiceIsStart)
+                {
+                    CommunicationViewModel.Intance.ServiceCommunication.GetEvent<ShakerStatusModel>().Publish(this, args.Data.ShakerStatus);
+                }
+                CommunicationViewModel.Intance.LocalCommunication?.GetEvent<Shaker.Model.ShakerStatusModel>()?.Subscrip((sender, args) =>
+                {
+                    UpDateModel(args.Data);
+                    CommunicationViewModel.Intance.ServiceCommunication?.GetEvent<Shaker.Model.ShakerStatusModel>()?.Publish(this, args.Data);
+                });
             });
         }
         private void InitDisplacementModel()

+ 4 - 2
Avalonia/ShakerApp/ViewModels/ViewModelBase.cs

@@ -18,6 +18,7 @@ public abstract class ViewModelBase<TModel> : ObservableObject where TModel : Sh
     public virtual double Width => double.NaN;
     public virtual double Height => double.NaN;
     public virtual bool CanResize => true;
+    [AllowNull]
     public Action CloseWindowAction { get; set; }
     public ISukiToastManager ToastManager { get; } = new SukiToastManager();
     public ISukiDialogManager DialogManager { get; } = new SukiDialogManager();
@@ -35,13 +36,13 @@ public abstract class ViewModelBase<TModel> : ObservableObject where TModel : Sh
         get { return saveIsEnabled; }
         set {SetProperty(ref saveIsEnabled , value); }
     }
-
+    [AllowNull]
     public DialogsViewModel Dialogs { get; }
     public virtual bool CanCancel { get; } = typeof(TModel).IsAnsiClass && !typeof(TModel).IsAbstract;
 
     public ViewModelBase()
     {
-        Dialogs = new DialogsViewModel(DialogManager, ToastManager);
+        Dialogs = new DialogsViewModel(DialogManager);
         if (typeof(TModel).IsAnsiClass && !typeof(TModel).IsAbstract)
         {
             Model = Activator.CreateInstance<TModel>();
@@ -111,6 +112,7 @@ public abstract class ViewModelBase<TModel> : ObservableObject where TModel : Sh
 
     [AllowNull]
     protected TModel lastModel;
+    [AllowNull]
     private Type content;
 
     public virtual void InitData()

+ 74 - 131
Avalonia/ShakerApp/Views/DebugView/DebugView.axaml

@@ -15,7 +15,7 @@
     <TabControl>
         <TabItem Header="{DynamicResource Displacement}">
             <suki:GlassCard HorizontalAlignment="Center" VerticalAlignment="Center">
-                <Grid Width="420" Height="240">
+                <Grid Width="420" Height="140">
                     <Grid.ColumnDefinitions>
                         <ColumnDefinition />
                         <ColumnDefinition />
@@ -23,18 +23,9 @@
                     <Grid.RowDefinitions>
                         <RowDefinition />
                         <RowDefinition />
-                        <RowDefinition />
                     </Grid.RowDefinitions>
                     <StackPanel
-                        Grid.ColumnSpan="2"
-                        HorizontalAlignment="Left"
-                        VerticalAlignment="Center"
-                        Orientation="Vertical">
-                        <TextBlock VerticalAlignment="Center" Text="{DynamicResource DisOpenLoop}" />
-                        <ToggleSwitch IsChecked="{Binding DisplacementOpenLoop}" />
-                    </StackPanel>
-                    <StackPanel
-                        Grid.Row="1"
+                        Grid.Row="0"
                         Grid.Column="0"
                         HorizontalAlignment="Left"
                         VerticalAlignment="Center"
@@ -46,7 +37,7 @@
                             Value="{Binding DisplacementP}" />
                     </StackPanel>
                     <StackPanel
-                        Grid.Row="1"
+                        Grid.Row="0"
                         Grid.Column="1"
                         HorizontalAlignment="Left"
                         VerticalAlignment="Center"
@@ -59,7 +50,7 @@
                     </StackPanel>
 
                     <StackPanel
-                        Grid.Row="2"
+                        Grid.Row="1"
                         Grid.Column="0"
                         HorizontalAlignment="Left"
                         VerticalAlignment="Center"
@@ -86,7 +77,16 @@
                         <RowDefinition Height="66" />
                         <RowDefinition Height="*" />
                     </Grid.RowDefinitions>
-                    <StackPanel Grid.ColumnSpan="2">
+
+                    <StackPanel
+                        Grid.Column="1"
+                        HorizontalAlignment="Left"
+                        VerticalAlignment="Center"
+                        Orientation="Vertical">
+                        <TextBlock VerticalAlignment="Center" Text="{DynamicResource DisOpenLoop}" />
+                        <ToggleSwitch IsChecked="{Binding DisplacementOpenLoop}" />
+                    </StackPanel>
+                    <StackPanel Grid.Column="0">
                         <TextBlock Text="{DynamicResource ServoValvePolarity}" />
                         <ComboBox
                             Width="120"
@@ -102,99 +102,67 @@
                             </ComboBox.ItemTemplate>
                         </ComboBox>
                     </StackPanel>
-                    <suki:GroupBox
-                        Grid.Row="1"
-                        Margin="0,0,10,0"
-                        Header="{DynamicResource ServoValveOffset}">
-                        <StackPanel Orientation="Vertical">
-                            <Grid Height="{StaticResource ItemHeight}" Background="LightGray">
-                                <Grid.ColumnDefinitions>
-                                    <ColumnDefinition Width="66" />
-                                    <ColumnDefinition Width="*" />
-                                </Grid.ColumnDefinitions>
-                                <TextBlock
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{DynamicResource ServoValveIndex}" />
-                                <TextBlock
-                                    Grid.Column="1"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{DynamicResource OffsetVoltage}" />
-                            </Grid>
-                            <ItemsControl ItemsSource="{Binding ServoValveBias}">
-                                <ItemsControl.ItemTemplate>
-                                    <DataTemplate>
-                                        <Grid Height="{StaticResource ItemHeight}" Margin="0,4,0,4">
-                                            <Grid.ColumnDefinitions>
-                                                <ColumnDefinition Width="66" />
-                                                <ColumnDefinition Width="*" />
-                                            </Grid.ColumnDefinitions>
-                                            <TextBlock
-                                                HorizontalAlignment="Center"
-                                                VerticalAlignment="Center"
-                                                Text="{Binding Index}" />
-                                            <NumericUpDown
-                                                Grid.Column="1"
-                                                Width="120"
-                                                HorizontalAlignment="Center"
-                                                VerticalAlignment="Center"
-                                                Value="{Binding Value}" />
-                                        </Grid>
-                                    </DataTemplate>
-                                </ItemsControl.ItemTemplate>
-                            </ItemsControl>
-                        </StackPanel>
-
-                    </suki:GroupBox>
-
-
-                    <suki:GroupBox
+                    <StackPanel
                         Grid.Row="1"
-                        Grid.Column="1"
+                        Grid.ColumnSpan="2"
                         Margin="0,0,10,0"
-                        Header="{DynamicResource OpenLoopVoltage}">
-                        <StackPanel Orientation="Vertical">
-                            <Grid Height="{StaticResource ItemHeight}" Background="LightGray">
-                                <Grid.ColumnDefinitions>
-                                    <ColumnDefinition Width="66" />
-                                    <ColumnDefinition Width="*" />
-                                </Grid.ColumnDefinitions>
-                                <TextBlock
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{DynamicResource ServoValveIndex}" />
-                                <TextBlock
-                                    Grid.Column="1"
-                                    HorizontalAlignment="Center"
-                                    VerticalAlignment="Center"
-                                    Text="{DynamicResource LoopVoltage}" />
-                            </Grid>
-                            <ItemsControl ItemsSource="{Binding ServoValveBias}">
-                                <ItemsControl.ItemTemplate>
-                                    <DataTemplate>
-                                        <Grid Height="{StaticResource ItemHeight}" Margin="0,4,0,4">
-                                            <Grid.ColumnDefinitions>
-                                                <ColumnDefinition Width="66" />
-                                                <ColumnDefinition Width="*" />
-                                            </Grid.ColumnDefinitions>
-                                            <TextBlock
-                                                HorizontalAlignment="Center"
-                                                VerticalAlignment="Center"
-                                                Text="{Binding Index}" />
-                                            <NumericUpDown
-                                                Grid.Column="1"
-                                                Width="120"
-                                                HorizontalAlignment="Center"
-                                                VerticalAlignment="Center"
-                                                Value="{Binding Value}" />
-                                        </Grid>
-                                    </DataTemplate>
-                                </ItemsControl.ItemTemplate>
-                            </ItemsControl>
-                        </StackPanel>
-
-                    </suki:GroupBox>
+                        Orientation="Vertical">
+                        <Grid Height="{StaticResource ItemHeight}" Background="LightGray">
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="66" />
+                                <ColumnDefinition Width="*" />
+                                <ColumnDefinition Width="*" />
+                            </Grid.ColumnDefinitions>
+                            <TextBlock
+                                HorizontalAlignment="Center"
+                                VerticalAlignment="Center"
+                                Text="{DynamicResource ServoValveIndex}" />
+                            <TextBlock
+                                Grid.Column="1"
+                                HorizontalAlignment="Center"
+                                VerticalAlignment="Center">
+                                <Run Text="{DynamicResource ServoValveOffset}" />
+                                <Run Text="(V)" />
+                            </TextBlock>
+                            <TextBlock
+                                Grid.Column="2"
+                                HorizontalAlignment="Center"
+                                VerticalAlignment="Center">
+                                <Run Text="{DynamicResource OpenLoopVoltage}" />
+                                <Run Text="(V)" />
+                            </TextBlock>
+                        </Grid>
+                        <ItemsControl ItemsSource="{Binding ValveConfig}">
+                            <ItemsControl.ItemTemplate>
+                                <DataTemplate>
+                                    <Grid Height="{StaticResource ItemHeight}" Margin="0,4,0,4">
+                                        <Grid.ColumnDefinitions>
+                                            <ColumnDefinition Width="66" />
+                                            <ColumnDefinition Width="*" />
+                                            <ColumnDefinition Width="*" />
+                                        </Grid.ColumnDefinitions>
+                                        <TextBlock
+                                            HorizontalAlignment="Center"
+                                            VerticalAlignment="Center"
+                                            Text="{Binding Index}" />
+                                        <NumericUpDown
+                                            Grid.Column="1"
+                                            Width="120"
+                                            HorizontalAlignment="Center"
+                                            VerticalAlignment="Center"
+                                            Value="{Binding Value.Bias}" />
+                                        <NumericUpDown
+                                            Grid.Column="2"
+                                            Width="120"
+                                            HorizontalAlignment="Center"
+                                            VerticalAlignment="Center"
+                                            IsEnabled="{Binding $parent[ItemsControl].DataContext.DisplacementOpenLoop}"
+                                            Value="{Binding Value.OpenLoopDrive}" />
+                                    </Grid>
+                                </DataTemplate>
+                            </ItemsControl.ItemTemplate>
+                        </ItemsControl>
+                    </StackPanel>
                 </Grid>
             </suki:GlassCard>
         </TabItem>
@@ -209,31 +177,6 @@
                     <RowDefinition />
                     <RowDefinition />
                 </Grid.RowDefinitions>
-                <suki:GlassCard
-                    Width="280"
-                    Height="160"
-                    VerticalAlignment="Top">
-                    <suki:GroupBox Header="{DynamicResource Acceleration}">
-                        <StackPanel VerticalAlignment="Top" Orientation="Horizontal">
-                            <TextBlock
-                                HorizontalAlignment="Center"
-                                VerticalAlignment="Center"
-                                Text="{DynamicResource AccelerationPolarity}" />
-                            <ComboBox
-                                Width="120"
-                                Height="{StaticResource ItemHeight}"
-                                ItemsSource="{Binding AccelerationPolarity, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}"
-                                SelectedValue="{Binding Path=AccelerationPolarity}"
-                                SelectedValueBinding="{Binding Value}">
-                                <ComboBox.ItemTemplate>
-                                    <DataTemplate>
-                                        <TextBlock Text="{local:ResourceBinding Key}" />
-                                    </DataTemplate>
-                                </ComboBox.ItemTemplate>
-                            </ComboBox>
-                        </StackPanel>
-                    </suki:GroupBox>
-                </suki:GlassCard>
                 <suki:GlassCard
                     Grid.Column="1"
                     Width="280"
@@ -251,7 +194,7 @@
                 </suki:GlassCard>
 
                 <suki:GlassCard
-                    Grid.Row="1"
+                    Grid.Row="0"
                     Width="280"
                     Height="180"
                     VerticalAlignment="Top">

+ 27 - 9
Avalonia/ShakerApp/Views/MainWindow.axaml

@@ -13,12 +13,12 @@
     Title="{Binding Title}"
     d:DesignHeight="450"
     d:DesignWidth="800"
-    FontFamily="{StaticResource AlibabaPuHuiTi}"
-    FontStyle="Normal"
-    FontWeight="Medium"
     x:DataType="vm:MainViewModel"
     ClosingBehavior="OwnerAndChildWindows"
     DataContext="{Binding Source={x:Static vm:MainViewModel.Default}}"
+    FontFamily="{StaticResource AlibabaPuHuiTi}"
+    FontStyle="Normal"
+    FontWeight="Medium"
     IsMenuVisible="True"
     mc:Ignorable="d">
     <Interaction.Behaviors>
@@ -70,36 +70,54 @@
                 Command="{Binding DeviceMangerCommand}"
                 CommandParameter="MenuManger"
                 Header="{DynamicResource MenuManger}"
+                IsEnabled="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=!LocalIsConnect}"
                 IsVisible="{Binding Source={x:Static vm:ShakerSettingViewModel.Instance}, Path=WorkingMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static model:WorkingMode.Local}}" />
             <MenuItem
                 CommandParameter="MenuConnect"
                 Header="{DynamicResource MenuConnect}"
+                IsEnabled="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=!LocalIsConnect}"
                 IsVisible="{Binding Source={x:Static vm:ShakerSettingViewModel.Instance}, Path=WorkingMode, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static model:WorkingMode.Remote}}" />
-            <MenuItem Header="{DynamicResource MenuDisConnect}" />
+            <MenuItem Header="{DynamicResource MenuDisConnect}" IsEnabled="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=LocalIsConnect}" />
 
             <MenuItem
                 Command="{Binding ShakerConfigCommand}"
                 CommandParameter="MenuDeviceConfig"
-                Header="{DynamicResource MenuDeviceConfig}" />
+                Header="{DynamicResource MenuDeviceConfig}"
+                IsEnabled="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=LocalIsConnect}" />
             <Separator />
             <MenuItem
                 Command="{Binding ShakerControlCommand}"
                 CommandParameter="MenuShakerControl"
-                Header="{DynamicResource MenuShakerControl}" />
+                Header="{DynamicResource MenuShakerControl}"
+                IsEnabled="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=LocalIsConnect}" />
             <Separator />
             <MenuItem
+                Classes.Connected="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=LocalIsConnect}"
+                Classes.OilEnabled="{Binding Source={x:Static vm:OilSourceStatusViewModel.Instance}, Path=IsEnabled}"
                 Command="{Binding OilControlCommand}"
                 CommandParameter="OilSourceControl"
-                Header="{DynamicResource OilSourceControl}"
-                IsEnabled="{Binding Source={x:Static vm:OilSourceStatusViewModel.Instance}, Path=IsEnabled}" />
+                Header="{DynamicResource OilSourceControl}">
+                <MenuItem.Styles>
+                    <Style Selector="MenuItem">
+                        <Setter Property="IsEnabled" Value="False" />
+                    </Style>
+                    <Style Selector="MenuItem.OilEnabled">
+                        <Setter Property="IsEnabled" Value="True" />
+                    </Style>
+                    <Style Selector="MenuItem.Connected">
+                        <Setter Property="IsEnabled" Value="True" />
+                    </Style>
+                </MenuItem.Styles>
+            </MenuItem>
             <Separator IsVisible="{Binding CanDebug}" />
             <MenuItem
                 Command="{Binding DebugCommand}"
                 CommandParameter="MenuDebug"
                 Header="{DynamicResource MenuDebug}"
+                IsEnabled="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=LocalIsConnect}"
                 IsVisible="{Binding CanDebug}" />
         </MenuItem>
-        <MenuItem Header="{DynamicResource MenuTest}">
+        <MenuItem Header="{DynamicResource MenuTest}" IsEnabled="{Binding Source={x:Static vm:CommunicationViewModel.Intance}, Path=LocalIsConnect}">
             <MenuItem.Styles>
                 <Style Selector="MenuItem.Selected">
                     <Setter Property="Icon">

+ 20 - 2
Avalonia/ShakerApp/Views/ShakerConfig/ShakerConfigView.axaml

@@ -4,6 +4,7 @@
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
     xmlns:local="clr-namespace:ShakerApp.Views"
+    xmlns:main="using:ShakerApp"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
     xmlns:suki="https://github.com/kikipoulet/SukiUI"
     xmlns:vm="clr-namespace:ShakerApp.ViewModels"
@@ -126,6 +127,7 @@
                                 <Grid.ColumnDefinitions>
                                     <ColumnDefinition Width="30" />
                                     <ColumnDefinition Width="*" />
+                                    <ColumnDefinition Width="*" />
                                 </Grid.ColumnDefinitions>
                                 <TextBlock
                                     HorizontalAlignment="Center"
@@ -139,11 +141,16 @@
                                     <Run Text="{DynamicResource Sensitivity}" />
                                     <Run Text="(mv/g)" />
                                 </TextBlock>
+                                <TextBlock
+                                    Grid.Column="2"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    Text="{DynamicResource AccelerationPolarity}" />
                             </Grid>
                             <ItemsControl
                                 VerticalAlignment="Top"
                                 Background="Transparent"
-                                ItemsSource="{Binding AccelerationsSensitivity}"
+                                ItemsSource="{Binding Accelerations}"
                                 TabIndex="0">
                                 <ItemsControl.ItemTemplate>
                                     <DataTemplate>
@@ -151,6 +158,7 @@
                                             <Grid.ColumnDefinitions>
                                                 <ColumnDefinition Width="30" />
                                                 <ColumnDefinition Width="*" />
+                                                <ColumnDefinition Width="*" />
                                             </Grid.ColumnDefinitions>
                                             <TextBlock
                                                 HorizontalAlignment="Center"
@@ -164,7 +172,17 @@
                                                 VerticalAlignment="Center"
                                                 Increment="0.001"
                                                 Minimum="0.001"
-                                                Value="{Binding Value}" />
+                                                Value="{Binding Value.Sensitivity}" />
+                                            <ComboBox
+                                                ItemsSource="{Binding Value.Polarity, Converter={StaticResource EnumToCollectionConverter}, Mode=OneTime}"
+                                                SelectedValue="{Binding Path=Value.Polarity}"
+                                                SelectedValueBinding="{Binding Value}">
+                                                <ComboBox.ItemTemplate>
+                                                    <DataTemplate>
+                                                        <TextBlock Text="{main:ResourceBinding Key}" />
+                                                    </DataTemplate>
+                                                </ComboBox.ItemTemplate>
+                                            </ComboBox>
                                         </Grid>
                                     </DataTemplate>
                                 </ItemsControl.ItemTemplate>

+ 3 - 3
Avalonia/ShakerApp/Views/TimeControl.axaml.cs

@@ -20,9 +20,9 @@ public partial class TimeControl : UserControl
             float time = val;
             if (control.changed) return val;
             control.changed = true;
-            control.SetValue(HourProperty, (uint)time / 3600);
-            control.SetValue(MinuteProperty, (byte)((uint)time / 60 % 60));
-            control.SetValue(SecondProperty, MathF.Floor((time - (control.Hour * 3600 + control.Minute * 60)) / control.Increment) * control.Increment);
+            control.SetValue(HourProperty!, (uint)time / 3600);
+            control.SetValue(MinuteProperty!, (byte)((uint)time / 60 % 60));
+            control.SetValue(SecondProperty!, MathF.Floor((time - (control.Hour * 3600 + control.Minute * 60)) / control.Increment) * control.Increment);
             control.changed = false;
         }
         return val;

+ 1 - 1
Communication/TcpEventBus/MsgTool.cs

@@ -69,7 +69,7 @@ namespace TcpEventBus
         }
         public static object[] GetAnonyDatas(byte[] data)
         {
-            if (data == null) return new object[0];
+            if (data == null || data.Length ==0) return new object[0];
             object[] d = new object[Unsafe.As<byte, int>(ref data[0])];
             int start = 4;
             for(int i=0;i<d.Length;i++)

+ 1 - 1
Communication/TcpEventBus/TcpEventBus.cs

@@ -31,7 +31,7 @@ namespace TcpEventBus
             tcp.Events.Connected += (sender, args) => Connected?.Invoke(sender, args);
             tcp.Events.Disconnected += (sender, args) =>
             {
-                _list.Clear();
+                //_list.Clear();
                 Disconnected?.Invoke(sender, args);
             };
         }

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

@@ -87,6 +87,7 @@
     <s:String x:Key="Confirm">确认</s:String>
     <s:String x:Key="Save">保存</s:String>
     <s:String x:Key="Cancel">取消</s:String>
+    <s:String x:Key="GetConfigError">获取参数失败</s:String>
     <s:String x:Key="PromptExitMsg">是否退出程序?</s:String>
     <s:String x:Key="DeviceName">设备名</s:String>
     <s:String x:Key="DeviceSN">序列号</s:String>

+ 272 - 30
NIFPGA/FPGA.cs

@@ -168,88 +168,330 @@ namespace NIFPGA
                 switch (reg.Datatype)
                 {
                     case lvbitx.Datatype.Int16:
-                        properties.Add(new FPGAProperty<short>(session, reg.Offset, reg.Indicator)
+                        if(!reg.Indicator)
                         {
-                            Name= reg.Name,
-                        });
+
+                            properties.Add(new FPGAWriteProperty<short>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<short>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Boolean:
-                        properties.Add(new FPGAProperty<bool>(session, reg.Offset, reg.Indicator)
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<bool>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
                         {
-                            Name = reg.Name,
-                        });
+                            properties.Add(new FPGAReadProperty<bool>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Int8:
-                        properties.Add(new FPGAProperty<sbyte>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<sbyte>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<sbyte>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Uint8:
-                        properties.Add(new FPGAProperty<byte>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<byte>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<byte>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Uint16:
-                        properties.Add(new FPGAProperty<ushort>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<ushort>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<ushort>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Int32:
-                        properties.Add(new FPGAProperty<int>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<int>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<int>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Uint32:
-                        properties.Add(new FPGAProperty<uint>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<uint>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<uint>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Int64:
-                        properties.Add(new FPGAProperty<long>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<long>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<long>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Uint64:
-                        properties.Add(new FPGAProperty<ulong>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<ulong>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<ulong>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Float:
-                        properties.Add(new FPGAProperty<float>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<float>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<float>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Double:
-                        properties.Add(new FPGAProperty<double>(session, reg.Offset, reg.Indicator) { Name = reg.Name });
+                        if (!reg.Indicator)
+                        {
+
+                            properties.Add(new FPGAWriteProperty<double>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
+                        {
+                            properties.Add(new FPGAReadProperty<double>(session, reg.Offset)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.FXP:
-                        properties.Add(new FPGAFXPProperty(session, reg.Offset, reg.FxpTypeInfo,_FXPConvert, reg.Indicator)
+                        if (!reg.Indicator)
+                        {
+                            properties.Add(new FPGAFXPWriteProperty(session, reg.Offset, reg.FxpTypeInfo, _FXPConvert)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
+                        else
                         {
-                            Name = reg.Name,
-                        });
+                            properties.Add(new FPGAFXPReadProperty(session, reg.Offset, reg.FxpTypeInfo, _FXPConvert)
+                            {
+                                Name = reg.Name,
+                            });
+                        }
                         break;
                     case lvbitx.Datatype.Array:
                         switch (reg.ArrayValueType)
                         {
                             case lvbitx.Datatype.Boolean:
-                                properties.Add(new FPGAArrayProperty<bool>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if(!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<bool>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<bool>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Int8:
-                                properties.Add(new FPGAArrayProperty<sbyte>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<sbyte>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<sbyte>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Uint8:
-                                properties.Add(new FPGAArrayProperty<byte>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<byte>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<byte>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Int16:
-                                properties.Add(new FPGAArrayProperty<short>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<short>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<short>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Uint16:
-                                properties.Add(new FPGAArrayProperty<short>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<ushort>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<ushort>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Int32:
-                                properties.Add(new FPGAArrayProperty<int>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<int>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<int>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Uint32:
-                                properties.Add(new FPGAArrayProperty<uint>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<uint>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<uint>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Int64:
-                                properties.Add(new FPGAArrayProperty<long>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<long>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<long>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Uint64:
-                                properties.Add(new FPGAArrayProperty<ulong>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<ulong>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<ulong>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Float:
-                                properties.Add(new FPGAArrayProperty<float>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<float>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<float>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Double:
-                                properties.Add(new FPGAArrayProperty<double>(session, reg.Offset, reg.Size, reg.Indicator) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayWriteProperty<double>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayReadProperty<double>(session, reg.Offset, reg.Size) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.FXP:
-                                properties.Add(new FPGAArrayFXPProperty(session, reg.Offset, reg.Size, reg.FxpTypeInfo,_FXPConvert) { Name = reg.Name });
+                                if (!reg.Indicator)
+                                {
+                                    properties.Add(new FPGAArrayFXPWriteProperty(session, reg.Offset, reg.Size, reg.FxpTypeInfo, _FXPConvert) { Name = reg.Name });
+                                }
+                                else
+                                {
+                                    properties.Add(new FPGAArrayFXPReadProperty(session, reg.Offset, reg.Size, reg.FxpTypeInfo, _FXPConvert) { Name = reg.Name });
+                                }
                                 break;
                             case lvbitx.Datatype.Array:
                                 break;

+ 31 - 0
NIFPGA/FPGAArrayFXPReadProperty.cs

@@ -0,0 +1,31 @@
+using FxpConvert.Common;
+
+namespace NIFPGA
+{
+    public sealed class FPGAArrayFXPReadProperty : FPGABaseProperty
+    {
+        Interop.NiFpgaDll_ReadArrayU64 Read;
+        private NiFpga_FxpTypeInfo _TypeInfo;
+        private IFxpConvert _Convert;
+        private ulong[] tempvalue = new ulong[0];
+        private float[] doubles = new float[0];
+        internal FPGAArrayFXPReadProperty(FPGASession session, uint indicator, uint count, NiFpga_FxpTypeInfo typeInfo, IFxpConvert convert) : base(session, indicator, true)
+        {
+            _Convert = convert;
+            Count = count;
+            tempvalue = new ulong[count];
+            doubles = new float[count];
+            _TypeInfo = typeInfo;
+            Read = _Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU64>();
+        }
+
+        private float[] GetData()
+        {
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref tempvalue[0], Count));
+            _Convert.FxpConvertToFloat(ref tempvalue[0], _TypeInfo, ref doubles[0], Count);
+            return doubles;
+        }
+        public uint Count { get; }
+        public float[] Value { get => GetData(); }
+    }
+}

+ 38 - 0
NIFPGA/FPGAArrayFXPWriteProperty.cs

@@ -0,0 +1,38 @@
+using FxpConvert.Common;
+
+namespace NIFPGA
+{
+    public sealed class FPGAArrayFXPWriteProperty : FPGABaseProperty
+    {
+        Interop.NiFpgaDll_ReadArrayU64 Read;
+        Interop.NiFpgaDll_WriteArrayU64 Write;
+        private NiFpga_FxpTypeInfo _TypeInfo;
+        private IFxpConvert _Convert;
+        private ulong[] tempvalue = new ulong[0];
+        private float[] doubles = new float[0];
+        internal FPGAArrayFXPWriteProperty(FPGASession session, uint indicator, uint count,NiFpga_FxpTypeInfo typeInfo, IFxpConvert convert) : base(session, indicator,false)
+        {
+            _Convert = convert;
+            Count = count;
+            tempvalue = new ulong[count];
+            doubles = new float[count];
+            _TypeInfo = typeInfo;
+            Read = _Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU64>();
+            Write = _Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU64>();
+        }
+        private float[] GetData()
+        {
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref tempvalue[0], Count));
+            _Convert.FxpConvertToFloat(ref tempvalue[0], _TypeInfo, ref doubles[0], Count);
+            return doubles;
+        }
+        private void SetData(float[] values)
+        {
+            if (values.Length != Count) return;
+            _Convert.FloatConvertToDxp(ref values[0], _TypeInfo, ref tempvalue[0], Count);
+            _Session.CheckResult(Write(_Session.Session,Indicator, ref tempvalue[0], Count));
+        }
+        public uint Count { get; }
+        public float[] Value { get => GetData(); set => SetData(value); }
+    }
+}

+ 62 - 0
NIFPGA/FPGAArrayReadProperty.cs

@@ -0,0 +1,62 @@
+using System.Runtime.CompilerServices;
+
+namespace NIFPGA
+{
+    public sealed class FPGAArrayReadProperty<T> : FPGABaseProperty
+    where T : unmanaged
+    {
+        delegate NiFpga_Status NiFpgaDll_Delegate(uint session, uint indicator, ref T array, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.U4)] uint size);
+        NiFpgaDll_Delegate Read;
+        private T[] tempvalue = new T[0];
+        internal FPGAArrayReadProperty(FPGASession session, uint indicator, uint count) : base(session, indicator, true)
+        {
+            Count = count;
+            tempvalue = new T[Count];
+
+            switch (tempvalue[0])
+            {
+                case (bool):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayBool).Name);
+                    break;
+                case (byte):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU8).Name);
+                    break;
+                case (sbyte):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI8).Name);
+                    break;
+                case short:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI16).Name);
+                    break;
+                case (ushort):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU16).Name);
+                    break;
+                case (int):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI32).Name);
+                    break;
+                case (uint):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU32).Name);
+                    break;
+                case (long):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI64).Name);
+                    break;
+                case (ulong):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU64).Name);
+                    break;
+                case (float):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArraySgl).Name);
+                    break;
+                case (double):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayDbl).Name);
+                    break;
+            }
+        }
+        private T[] GetValues()
+        {
+            if (Count == 0) return tempvalue;
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref tempvalue[0], Count));
+            return tempvalue;
+        }
+        public uint Count { get; }
+        public T[] Values { get => GetValues(); }
+    }
+}

+ 79 - 0
NIFPGA/FPGAArrayWriteProperty.cs

@@ -0,0 +1,79 @@
+using System.Runtime.CompilerServices;
+
+namespace NIFPGA
+{
+    public sealed class FPGAArrayWriteProperty<T> : FPGABaseProperty
+    where T : unmanaged
+    {
+        private delegate NiFpga_Status NiFpgaDll_Delegate(uint session, uint indicator, ref T array, [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.U4)] uint size);
+        NiFpgaDll_Delegate Read;
+        NiFpgaDll_Delegate Write;
+        private T[] tempvalue = new T[0];
+        internal FPGAArrayWriteProperty(FPGASession session, uint indicator,uint count) : base(session, indicator,false)
+        {
+            Count= count;
+            tempvalue = new T[Count];
+            switch (tempvalue[0])
+            {
+                case (bool):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayBool).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayBool).Name);
+                    break;
+                case (byte):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU8).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayU8).Name);
+                    break;
+                case (sbyte):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI8).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayI8).Name);
+                    break;
+                case short:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI16).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayI16).Name);
+                    break;
+                case (ushort):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU16).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayU16).Name);
+                    break;
+                case (int):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI32).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayI32).Name);
+                    break;
+                case (uint):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU32).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayU32).Name);
+                    break;
+                case (long):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayI64).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayI64).Name);
+                    break;
+                case (ulong):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayU64).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayU64).Name);
+                    break;
+                case (float):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArraySgl).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArraySgl).Name);
+                    break;
+                case (double):
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadArrayDbl).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteArrayDbl).Name);
+                    break;
+            }
+        }
+
+        private T[] GetValues()
+        {
+            if (Count == 0) return tempvalue;
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref tempvalue[0], Count));
+            return tempvalue;
+        }
+        private void SetValue(T[] values)
+        {
+            if (values.Length != Count) return;
+            _Session.CheckResult(Write(_Session.Session, Indicator, ref values[0], Count));
+        }
+        public uint Count { get; }
+        public T[] Values { get => GetValues(); set => SetValue(value); }
+    }
+}

+ 26 - 0
NIFPGA/FPGAFXPReadProperty.cs

@@ -0,0 +1,26 @@
+using FxpConvert.Common;
+
+namespace NIFPGA
+{
+    public sealed class FPGAFXPReadProperty : FPGABaseProperty
+    {
+        Interop.NiFpgaDll_ReadU64 Read;
+        private NiFpga_FxpTypeInfo _TypeInfo;
+        private IFxpConvert _Convert;
+        internal FPGAFXPReadProperty(FPGASession session, uint indicator, NiFpga_FxpTypeInfo typeInfo, IFxpConvert convert) : base(session, indicator, true)
+        {
+            _TypeInfo = typeInfo;
+            _Convert = convert;
+            Read = _Session.GetDelegate<Interop.NiFpgaDll_ReadU64>();
+        }
+        private float GetValue()
+        {
+            ulong value = 0;
+            float temp = 0;
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref value));
+            _Convert.FxpConvertToFloat(ref value, _TypeInfo, ref temp, 1);
+            return temp;
+        }
+        public float Value => GetValue();
+    }
+}

+ 34 - 0
NIFPGA/FPGAFXPWriteProperty.cs

@@ -0,0 +1,34 @@
+using FxpConvert.Common;
+
+namespace NIFPGA
+{
+    public sealed class FPGAFXPWriteProperty: FPGABaseProperty
+    {
+        Interop.NiFpgaDll_ReadU64 Read;
+        Interop.NiFpgaDll_WriteU64 Write;
+        private NiFpga_FxpTypeInfo _TypeInfo;
+        private IFxpConvert _Convert;
+        internal FPGAFXPWriteProperty(FPGASession session, uint indicator,NiFpga_FxpTypeInfo typeInfo,IFxpConvert convert) : base(session, indicator,false)
+        {
+            _TypeInfo = typeInfo;
+            _Convert = convert;
+            Read = _Session.GetDelegate<Interop.NiFpgaDll_ReadU64>();
+            Write = _Session.GetDelegate<Interop.NiFpgaDll_WriteU64>();
+        }
+        private float GetValue()
+        {
+            ulong value = 0;
+            float temp = 0;
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref value));
+            _Convert.FxpConvertToFloat(ref value, _TypeInfo, ref temp, 1);
+            return temp;
+        }
+        private void SetValue(float value)
+        {
+            ulong temp = 0;
+            _Convert.FloatConvertToDxp(ref value, _TypeInfo, ref temp, 1);
+            _Session.CheckResult(Write(_Session.Session, Indicator, temp));
+        }
+        public float Value { get => GetValue(); set => SetValue(value); }
+    }
+}

+ 0 - 250
NIFPGA/FPGAProperty.cs

@@ -1,250 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics.Metrics;
-using System.Linq;
-using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
-using FxpConvert.Common;
-
-namespace NIFPGA
-{
-    public sealed class FPGAProperty<T> : FPGABaseProperty
-        where T : unmanaged
-    {
-        internal FPGAProperty(FPGASession session, uint indicator,bool isIndicator = true) : base(session, indicator,isIndicator)
-        {
-        }
-        private void SetValue(T value)
-        {
-            switch(value)
-            {
-                case Boolean boolvalue:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteBool>()(_Session.Session, Indicator, Convert.ToByte(boolvalue)));
-                    break;
-                case Byte:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteU8>()(_Session.Session, Indicator, Unsafe.As<T,byte>(ref value)));
-                    break;
-                case SByte:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteI8>()(_Session.Session, Indicator, Unsafe.As<T, sbyte>(ref value)));
-                    break;
-                case Int16:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteI16>()(_Session.Session, Indicator, Unsafe.As<T, short>(ref value)));
-                    break;
-                case UInt16:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteU16>()(_Session.Session, Indicator, Unsafe.As<T, ushort>(ref value)));
-                    break;
-                case Int32:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteI32>()(_Session.Session, Indicator, Unsafe.As<T, int>(ref value)));
-                    break;
-                case UInt32:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteU32>()(_Session.Session, Indicator, Unsafe.As<T, uint>(ref value)));
-                    break;
-                case Int64:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteI64>()(_Session.Session, Indicator, Unsafe.As<T, long>(ref value)));
-                    break;
-                case UInt64:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteU64>()(_Session.Session, Indicator, Unsafe.As<T, ulong>(ref value)));
-                    break;
-                case Single:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteSgl>()(_Session.Session, Indicator, Unsafe.As<T, float>(ref value)));
-                    break;
-                case double:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteDbl>()(_Session.Session, Indicator, Unsafe.As<T, double>(ref value)));
-                    break;
-            }
-        }
-
-
-        private T GetValue()
-        {
-            T value = default;
-            switch (value)
-            {
-                case Boolean:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadBool>()(_Session.Session, Indicator,ref Unsafe.As<T,byte>(ref value)));
-                    break;
-                case Byte:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadU8>()(_Session.Session, Indicator, ref Unsafe.As<T, byte>(ref value)));
-                    break;
-                case SByte:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadI8>()(_Session.Session, Indicator, ref Unsafe.As<T, sbyte>(ref value)));
-                    break;
-                case Int16:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadI16>()(_Session.Session, Indicator, ref Unsafe.As<T, short>(ref value)));
-                    break;
-                case UInt16:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadU16>()(_Session.Session, Indicator, ref Unsafe.As<T, ushort>(ref value)));
-                    break;
-                case Int32:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadI32>()(_Session.Session, Indicator, ref Unsafe.As<T, int>(ref value)));
-                    break;
-                case UInt32:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadU32>()(_Session.Session, Indicator, ref Unsafe.As<T, uint>(ref value)));
-                    break;
-                case Int64:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadI64>()(_Session.Session, Indicator, ref Unsafe.As<T, long>(ref value)));
-                    break;
-                case UInt64:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadU64>()(_Session.Session, Indicator, ref Unsafe.As<T, ulong>(ref value)));
-                    break;
-                case Single:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadSgl>()(_Session.Session, Indicator, ref Unsafe.As<T, float>(ref value)));
-                    break;
-                case double:
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadDbl>()(_Session.Session, Indicator, ref Unsafe.As<T, double>(ref value)));
-                    break;
-            }
-            return value;
-        }
-        public T Value { get=>GetValue(); set=>SetValue(value); }
-    }
-    public sealed class FPGAFXPProperty: FPGABaseProperty
-    {
-        private NiFpga_FxpTypeInfo _TypeInfo;
-        private IFxpConvert _Convert;
-        internal FPGAFXPProperty(FPGASession session, uint indicator,NiFpga_FxpTypeInfo typeInfo,IFxpConvert convert, bool isIndicator = true) : base(session, indicator,isIndicator)
-        {
-            _TypeInfo = typeInfo;
-            _Convert = convert;
-        }
-        private float GetValue()
-        {
-            ulong value=0;
-            float temp = 0;
-            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadU64>()(_Session.Session, Indicator, ref value));
-            _Convert.FxpConvertToFloat(ref value, _TypeInfo, ref temp, 1);
-            return temp;
-        }
-        private void SetValue(float value)
-        {
-            ulong temp = 0;
-            _Convert.FloatConvertToDxp(ref value, _TypeInfo, ref temp, 1);
-            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteU64>()(_Session.Session, Indicator, temp));
-        }
-        public float Value { get=>GetValue(); set=>SetValue(value); }
-    }
-    public sealed class FPGAArrayProperty<T> : FPGABaseProperty
-    where T : unmanaged
-    {
-        private T[] tempvalue = new T[0];
-        internal FPGAArrayProperty(FPGASession session, uint indicator,uint count, bool isIndicator = true) : base(session, indicator,isIndicator)
-        {
-            Count= count;
-            tempvalue= new T[Count];
-        }
-        private void SetValue(T[] values)
-        {
-            if (values.Length == 0 || values.Length!=Count) return;
-            switch (values[0])
-            {
-                case (bool):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayBool>()(_Session.Session, Indicator, ref Unsafe.As<T, byte>(ref values[0]), Count));
-                    break;
-                case (byte):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU8>()(_Session.Session, Indicator, ref Unsafe.As<T, byte>(ref values[0]), Count));
-                    break;
-                case (sbyte):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayI8>()(_Session.Session, Indicator, ref Unsafe.As<T, sbyte>(ref values[0]), Count));
-                    break;
-                case (short):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayI16>()(_Session.Session, Indicator, ref Unsafe.As<T, short>(ref values[0]), Count));
-                    break;
-                case (ushort):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU16>()(_Session.Session, Indicator, ref Unsafe.As<T, ushort>(ref values[0]), Count));
-                    break;
-                case (int):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayI32>()(_Session.Session, Indicator, ref Unsafe.As<T, int>(ref values[0]), Count));
-                    break;
-                case (uint):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU32>()(_Session.Session, Indicator, ref Unsafe.As<T, uint>(ref values[0]), Count));
-                    break;
-                case (long):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayI64>()(_Session.Session, Indicator, ref Unsafe.As<T, long>(ref values[0]), Count));
-                    break;
-                case (ulong):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU64>()(_Session.Session, Indicator, ref Unsafe.As<T, ulong>(ref values[0]), Count));
-                    break;
-                case (float):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArraySgl>()(_Session.Session, Indicator, ref Unsafe.As<T, float>(ref values[0]), Count));
-                    break;
-                case (double):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayDbl>()(_Session.Session, Indicator, ref Unsafe.As<T, double>(ref values[0]), Count));
-                    break;
-            }
-        }
-        private T[] GetValues()
-        {
-            if (Count == 0) return tempvalue;
-            switch (tempvalue[0])
-            {
-                case (bool):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayBool>()(_Session.Session, Indicator, ref Unsafe.As<T, byte>(ref tempvalue[0]), Count));
-                    break;
-                case (byte):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU8>()(_Session.Session, Indicator, ref Unsafe.As<T, byte>(ref tempvalue[0]), Count));
-                    break;
-                case (sbyte):
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayI8>()(_Session.Session, Indicator, ref Unsafe.As<T, sbyte>(ref tempvalue[0]), Count));
-                    break;                                                                                                                                 
-                case short:                                                                                                                        
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayI16>()(_Session.Session, Indicator, ref Unsafe.As<T, short>(ref tempvalue[0]),Count));
-                    break;                                                                                                                                 
-                case (ushort):                                                                                                                        
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU16>()(_Session.Session, Indicator, ref Unsafe.As<T, ushort>(ref tempvalue[0]),Count));
-                    break;                                                                                                                                 
-                case (int):                                                                                                                          
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayI32>()(_Session.Session, Indicator, ref Unsafe.As<T, int>(ref tempvalue[0]),Count));
-                    break;                                                                                                                                 
-                case (uint):                                                                                                                         
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU32>()(_Session.Session, Indicator, ref Unsafe.As<T, uint>(ref tempvalue[0]),Count));
-                    break;                                                                                                                                 
-                case (long):                                                                                                                         
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayI64>()(_Session.Session, Indicator, ref Unsafe.As<T, long>(ref tempvalue[0]),Count));
-                    break;                                                                                                                                 
-                case (ulong):                                                                                                                        
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU64>()(_Session.Session, Indicator, ref Unsafe.As<T, ulong>(ref tempvalue[0]),Count));
-                    break;                                                                                                                                 
-                case (float):                                                                                                                        
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArraySgl>()(_Session.Session, Indicator, ref Unsafe.As<T, float>(ref tempvalue[0]),Count));
-                    break;                                                                                                                                 
-                case (double):                                                                                                                       
-                    _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayDbl>()(_Session.Session, Indicator, ref Unsafe.As<T, double>(ref tempvalue[0]), Count));
-                    break;
-            }
-            return tempvalue;
-        }
-        public uint Count { get; }
-        public T[] Values { get=>GetValues(); set=>SetValue(value); }
-    }
-
-    public sealed class FPGAArrayFXPProperty : FPGABaseProperty
-    {
-        private NiFpga_FxpTypeInfo _TypeInfo;
-        private IFxpConvert _Convert;
-        private ulong[] tempvalue = new ulong[0];
-        private float[] doubles= new float[0];
-        internal FPGAArrayFXPProperty(FPGASession session, uint indicator, uint count,NiFpga_FxpTypeInfo typeInfo, IFxpConvert convert, bool isIndicator = true) : base(session, indicator,isIndicator)
-        {
-            _Convert = convert;
-            Count = count;
-            tempvalue = new ulong[count];
-            doubles = new float[count];
-            _TypeInfo = typeInfo;
-        }
-        private void SetData(float[] values)
-        {
-            if (values.Length != Count) return;
-            _Convert.FloatConvertToDxp(ref values[0], _TypeInfo, ref tempvalue[0], Count);
-            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_WriteArrayU64>()(_Session.Session,Indicator, ref tempvalue[0], Count));
-        }
-        private float[] GetData()
-        {
-            _Session.CheckResult(_Session.GetDelegate<Interop.NiFpgaDll_ReadArrayU64>()(_Session.Session,Indicator, ref tempvalue[0], Count));
-            _Convert.FxpConvertToFloat(ref tempvalue[0], _TypeInfo,ref doubles[0], Count);
-            return doubles;
-        }
-        public uint Count { get; }
-        public float[] Value { get=>GetData(); set=>SetData(value); }
-    }
-}

+ 60 - 0
NIFPGA/FPGAReadProperty.cs

@@ -0,0 +1,60 @@
+using System.Diagnostics.CodeAnalysis;
+using System.Runtime.CompilerServices;
+
+namespace NIFPGA
+{
+    public sealed class FPGAReadProperty<T> : FPGABaseProperty
+        where T : unmanaged
+    {
+        private delegate NiFpga_Status NiFpgaDll_Delegate(uint session, uint indicator, ref T value);
+        [AllowNull]
+        private NiFpgaDll_Delegate Read;
+        internal FPGAReadProperty(FPGASession session, uint indicator) : base(session, indicator, true)
+        {
+            T val = default(T);
+            switch (val)
+            {
+                case Boolean:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadBool).Name);
+                    break;
+                case Byte:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU8).Name);
+                    break;
+                case SByte:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI8).Name);
+                    break;
+                case Int16:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI16).Name);
+                    break;
+                case UInt16:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU16).Name);
+                    break;
+                case Int32:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI32).Name);
+                    break;
+                case UInt32:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU32).Name);
+                    break;
+                case Int64:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI64).Name);
+                    break;
+                case UInt64:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU64).Name);
+                    break;
+                case Single:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadSgl).Name);
+                    break;
+                case double:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadDbl).Name);
+                    break;
+            }
+        }
+        private T GetValue()
+        {
+            T value = default;
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref value));
+            return value;
+        }
+        public T Value => GetValue();
+    }
+}

+ 4 - 0
NIFPGA/FPGASession.cs

@@ -41,6 +41,10 @@ namespace NIFPGA
         {
             return _NativeLoader.LoadFunction<T>(typeof(T).Name);
         }
+        public T GetDelegate<T>(string enterpoint) where T : Delegate
+        {
+            return _NativeLoader.LoadFunction<T>(enterpoint);
+        }
         public void CheckResult(NiFpga_Status result)
         {
             Error = result < NiFpga_Status.Success;

+ 85 - 0
NIFPGA/FPGAWriteProperty.cs

@@ -0,0 +1,85 @@
+using Newtonsoft.Json.Linq;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Diagnostics.Metrics;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace NIFPGA
+{
+    public sealed class FPGAWriteProperty<T> : FPGABaseProperty
+        where T : unmanaged
+    {
+        private delegate NiFpga_Status NiFpgaDll_Delegate(uint session, uint indicator, ref T value);
+        [AllowNull]
+        private NiFpgaDll_Delegate Read;
+        [AllowNull]
+        private NiFpgaDll_Delegate Write;
+        internal FPGAWriteProperty(FPGASession session, uint indicator) : base(session, indicator,false)
+        {
+            T val =default(T);
+            switch (val)
+            {
+                case Boolean:
+                     Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadBool).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteBool).Name);
+                    break;
+                case Byte:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU8).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteU8).Name);
+                    break;
+                case SByte:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI8).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteI8).Name);
+                    break;
+                case Int16:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI16).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteI16).Name);
+                    break;
+                case UInt16:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU16).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteU16).Name);
+                    break;
+                case Int32:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI32).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteI32).Name);
+                    break;
+                case UInt32:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU32).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteU32).Name);
+                    break;
+                case Int64:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadI64).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteI64).Name);
+                    break;
+                case UInt64:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadU64).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteU64).Name);
+                    break;
+                case Single:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadSgl).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteSgl).Name);
+                    break;
+                case double:
+                    Read = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_ReadDbl).Name);
+                    Write = _Session.GetDelegate<NiFpgaDll_Delegate>(typeof(Interop.NiFpgaDll_WriteDbl).Name);
+                    break;
+            }
+        }
+
+        private T GetValue()
+        {
+            T value = default;
+            _Session.CheckResult(Read(_Session.Session, Indicator, ref value));
+            return value;
+        }
+        private void SetValue(T value)
+        {
+            _Session.CheckResult(Write(_Session.Session, Indicator, ref value));
+        }
+        public T Value { get => GetValue(); set => SetValue(value); }
+    }
+}

+ 8 - 1
NIFPGA/NIFPGA.projitems

@@ -11,8 +11,15 @@
   <ItemGroup>
     <Compile Include="$(MSBuildThisFileDirectory)Fifo.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)FPGA.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAArrayFXPReadProperty.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAArrayFXPWriteProperty.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAArrayReadProperty.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAArrayWriteProperty.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)FPGABaseProperty.cs" />
-    <Compile Include="$(MSBuildThisFileDirectory)FPGAProperty.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAFXPReadProperty.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAFXPWriteProperty.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAWriteProperty.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)FPGAReadProperty.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)FPGASession.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)Irq.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)NIFPGA.Interop.cs" />

+ 13 - 0
NIFPGA/lvbitx/Bitfile.cs

@@ -25,11 +25,24 @@ namespace NIFPGA.lvbitx
     }
     public class Register
     {
+        /// <summary>
+        /// 寄存器名字
+        /// </summary>
         public string Name { get; set; } = string.Empty;
         public Boolean Hidden { get; set; }
+        /// <summary>
+        /// <see cref="true"/>为写
+        /// <see cref="false"/>为读
+        /// </summary>
         public Boolean Indicator { get; set; }
+        /// <summary>
+        /// 数据类型
+        /// </summary>
         public Datatype Datatype { get; set; }
         public string FlattenedType { get; set; } = string.Empty;
+        /// <summary>
+        /// 寄存器地址
+        /// </summary>
         public uint Offset { get; set; }
         public uint SizeInBits { get; set; }
         public uint Class { get; set; }

+ 1 - 2
Shaker.Model/Model/AmptIdentifyConfigModel.cs

@@ -6,8 +6,7 @@ namespace Shaker.Model
     {
         public float LowFreq = 3;
         public float HigthFreq = 6;
-
-        public object Clone()
+        public override object Clone()
         {
             return this.CloneBase();
         }

+ 4 - 1
Shaker.Model/Model/CircuitModel.cs

@@ -10,6 +10,9 @@ namespace Shaker.Model
         public bool EnablePressure = true;
         public bool IsLoadPressure = false;
 
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 1 - 2
Shaker.Model/Model/DeviceInfoModel.cs

@@ -12,8 +12,7 @@ namespace Shaker.Model
         public string SN = string.Empty;
         public string IP = "127.0.0.1";
         public int Port = 5555;
-
-        public object Clone()
+        public override object Clone()
         {
             return this.CloneBase();
         }

+ 4 - 1
Shaker.Model/Model/ErrorInfoModel.cs

@@ -4,6 +4,9 @@
     {
         public string Name = string.Empty;
         public bool Status = false;
-        public object Clone() => this.CloneBase();
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 2 - 5
Shaker.Model/Model/IModel.cs

@@ -14,17 +14,14 @@ namespace Shaker.Model
     public abstract class BaseModel : IModel
     {
         public int Id = 0;
-        public virtual object Clone()
-        {
-            return this.CloneBase();
-        }
+        public abstract object Clone();
     }
 
     public static class IModelTools
     {
         public static TModel CloneBase<TModel>(this TModel model) where TModel:IModel
         {
-            return Newtonsoft.Json.JsonConvert.DeserializeObject<TModel>(Newtonsoft.Json.JsonConvert.SerializeObject(model)) ?? default(TModel);
+            return Newtonsoft.Json.JsonConvert.DeserializeObject<TModel>(Newtonsoft.Json.JsonConvert.SerializeObject(model)) ?? Activator.CreateInstance<TModel>();
         }
     }
 }

+ 21 - 0
Shaker.Model/Model/LevelLogic.cs

@@ -0,0 +1,21 @@
+using System.ComponentModel;
+
+namespace Shaker.Model
+{
+    /// <summary>
+    /// PLC逻辑量控制逻辑
+    /// </summary>
+    public enum LevelLogic
+    {
+        /// <summary>
+        /// 电平
+        /// </summary>
+        [Description("Level")]
+        Level,
+        /// <summary>
+        /// 边沿
+        /// </summary>
+        [Description("Edge")]
+        Edge,
+    }
+}

+ 1 - 3
Shaker.Model/Model/OilSourceAnalogModel.cs

@@ -9,10 +9,8 @@
         public bool IsLowerWarn = false;
         public bool IsLowerError = false;
         public string Unit = string.Empty;
-
-        public object Clone()
+        public override object Clone()
         {
-
             return this.CloneBase();
         }
     }

+ 3 - 12
Shaker.Model/Model/OilSourceModel.cs

@@ -69,6 +69,7 @@ namespace Shaker.Model
             Name="CyclePump",
             EnablePressure = false,
         };
+        public LevelLogic LevelLogic = LevelLogic.Edge;
         /// <summary>
         /// 是否为远程控制
         /// </summary>
@@ -83,19 +84,9 @@ namespace Shaker.Model
         public List<OilSourceAnalogModel> OilSourceAnalogs = new List<OilSourceAnalogModel>();
 
         public List<ErrorInfoModel> OilErrors = new List<ErrorInfoModel>();
-        public object Clone()
+        public override object Clone()
         {
-            return new OilSourceStatusModel()
-            {
-                Circuit = Circuit.Select(x => x.Clone()).Cast<CircuitModel>().ToList(),
-                Forerunner = (CircuitModel)Forerunner.Clone(),
-                Circulate = Circulate.CloneBase(),
-                Assistant = Assistant.CloneBase(),
-                IsRemote = IsRemote,
-                IsEnabled = IsEnabled,
-                OilSourceAnalogs = OilSourceAnalogs.Select(x => x.Clone()).Cast<OilSourceAnalogModel>().ToList(),
-                OilErrors = OilErrors.ToList(),
-            };
+            return this.CloneBase();
         }
     }
 }

+ 4 - 1
Shaker.Model/Model/SearchDeviceModel.cs

@@ -10,7 +10,10 @@ namespace Shaker.Model
     {
         public string License = string.Empty;
 
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
     public sealed class ResultDeviceModel:BaseModel
     {

+ 0 - 31
Shaker.Model/Model/ShakerConfigModel.cs

@@ -1,31 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Shaker.Model
-{
-    public class ShakerConfigModel : BaseModel
-    {
-
-        public uint MaxRiseCount = 120000;
-        public uint MaxZeroChangedCount = 40000;
-        public uint MaxSignalCount = 20000;
-        public uint MaxEmergencyStopCount = 6000;
-        public uint MaxStopWindowCount = 16000;
-        public uint MaxAdjustCount = 4000;
-        public uint MaxFallCount = 60000;
-        public uint StartCount = 70000;
-        public float InitialLocation = -45;
-        public uint SampleRate = 4000;
-        public uint FPGAClock = 40_000_000;
-        public uint ChannelCount = 8;
-        public float MaxFrequency = 200f;
-        public float MinFrequency = 0.1f;
-        public string[] ChannelNames = new string[8] { "GivenDisplacementSignal", "MeasuredDisplacementSignal", "AccelerationSignal", "OutInputSignal", "ValveDriveSignal1", "ValveDriveSignal2", "ValveDriveSignal3", "ValveDriveSignal4" };
-        public string[] Units = new string[8] { "mm","mm","g","V","V","V","V","V"};
-
-
-    }
-}

+ 11 - 7
Shaker.Model/Model/ShakerControlModel.cs

@@ -1,30 +1,34 @@
 
+using Shaker.Models;
+
 namespace Shaker.Model
 {
     public class ShakerControlModel : BaseModel
     {
-        public int MaxControlItemCount = 50;
+        public readonly int MaxControlItemCount = 50;
         public float MaxValveVoltage = 16;
         public float MinValveVoltage = -16;
         public float MaxDisplacementVoltage = 16;
         public float MinDisplacementVoltage = -16;
         public Polarity ValvePolarity = Polarity.Positive;
-        public Polarity AccelerationPolarity = Polarity.Positive;
         public bool SelfLoop = false;
         public bool Debug = false;
         public float DisplacementP = 1;
         public float DisplacementI = 0;
         public float FlutterFrequency = 200;
         public float FlutterAmpt = 0.01f;
-        public const int ServoValveCount = 4;
         public float MaxDisplacementIntegral = 2;
+        public MainPageType PageType = MainPageType.StartPage;
         public float DisplacementBias = 0;
-        public float[] ServoValveBias = new float[ServoValveCount];
+        public List<ValveConfigItemModel> ValveConfig = new List<ValveConfigItemModel>();
+
         public bool OilStopped = false;
         public bool DisplacementOpenLoop = false;
-        public float[] OpenLoopDisplacement = new float[ServoValveCount];
         public bool OutSignal = false;
-        public List<SweepControlItemModel> ControlItems  = new List<SweepControlItemModel>();
-
+        public List<SweepControlItemModel> ControlItems = new List<SweepControlItemModel>();
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 1
Shaker.Model/Model/ShakerSecurityModel.cs

@@ -9,6 +9,9 @@
         public float MaxJitterAcceleration = 32;
         public float MaxJitterDisplacement = 1000;
         public float MaxVelocity = 0.6f;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 1
Shaker.Model/Model/ShakerSensitivityModel.cs

@@ -4,6 +4,9 @@
     {
         public float Displacement=100;
         public float Acceleration=100;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 3
Shaker.Model/Model/ShakerStatusModel.cs

@@ -5,7 +5,6 @@ namespace Shaker.Model
     {
         public RTStatus RTStatus = RTStatus.Init;
         public bool Start = false;
-        public float SynthesisAmplitude = 0;
         public bool IsTableRised = false;
         public bool IsTableDroped = false;
         public bool IsFaultRelease = false;
@@ -19,7 +18,9 @@ namespace Shaker.Model
         public bool ClosedValve = false;
         public uint DropCount = 0;
         public ushort ErrorCode = 0;
-        public bool ValvePower = false;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 1
Shaker.Model/Model/SweepControlItemModel.cs

@@ -28,6 +28,9 @@ namespace Shaker.Model
         /// 压缩速率
         /// </summary>
         public float CompressionRate = 1400;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 1 - 2
Shaker.Model/Model/SweepFreqConfigModel.cs

@@ -34,8 +34,7 @@
         public List<float> LowerWarnSlope = new List<float>();
         public List<float> LowerWarnOffset = new List<float>();
         public List<SweepItemModel> SweepItems = new List<SweepItemModel>();
-
-        public object Clone()
+        public override object Clone()
         {
             return this.CloneBase();
         }

+ 4 - 1
Shaker.Model/Model/SweepItemModel.cs

@@ -15,6 +15,9 @@ namespace Shaker.Model
         public float UpWarn = 3;
         public float DownStop = -6;
         public float DownWarn = -3;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 13 - 0
Shaker.Model/Model/ValveConfigItemModel.cs

@@ -0,0 +1,13 @@
+
+namespace Shaker.Model
+{
+    public class ValveConfigItemModel:BaseModel
+    {
+        public float Bias = 0;
+        public float OpenLoopDrive = 0;
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
+    }
+}

+ 4 - 0
Shaker.Model/Models/AccelerationConfigModel.cs

@@ -11,5 +11,9 @@ namespace Shaker.Model
         public float Weight = 1;
         public float Sensitivity = 100;
         public Shaker.Model.Polarity Polarity = Polarity.Positive;
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

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

@@ -15,10 +15,11 @@ namespace Shaker.Model
         [AllowNull]
         public ShakerControlModel ShakerControl { get; set; }
         [AllowNull]
-        public ShakerSecurityModel ShakerSecurity { get; set; }
-        [AllowNull]
-        public ShakerSensitivityModel ShakerSensitivity { get; set; }
+        public ShakerStatusModel ShakerStatus { get; set; }
+
         [AllowNull]
         public SweepConfigModel SweepConfig { get; set; }
+        [AllowNull]
+        public ShakerConfigModel ShakerConfig { get; set; }
     }
 }

+ 4 - 0
Shaker.Model/Models/AnalogSignalConfigModel.cs

@@ -7,5 +7,9 @@ namespace Shaker.Models
         public string Name = string.Empty;
         public string Unit = string.Empty;
         public AnalogType AnalogType = AnalogType.Displacement;
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 1
Shaker.Model/Models/RandomConfigModel.cs

@@ -24,6 +24,9 @@ namespace Shaker.Model
         public uint StopLins = 160;
         public uint WarnLines = 120;
         public float StopRMS = 6;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 1
Shaker.Model/Models/RandomIdentifyModel.cs

@@ -7,6 +7,9 @@
         public float EndLevel = -12;
         public float MaxDisplacement = 10;
         public uint IdentifyFrameCount = 20;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 1
Shaker.Model/Models/RandomPlanItemModel.cs

@@ -4,6 +4,9 @@
     {
         public float Level = 0;
         public uint Time = 10;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 1
Shaker.Model/Models/RandomSpectrumItemModel.cs

@@ -9,6 +9,9 @@
         public float UpWarn = 3;
         public float DownStop = -6;
         public float DownWarn = -3;
-
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 6 - 3
Shaker.Model/Models/ShakerConfigModel.cs

@@ -24,7 +24,7 @@ namespace Shaker.Models
         public uint FPGAClock = 40_000_000;
         public float MaxFrequency = 200f;
         public float MinFrequency = 0.1f;
-        public AnalogSignalConfigModel[] AnalogSignalConfigs = new AnalogSignalConfigModel[0] { };
+        public List<AnalogSignalConfigModel> AnalogSignalConfigs = new List<AnalogSignalConfigModel>();
 
 
         public float MaxOutInput = 16;
@@ -38,7 +38,10 @@ namespace Shaker.Models
 
 
         public float DisplacementSensitivity = 100;
-        public AccelerationConfigModel[] AccelerationConfigs = new AccelerationConfigModel[] { };
-
+        public List<AccelerationConfigModel> AccelerationConfigs = new List<AccelerationConfigModel>();
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 4 - 3
Shaker.Model/Models/SineDataModel.cs

@@ -7,16 +7,17 @@ using System.Threading.Tasks;
 
 namespace Shaker.Model
 {
-    public class SineDataModel : IResultDataModel
+    public class SineDataModel :BaseModel, IResultDataModel
     {
         public float TotalTime = 0;
         public float RunTime = 0;
         public float CurrentFrequency = 0;
         public float CurrentAcceleration = 0;
-        public int SweepIndex = 0;
+        public uint SweepIndex = 0;
         public SweepDirection SweepDirection = SweepDirection.Up;
+        public SweepStep SweepStep = SweepStep.Start;
         public readonly MainPageType MainPageType = MainPageType.SinePage;
-        public object Clone()
+        public override object Clone()
         {
             return this.CloneBase();
         }

+ 6 - 1
Shaker.Model/Models/SweepConfigModel.cs

@@ -30,9 +30,14 @@ namespace Shaker.Models
         public float HigthFrequencyMinCorrect = 0.9f;
         public float HigthFrequencyMaxCorrect = 1.1f;
         public int SelectChannel = 0;
+        public float LowFreq = 3;
+        public float HighFreq = 6;
 
         public List<SweepItemModel> SweepItems = new List<SweepItemModel>();
-        
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
 
     }
 }

+ 0 - 10
Shaker/BitAddressConfig.cs

@@ -1,10 +0,0 @@
-using Shaker.Model;
-
-namespace ShakerService
-{
-    public class BitAddressConfig:BaseModel
-    {
-        public string Address = "";
-        public byte BitIndex = 0;
-    }
-}

+ 5 - 38
Shaker/Communication.cs

@@ -16,6 +16,7 @@ namespace ShakerService
         private Communication()
         {
             Context = new LocalCommunication.Communication();
+            DbConnection = new SQLite.SQLiteConnection("Config.db");
         }
         static Communication()
         {
@@ -23,7 +24,6 @@ namespace ShakerService
         }
         public void StartService(string ip,int port)
         {
-            DbConnection = new SQLite.SQLiteConnection("Config.db");
             Context.StartService(ip, port);
             InitMsgResponse();
         }
@@ -35,45 +35,12 @@ namespace ShakerService
                 {
                     SweepConfig = ServiceSweepConfigViewModel.Instance.Model,
                     OilSource = OilSource.OilSource.Default.OilSourceStatus,
+                    ShakerConfig = ServiceShakerConfigViewModel.Instance.Model,
+                    ShakerControl = ServiceShakerControlViewModel.Instance.Model,
+                    ShakerStatus = ServiceShakerStatusViewModel.Instance.Model,
                 };
             });
-            Context.GetEvent(Topic.START).Subscrip((sender, args) =>
-            {
-
-            });
-            Context.GetEvent(Topic.STOP).Subscrip((sender, args) =>
-            {
-
-            });
-            Context.GetEvent(Topic.VALVEPOWER).Subscrip((sender, args) =>
-            {
-                if(args.Data.Length>0 && args.Data[0] is bool power)
-                {
-
-                }
-            });
-
-            Context.GetEvent(Topic.DROPTABLE).Subscrip((sender, args) =>
-            {
-
-            });
-
-            Context.GetEvent(Topic.RISETABLE).Subscrip((sender, args) =>
-            {
-
-            });
-            Context.GetEvent(Topic.EXIT).Subscrip((sender, args) =>
-            {
-
-            });
-
-            Context.GetEvent(Topic.ZEROCHANGE).Subscrip((sender, args) =>
-            {
-                if(args.Data.Length>0 && args.Data[0] is float zero)
-                {
-
-                }
-            });
+            
         }
         public SQLite.SQLiteConnection DbConnection { get; private set; }
         public static Communication Instance { get; } = new Communication();

+ 23 - 0
Shaker/Data/TestType.cs

@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService.Data
+{
+    /// <summary>
+    /// fpga中的实验类型
+    /// </summary>
+    internal enum TestType:ushort
+    {
+        /// <summary>
+        /// 正弦
+        /// </summary>
+        Sine,
+        /// <summary>
+        /// 随机
+        /// </summary>
+        Random,
+    }
+}

+ 18 - 0
Shaker/OilSource/BitAddressConfig.cs

@@ -0,0 +1,18 @@
+using Shaker.Model;
+
+namespace ShakerService.OilSource
+{
+    public class BitAddressConfig:BaseModel
+    {
+        public string Address = "";
+        public byte BitIndex = 0;
+        public override object Clone()
+        {
+            return new BitAddressConfig()
+            {
+                Address = Address,
+                BitIndex = BitIndex
+            };
+        }
+    }
+}

+ 55 - 2
Shaker/OilSource/OilSource.cs

@@ -3,6 +3,7 @@ using System;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
+using System.Net.NetworkInformation;
 using System.Text;
 using System.Threading.Tasks;
 
@@ -20,6 +21,10 @@ namespace ShakerService.OilSource
         private OilSourceConfig oilSourceConfig = new OilSourceConfig();
         public OilSourceStatusModel OilSourceStatus { get; } = new OilSourceStatusModel();
         public static OilSource Default { get; } = new OilSource();
+        /// <summary>
+        /// PLC断开连接后定时重连PLC计时器
+        /// </summary>
+        private System.Timers.Timer _timer = new System.Timers.Timer(5000);
         public void Init()
         {
             oilSourceConfig = OilSourceConfig.ReadConfig();
@@ -50,12 +55,52 @@ namespace ShakerService.OilSource
                 _IsEnabled = false;
                 return;
             }
-            _PLCConnect.Init(oilSourceConfig.IP, oilSourceConfig.Port);
-            _PLCConnect.StatusChanged += PLCConnect_StatusChanged;
+            try
+            {
+                _PLCConnect.Init(oilSourceConfig.IP, oilSourceConfig.Port);
+                _PLCConnect.Connect();
+                _PLCConnect.StatusChanged += PLCConnect_StatusChanged;
+            }
+            catch
+            {
+                
+            }
+            if(!_PLCConnect.IsConnected)
+            {
+                RepeatConnectPLC();
+            }
+        }
+        private void RepeatConnectPLC()
+        {
+            _timer.Enabled = true;
+            _timer.Start();
         }
         private OilSource()
         {
+            _timer = new System.Timers.Timer(5000);
+            _timer.Elapsed += Timer_Elapsed;
+            _timer.Enabled = false;
+            _timer.AutoReset = true;
+            _timer.Stop();
         }
+
+        private void Timer_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
+        {
+            try
+            {
+                Ping ping = new Ping();
+                if(ping.Send(oilSourceConfig.IP).Status == IPStatus.Success)
+                {
+                    _PLCConnect.Init(oilSourceConfig.IP, oilSourceConfig.Port);
+                    _PLCConnect.Connect();
+                }
+            }
+            catch
+            {
+
+            }
+        }
+
         public bool IsConnected => _PLCConnect == null ? false : _PLCConnect.IsConnected;
         public void Connect()
         {
@@ -71,6 +116,14 @@ namespace ShakerService.OilSource
         {
             _IsEnabled = e;
             StatusChanged?.Invoke(this, e);
+            if(e)
+            {
+                _timer.Stop();
+            }
+            else
+            {
+                ReadOilSourceData();
+            }
         }
 
         public void ReadOilSourceData()

+ 4 - 0
Shaker/OilSource/OilSourceConfig.cs

@@ -42,5 +42,9 @@ namespace ShakerService.OilSource
             config.ErrorAddress.AddRange(Communication.Instance.DbConnection.Query<BitAddressConfig>($"select * from {nameof(ErrorAddress)}") ?? new List<BitAddressConfig>());
             return config;
         }
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
     }
 }

+ 12 - 35
Shaker/Service.RTInit.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using ShakerService.ViewModel;
 
 namespace ShakerService
 {
@@ -11,50 +12,26 @@ namespace ShakerService
         private void RTInit()
         {
             ShakerFpga.Instance.Reset();
-            ShakerFpga.Instance.MaxRiseCount.Value = MainConfig.ShakerConfig.MaxRiseCount;
-            ShakerFpga.Instance.MaxZeroChangedCount.Value = MainConfig.ShakerConfig.MaxZeroChangedCount;
-            ShakerFpga.Instance.MaxSignalCount.Value = MainConfig.ShakerConfig.MaxSignalCount;
-            ShakerFpga.Instance.MaxEmergencyStopCount.Value = MainConfig.ShakerConfig.MaxEmergencyStopCount;
-            ShakerFpga.Instance.MaxStopWindowCount.Value = MainConfig.ShakerConfig.MaxStopWindowCount;
-            ShakerFpga.Instance.MaxFallCount.Value = MainConfig.ShakerConfig.MaxFallCount;
-            ShakerFpga.Instance.InitialLocation.Value = Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerConfig.InitialLocation, MainConfig.ShakerSensitivity.Displacement);
-            ShakerFpga.Instance.SampleRate.Value = MainConfig.ShakerConfig.SampleRate;
-            ShakerFpga.Instance.SampleInterval.Value = 1f / MainConfig.ShakerConfig.SampleRate;
-            ShakerFpga.Instance.RiseInterval.Value = Tools.Tools.CalcInterval(MainConfig.ShakerConfig.MaxRiseCount);
-            ShakerFpga.Instance.ZeroChangedInterval.Value = Tools.Tools.CalcInterval(MainConfig.ShakerConfig.MaxZeroChangedCount);
-            ShakerFpga.Instance.EmergencyStopInterval.Value = Tools.Tools.CalcInterval(MainConfig.ShakerConfig.MaxEmergencyStopCount);
-            ShakerFpga.Instance.FallInterval.Value = Tools.Tools.CalcInterval(MainConfig.ShakerConfig.MaxFallCount);
-            ShakerFpga.Instance.StopWindowInterval.Value = Tools.Tools.CalcInterval(MainConfig.ShakerConfig.MaxStopWindowCount);
-            ShakerFpga.Instance.SignalInterval.Value = Tools.Tools.CalcInterval(MainConfig.ShakerConfig.MaxSignalCount);
-            ShakerFpga.Instance.MaxOutInput.Value = MainConfig.ShakerSecurity.MaxOutInput;
-            ShakerFpga.Instance.WarnOutInput.Value = MainConfig.ShakerSecurity.MaxOutInput * 0.8f;
-            ShakerFpga.Instance.MaxAcceleration.Value = MainConfig.ShakerSecurity.MaxAcceleration;
-            ShakerFpga.Instance.MaxDisplacement.Value = MainConfig.ShakerSecurity.MaxDisplacement;
-            ShakerFpga.Instance.MaxDriver.Value = MainConfig.ShakerSecurity.MaxDriver;
-            ShakerFpga.Instance.ServoValvePolarity.Value = MainConfig.ShakerControl.ValvePolarity == Shaker.Model.Polarity.Positive;
-            ShakerFpga.Instance.AccelerationPolarity.Value = MainConfig.ShakerControl.AccelerationPolarity == Shaker.Model.Polarity.Positive;
-            ShakerFpga.Instance.SelfLoop.Value = MainConfig.ShakerControl.SelfLoop;
-            ShakerFpga.Instance.Debug.Value = MainConfig.ShakerControl.Debug;
             ShakerFpga.Instance.ChangeZero.Value = false;
-            ShakerFpga.Instance.MaxAdjustCount.Value = MainConfig.ShakerConfig.MaxAdjustCount;
-            ShakerFpga.Instance.AdjustInverval.Value = Tools.Tools.CalcInterval(MainConfig.ShakerConfig.MaxAdjustCount);
-            ShakerFpga.Instance.StartCount.Value = MainConfig.ShakerConfig.StartCount;
-            ShakerFpga.Instance.Start.Value = MainConfig.ShakerStatus.Start;
-            ShakerFpga.Instance.LoopRate.Value = MainConfig.ShakerConfig.FPGAClock / MainConfig.ShakerConfig.SampleRate;
+            ServiceShakerConfigViewModel.Instance.SetFpga();
+            ServiceShakerControlViewModel.Instance.SetFpga();
             ShakerFpga.Instance.Run();
             RTInitFifo();
         }
         private void RTInitFifo()
         {
-            ShakerFpga.Instance.Write.HostBufferSize = MainConfig.ShakerConfig.SampleRate * MainConfig.ShakerConfig.ChannelCount;
+            ShakerFpga.Instance.Write.HostBufferSize = (ulong)(ServiceShakerConfigViewModel.Instance.SampleRate * ServiceShakerConfigViewModel.Instance.ChannelCount);
             ShakerFpga.Instance.Write.CommitConfiguration();
             ShakerFpga.Instance.Write.Start();
-            ReadedDataCache = new float[MainConfig.ShakerConfig.ChannelCount*MainConfig.ShakerConfig.SampleRate];
-            DataCache = new float[MainConfig.ShakerConfig.ChannelCount,MainConfig.ShakerConfig.SampleRate];
-            SensitivityValues = Enumerable.Repeat(1f, (int)MainConfig.ShakerConfig.ChannelCount).ToArray();
-            SensitivityValues[0] = MainConfig.ShakerSensitivity.Displacement / 1000f;
+            ShakerFpga.Instance.Read.HostBufferSize = ServiceShakerConfigViewModel.Instance.SampleRate << 1;
+            ShakerFpga.Instance.Read.CommitConfiguration();
+            ShakerFpga.Instance.Read.Start();
+            ReadedDataCache = new float[ServiceShakerConfigViewModel.Instance.ChannelCount*ServiceShakerConfigViewModel.Instance.SampleRate];
+            DataCache = new float[ServiceShakerConfigViewModel.Instance.ChannelCount,ServiceShakerConfigViewModel.Instance.SampleRate];
+            SensitivityValues = Enumerable.Repeat(1f, (int)ServiceShakerConfigViewModel.Instance.ChannelCount).ToArray();
+            SensitivityValues[0] = ServiceShakerConfigViewModel.Instance.DisplacementSensitivity / 1000f;
             SensitivityValues[1] = SensitivityValues[0];
-            SensitivityValues[2] = MainConfig.ShakerSensitivity.Acceleration / 1000f;
+            SensitivityValues[2] = ServiceShakerConfigViewModel.Instance.AccelerationSensitivity / 1000f;
         }
     }
 }

+ 13 - 14
Shaker/Service.cs

@@ -13,12 +13,9 @@ namespace ShakerService
 {
     internal partial class Service
     {
-        private ServiceConfig ServiceConfig;
         public Service()
         {
-
-            ServiceConfig = Tools.ServiceConfigTool.ReadServiceConfig();
-            Communication.Instance.Context.StartService("0,0,0,0",ServiceConfig.Port);
+            Communication.Instance.StartService("0,0,0,0",ServiceConfigViewModel.Instance.Port);
             InitControl();
         }
 
@@ -28,7 +25,10 @@ namespace ShakerService
         private System.Timers.Timer UpAmpttimer = new System.Timers.Timer();
         private System.Timers.Timer ReadConfigTimer = new System.Timers.Timer();
         private AutoResetEvent WaitTriggerLock = new AutoResetEvent(false);
-        private ManualResetEvent m = new ManualResetEvent(true);
+        /// <summary>
+        /// 油源循环锁,当油源与PLC断开连接后自动阻塞轮询线程
+        /// </summary>
+        private ManualResetEvent OilLock = new ManualResetEvent(true);
         private async void DeviceDiscovery()
         {
             System.Net.Sockets.UdpClient udpClient = new System.Net.Sockets.UdpClient(Topic.DISCOVERYPORT);
@@ -46,9 +46,9 @@ namespace ShakerService
                         int index = aa.FindIndex(x => (x.Address.Address & x.IPv4Mask.Address) == (result.RemoteEndPoint.Address.Address & x.IPv4Mask.Address));
                         ResultDeviceModel resultDevice = new ResultDeviceModel();
                         resultDevice.Success = true;
-                        resultDevice.DeviceInfoModel.Port = ServiceConfig.Port;
-                        resultDevice.DeviceInfoModel.SN = ServiceConfig.SN;
-                        resultDevice.DeviceInfoModel.Name = ServiceConfig.Name;
+                        resultDevice.DeviceInfoModel.Port = ServiceConfigViewModel.Instance.Port;
+                        resultDevice.DeviceInfoModel.SN = ServiceConfigViewModel.Instance.SN;
+                        resultDevice.DeviceInfoModel.Name = ServiceConfigViewModel.Instance.Name;
                         if(index ==-1)
                         {
                             resultDevice.DeviceInfoModel.IP = "127.0.0.1";
@@ -71,11 +71,11 @@ namespace ShakerService
             {
                 if(args)
                 {
-                    m.Reset();
+                    OilLock.Reset();
                 }
                 else
                 {
-                    m.Set();
+                    OilLock.Set();
                 }
             };
             return;
@@ -92,7 +92,7 @@ namespace ShakerService
             OilSource.OilSource.Default.Connect();
             if(!OilSource.OilSource.Default.IsConnected)
             {
-                m.Reset();
+                OilLock.Reset();
             }
             UpAmpttimer = new System.Timers.Timer();
             UpAmpttimer.AutoReset = true;
@@ -120,7 +120,7 @@ namespace ShakerService
         {
             while(!tokenSource.IsCancellationRequested)
             {
-                m.WaitOne();
+                OilLock.WaitOne();
                 OilSource.OilSource.Default.ReadOilSourceData();
                 await Task.Delay(10);
             }
@@ -149,7 +149,6 @@ namespace ShakerService
                 while(!tokenSource.IsCancellationRequested)
                 {
                     ReadFifo();
-                    if (!MainConfig.ShakerStatus.Start) break;
                 }
                 UpAmpttimer.Stop();
                 ReadConfigTimer.Stop();
@@ -161,7 +160,7 @@ namespace ShakerService
         }
         private void Stop()
         {
-            MainConfig.ShakerStatus.Start = false;
+            tokenSource.Cancel();
         }
 
 

+ 36 - 3
Shaker/ServiceConfig.cs

@@ -1,15 +1,48 @@
-using System;
+using Shaker.Model;
+using ShakerService.ViewModel;
+using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Net.Http.Headers;
 using System.Text;
 using System.Threading.Tasks;
 
 namespace ShakerService
 {
-    public class ServiceConfig
+    internal class ServiceConfigModel : BaseModel
     {
         public string Name = "振动台";
         public string SN = "SN123456";
-        public int Port { get; set; } = 5555;
+        public int Port = 5555;
+        public int AnalogCount = 11;
+        public int ValveCount = 4;
+        public int AccelerationCount = 2;
+        public override object Clone()
+        {
+            return this.CloneBase();
+        }
+    }
+    internal class ServiceConfigViewModel:BaseServiceViewModel<ServiceConfigModel>
+    {
+        public string Name => Model.Name;
+        public string SN => Model.SN;
+        public int Port => Model.Port;
+        public int AnalogCount => Model.AnalogCount;
+        public int ValveCount => Model.ValveCount;
+        public int AccelerationCount => Model.AccelerationCount;
+
+        private ServiceConfigViewModel()
+        {
+            Communication.Instance.DbConnection.CreateTable<ServiceConfigModel>();
+            var config = Communication.Instance.DbConnection.Query<ServiceConfigModel>($"select * from {nameof(ServiceConfigModel)}")?.FirstOrDefault() ?? new ServiceConfigModel();
+            UpModel(config);
+            Communication.Instance.DbConnection.DeleteAll<ServiceConfigModel>();
+            Communication.Instance.DbConnection.Insert(config, nameof(ServiceConfigModel));
+        }
+        static ServiceConfigViewModel()
+        {
+
+        }
+        public static ServiceConfigViewModel Instance { get; } = new ServiceConfigViewModel();
     }
 }

Різницю між файлами не показано, бо вона завелика
+ 412 - 332
Shaker/ShakerFpga.cs


+ 11 - 9
Shaker/ShakerService.CalcDisplacement.cs

@@ -1,4 +1,6 @@
-using System;
+using Shaker.Model.Tools;
+using ShakerService.ViewModel;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
@@ -14,19 +16,19 @@ namespace ShakerService
         private float _RA_k = 0;
         private void CalcDisplacement()
         {
-            if (MainConfig.ShakerControl.ControlItems.Count == 0) return;
+            if (ViewModel.ServiceShakerControlViewModel.Instance.SweepControlItems.Count == 0) return;
             _CycleCount++;
             float freq = ShakerFpga.Instance.CurrentFrequency.Value;
-            var config = this.MainConfig.ShakerControl.ControlItems.FirstOrDefault(x => freq >= x.Frequency);
-            config ??= this.MainConfig.ShakerControl.ControlItems.Last();
+            var config = ViewModel.ServiceShakerControlViewModel.Instance.SweepControlItems.FirstOrDefault(x => freq >= x.Frequency)!.Model;
+            config ??= ViewModel.ServiceShakerControlViewModel.Instance.SweepControlItems.Last().Model;
             if (config.UpDateInvert<=1 || _CycleCount % config.UpDateInvert ==0)
             {
-                int freqindex = FindFreqIndex(MainConfig.SweepFreqConfig.FreqControls, freq);
-                var accv = CalcAccAmpt(MainConfig.SweepFreqConfig.AccSlope, MainConfig.SweepFreqConfig.AccOffset, freqindex, MathF.Log(freq));
+                int freqindex = ViewModel.ServiceSweepConfigViewModel.Instance.Model.FindFrequencyIndex(freq);
+                var accv = Tools.Tools.QuantitiesToVoltage(ViewModel.ServiceSweepConfigViewModel.Instance.Model.CalcAmpt(freq),ViewModel.ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
                 if ((Shaker.Model.SweepStep)ShakerFpga.Instance.SweepStep.Value == Shaker.Model.SweepStep.SignalGen)
                 {
                     CalcSynthesisAmplitude(freq);
-                    float ampt = MainConfig.ShakerStatus.SynthesisAmplitude;
+                    float ampt = ServiceSweepConfigViewModel.Instance.SweepData.CurrentAcceleration;
                     CalcNextDisp(freq, accv, ampt, _RA_k, config, ref _D_k);
                     ShakerFpga.Instance.GivenDisplacement.Value = _D_k;
                 }
@@ -39,8 +41,8 @@ namespace ShakerService
         }
         private void CalcNextDisp(float freq,float nextaccv,float a_k,float ra_k_1,Shaker.Model.SweepControlItemModel item,ref float d_k_1)
         {
-            float mincorrect = freq >= MainConfig.SweepFreqConfig.CrossoverPoint ? MainConfig.SweepFreqConfig.HigthFrequencyMinCorrect : MainConfig.SweepFreqConfig.LowFrequencyMinCorrect;
-            float maxcorrect = freq >= MainConfig.SweepFreqConfig.CrossoverPoint ? MainConfig.SweepFreqConfig.HigthFrequencyMaxCorrect : MainConfig.SweepFreqConfig.LowFrequencyMaxCorrect;
+            float mincorrect = freq >= ServiceSweepConfigViewModel.Instance.CrossoverPoint ? ServiceSweepConfigViewModel.Instance.HigthFrequencyMinCorrect : ServiceSweepConfigViewModel.Instance.LowFrequencyMinCorrect;
+            float maxcorrect = freq >= ServiceSweepConfigViewModel.Instance.CrossoverPoint ? ServiceSweepConfigViewModel.Instance.HigthFrequencyMaxCorrect : ServiceSweepConfigViewModel.Instance.LowFrequencyMaxCorrect;
             var v1= MathF.Pow(ra_k_1 / a_k, item.ExponentialCoefficients);
             var factor = d_k_1 / nextaccv;
             var changeratio = factor >= 1 ? ((item.CompressionRate + 1) / ((Math.Clamp(factor, 0.1f, 10f)) + item.CompressionRate)) : (((1 / (Math.Clamp(factor, 0.1f, 1))) + item.CompressionRate) / (item.CompressionRate + 1));

+ 20 - 15
Shaker/ShakerService.Control.cs

@@ -1,4 +1,5 @@
 using Shaker.Model;
+using ShakerService.ViewModel;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -27,16 +28,20 @@ namespace ShakerService
         [PropertyInit]
         private void SyncConfig()
         {
-            tcpBus.GetEvent<MainWindowModel>(Shaker.Model.Topic.SYNCCONFIG).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent<AllConfig>(Shaker.Model.Topic.SYNCCONFIG).Subscrip((_, _) =>
             {
-                return MainConfig;
+                return new AllConfig()
+                {
+                    SweepConfig = ServiceSweepConfigViewModel.Instance.Model,
+                    OilSource = OilSource.OilSource.Default.OilSourceStatus,
+                };
             });
         }
 
         [PropertyInit]
         private void InitStartControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.START).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.START).Subscrip((_, _) =>
             {
                 StartTrigger();
             });
@@ -44,7 +49,7 @@ namespace ShakerService
         [PropertyInit]
         private void InitRiseTableControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.RISETABLE).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.RISETABLE).Subscrip((_, _) =>
             {
                 RiseTable();
             });
@@ -52,7 +57,7 @@ namespace ShakerService
         [PropertyInit]
         private void InitZeroChangeControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.ZEROCHANGE).Subscrip((_, e) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.ZEROCHANGE).Subscrip((_, e) =>
             {
                 ZeroChange((float)e.Data[0]);
             });
@@ -60,7 +65,7 @@ namespace ShakerService
         [PropertyInit]
         private void InitDropTableControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.DROPTABLE).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.DROPTABLE).Subscrip((_, _) =>
             {
                 DropTable();
             });
@@ -68,7 +73,7 @@ namespace ShakerService
         [PropertyInit]
         private void InitStopSignalGenControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.STOPSIGNALGEN).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.STOPSIGNALGEN).Subscrip((_, _) =>
             {
                 StopSignalGen();
             });
@@ -76,7 +81,7 @@ namespace ShakerService
         [PropertyInit]
         private void InitValvePowerControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.STOPSIGNALGEN).Subscrip((_, e) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.STOPSIGNALGEN).Subscrip((_, e) =>
             {
                 ValvePower((bool)e.Data[0]);
             });
@@ -84,15 +89,15 @@ namespace ShakerService
         [PropertyInit]
         private void InitStopControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.STOP).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.STOP).Subscrip((_, _) =>
             {
-                MainConfig.ShakerStatus.Start = false;
+                Stop();
             });
         }
         [PropertyInit]
         private void InitStartGen()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.STARTSIGNALGEN).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.STARTSIGNALGEN).Subscrip((_, _) =>
             {
                 StartGen();
             });
@@ -100,7 +105,7 @@ namespace ShakerService
         [PropertyInit]
         private void InitResetErrorControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.RESETERROR).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.RESETERROR).Subscrip((_, _) =>
             {
                 ResetError();
             });
@@ -108,14 +113,14 @@ namespace ShakerService
         [PropertyInit]
         private void InitExitControl()
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.EXIT).Subscrip((_, _) =>
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.EXIT).Subscrip((_, _) =>
             {
-                MainConfig.ShakerStatus.Start = false;
+                Stop();
             });
         }
         private void SendData(float[,] data)
         {
-            tcpBus.GetEvent(Shaker.Model.Topic.DATA).Publish(this, null, data);
+            Communication.Instance.Context.GetEvent(Shaker.Model.Topic.DATA).Publish(this, null, data);
         }
     }
 }

+ 35 - 33
Shaker/ShakerService.ReadConfig.cs

@@ -1,4 +1,6 @@
-using System;
+using Shaker.Model.Tools;
+using ShakerService.ViewModel;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -10,23 +12,19 @@ namespace ShakerService
     {
         private void ReadConfig()
         {
-            MainConfig.ShakerStatus.CurrentFrequency = ShakerFpga.Instance.CurrentFrequency.Value;
-            MainConfig.ShakerStatus.RTStatus = (Shaker.Model.RTStatus)ShakerFpga.Instance.RTStatus.Value;
-            MainConfig.ShakerStatus.IsTableRised = ShakerFpga.Instance.Rised.Value;
-            MainConfig.ShakerStatus.RiseCount = ShakerFpga.Instance.RiseIndex.Value;
-            MainConfig.ShakerStatus.IsTableDroped = ShakerFpga.Instance.Rised.Value;
-            MainConfig.ShakerStatus.IsFaultRelease = ShakerFpga.Instance.Troubleshooting.Value;
-            MainConfig.ShakerStatus.SignalGenStopCount = ShakerFpga.Instance.StopWindowIndex.Value;
-            MainConfig.ShakerStatus.EmergencyStopCount = ShakerFpga.Instance.EmergencyStopIndex.Value;
-            MainConfig.ShakerStatus.IsSignalGenStoped = ShakerFpga.Instance.SignalFinish.Value;
-            MainConfig.ShakerStatus.ZeroChangedCount = ShakerFpga.Instance.ZeroChangedIndex.Value;
-            MainConfig.ShakerStatus.WarnCode = ShakerFpga.Instance.WarnCode.Value;
-            MainConfig.ShakerStatus.ErrorCode = ShakerFpga.Instance.ErrorCode.Value;
-            MainConfig.ShakerStatus.ClosedValve = ShakerFpga.Instance.ErrorCloseVavle.Value;
-            MainConfig.ShakerStatus.DropCount = ShakerFpga.Instance.FallIndex.Value;
-            MainConfig.ShakerStatus.SweepIndex = ShakerFpga.Instance.SweepIndex.Value;
-            MainConfig.ShakerStatus.SignalGenTime = ShakerFpga.Instance.FixedFrequencyTime.Value;
-            MainConfig.ShakerStatus.CurrentDirection = ShakerFpga.Instance.CurrentSweepDirection.Value?  Shaker.Model.SweepDirection.Down: Shaker.Model.SweepDirection.Up;
+            switch(ServiceShakerControlViewModel.Instance.PageType)
+            {
+                case Shaker.Models.MainPageType.RandomPage:
+                    break;
+                case Shaker.Models.MainPageType.OutSignal:
+                    break;
+                case Shaker.Models.MainPageType.SinePage:
+                    ServiceSweepConfigViewModel.Instance.SweepData.ReadFpgaData();
+                    break;
+                case Shaker.Models.MainPageType.StartPage:
+                    break;
+            }
+            ServiceSweepConfigViewModel.Instance.SweepData.ReadFpgaData();
         }
 
         private void CalcSynthesisAmplitude(float currentfreq)
@@ -42,40 +40,44 @@ namespace ShakerService
             float fftdisp =DispToAcc(MathF.Sqrt(real[1] * real[1] + img[1] * img[1])/(real.Length/2),currentfreq);
             float identifyacc = ShakerFpga.Instance.IdentifyAcceleration.Value;
             float identifydisp = DispToAcc(ShakerFpga.Instance.IdentifyDisplacement.Value,currentfreq);
-            if(currentfreq<= MainConfig.AmptIdentifyConfig.LowFreq)
+            if(currentfreq<= ServiceSweepConfigViewModel.Instance.LowFreq)
             {
                 ampt = fftdisp;
             }
-            else if(currentfreq<=MainConfig.AmptIdentifyConfig.HigthFreq)
+            else if(currentfreq<= ServiceSweepConfigViewModel.Instance.HighFreq)
             {
-                float disp = MainConfig.ShakerControl.SelfLoop ? identifydisp : identifyacc;
-                float v1 = (MainConfig.AmptIdentifyConfig.HigthFreq - currentfreq) / (MainConfig.AmptIdentifyConfig.HigthFreq - MainConfig.AmptIdentifyConfig.LowFreq) * fftdisp;
-                float v2 = (MainConfig.AmptIdentifyConfig.HigthFreq - MainConfig.AmptIdentifyConfig.LowFreq) / (currentfreq - MainConfig.AmptIdentifyConfig.LowFreq) * disp;
+                float disp = ServiceShakerControlViewModel.Instance.SelfLoop ? identifydisp : identifyacc;
+                float v1 = (ServiceSweepConfigViewModel.Instance.HighFreq - currentfreq) / (ServiceSweepConfigViewModel.Instance.HighFreq - ServiceSweepConfigViewModel.Instance.LowFreq) * fftdisp;
+                float v2 = (ServiceSweepConfigViewModel.Instance.HighFreq - ServiceSweepConfigViewModel.Instance.LowFreq) / (currentfreq - ServiceSweepConfigViewModel.Instance.LowFreq) * disp;
                 ampt = v1 + v2;
             }
             else
             {
-                ampt = MainConfig.ShakerControl.SelfLoop ? identifydisp : identifyacc;
+                ampt = ServiceShakerControlViewModel.Instance.SelfLoop ? identifydisp : identifyacc;
             }
-            MainConfig.ShakerStatus.SynthesisAmplitude = ampt;
+            ServiceSweepConfigViewModel.Instance.SweepData.CurrentAcceleration = ampt;
             ShakerFpga.Instance.SynthesisAmpt.Value = ampt;
         }
 
         private float DispToAcc(float disp,float currentFreq)
         {
-            return disp * 1000 / MainConfig.ShakerSensitivity.Displacement * MathF.Pow((currentFreq * 2 * 3.14f), 2) / 9800 * (MainConfig.ShakerSensitivity.Acceleration / 1000);
+            return disp * 1000 / ServiceShakerConfigViewModel.Instance.DisplacementSensitivity * MathF.Pow((currentFreq * 2 * MathF.PI), 2) / 9800 * (ServiceShakerConfigViewModel.Instance.AccelerationSensitivity / 1000);
         }
         
 
         private void CalcDowntime()
         {
-            float currentfreq = MainConfig.ShakerStatus.CurrentFrequency;
-            int freqindex = FindFreqIndex(MainConfig.SweepFreqConfig.FreqControls, currentfreq);
-            float lnfreq = MathF.Log(currentfreq);
-            ShakerFpga.Instance.LowerStop.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.LowerDowntimeSlope, MainConfig.SweepFreqConfig.LowerDowntimeOffset, freqindex, lnfreq);
-            ShakerFpga.Instance.LowerWarn.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.LowerWarnSlope, MainConfig.SweepFreqConfig.LowerWarnOffset, freqindex, lnfreq);
-            ShakerFpga.Instance.UpperStop.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.UpperDowntimeSlope, MainConfig.SweepFreqConfig.UpperDowntimeOffset, freqindex, lnfreq);
-            ShakerFpga.Instance.UpperWarn.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.UpperWarnSlope, MainConfig.SweepFreqConfig.UpperWarnOffset, freqindex, lnfreq);
+            float currentfreq = ServiceSweepConfigViewModel.Instance.SweepData.CurrentFrequency;
+            float value = 0;
+            float upstop = 0;
+            float upwarn = 0;
+            float downstop = 0;
+            float downwarn = 0;
+            ServiceSweepConfigViewModel.Instance.Model.CalcAmpt(currentfreq, ref value, ref upstop, ref upwarn, ref downstop, ref downwarn);
+            ShakerFpga.Instance.LowerStop.Value = Tools.Tools.QuantitiesToVoltage(downstop, ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
+            ShakerFpga.Instance.LowerWarn.Value = Tools.Tools.QuantitiesToVoltage(downwarn, ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
+            ShakerFpga.Instance.UpperStop.Value = Tools.Tools.QuantitiesToVoltage(upstop, ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
+            ShakerFpga.Instance.UpperWarn.Value = Tools.Tools.QuantitiesToVoltage(upwarn, ServiceShakerConfigViewModel.Instance.AccelerationSensitivity);
         }
         /// <summary>
         /// 差值加速度电压

+ 5 - 5
Shaker/ShakerService.ReadFifo.cs

@@ -1,4 +1,5 @@
-using System;
+using ShakerService.ViewModel;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
@@ -18,17 +19,16 @@ namespace ShakerService
             {
                 if(ShakerFpga.Instance.Write.ElementsRemaining>=ReadedDataCache.Length)
                 {
-                    ShakerFpga.Instance.Write.Read(ref ReadedDataCache[0], (uint)ReadedDataCache.Length, 0, ref ReadDataLength); Tools.Tools.ArrayTranspose(ref ReadedDataCache[0], ref DataCache[0, 0], (int)MainConfig.ShakerConfig.SampleRate, (int)MainConfig.ShakerConfig.ChannelCount);
-                    for (int i = 0; i < MainConfig.ShakerConfig.ChannelCount; i++)
+                    ShakerFpga.Instance.Write.Read(ref ReadedDataCache[0], (uint)ReadedDataCache.Length, 0, ref ReadDataLength); Tools.Tools.ArrayTranspose(ref ReadedDataCache[0], ref DataCache[0, 0], (int)ServiceShakerConfigViewModel.Instance.SampleRate, (int)ServiceShakerConfigViewModel.Instance.ChannelCount);
+                    for (int i = 0; i <ServiceShakerConfigViewModel.Instance.ChannelCount; i++)
                     {
                         if (SensitivityValues[i] == 1) continue;
-                        Calc.Multiply.Multiply(ref DataCache[i, 0], SensitivityValues[i], MainConfig.ShakerConfig.SampleRate);
+                        Calc.Multiply.Multiply(ref DataCache[i, 0], SensitivityValues[i], ServiceShakerConfigViewModel.Instance.SampleRate);
                     }
                     SendData(DataCache);
                     break;
                 }
                 await Task.Delay(10);
-                if (!MainConfig.ShakerStatus.Start) break;
             }
         }
     }

+ 0 - 1
Shaker/ShakerService.WaitTrigger.cs

@@ -11,7 +11,6 @@ namespace ShakerService
         private void StartTrigger()
         {
             WriteConfig();
-            MainConfig.ShakerStatus.Start = true;
             WaitTriggerLock.Set();
         }
     }

+ 28 - 79
Shaker/ShakerService.WriteConfig.cs

@@ -1,4 +1,6 @@
-using System;
+using Microsoft.VisualBasic;
+using ShakerService.ViewModel;
+using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Linq.Expressions;
@@ -11,38 +13,6 @@ namespace ShakerService
     {
         private void WriteConfig()
         {
-            ShakerFpga.Instance.MaxDisplacement.Value = Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerSecurity.MaxDisplacement, MainConfig.ShakerSensitivity.Displacement);
-            ShakerFpga.Instance.MaxAcceleration.Value = Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerSecurity.MaxAcceleration, MainConfig.ShakerSensitivity.Acceleration);
-            ShakerFpga.Instance.MaxDriver.Value = MainConfig.ShakerSecurity.MaxDriver;
-            ShakerFpga.Instance.MaxOutInput.Value = MainConfig.ShakerSecurity.MaxOutInput;
-            ShakerFpga.Instance.WarnDisplacement.Value = Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerSecurity.MaxDisplacement * 0.5f, MainConfig.ShakerSensitivity.Displacement);
-            ShakerFpga.Instance.WarnAcceleration.Value = Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerSecurity.MaxAcceleration, MainConfig.ShakerSensitivity.Acceleration);
-            ShakerFpga.Instance.WarnOutInput.Value = MainConfig.ShakerSecurity.MaxOutInput * 0.8f;
-            ShakerFpga.Instance.DisplacementP.Value = MainConfig.ShakerControl.DisplacementP;
-            ShakerFpga.Instance.DisplacementI.Value = MainConfig.ShakerControl.DisplacementI;
-            ShakerFpga.Instance.FlutterFrequency.Value = MainConfig.ShakerControl.FlutterFrequency;
-            ShakerFpga.Instance.FlutterAmpt.Value = MainConfig.ShakerControl.FlutterAmpt;
-            ShakerFpga.Instance.ServoValvePolarity.Value = MainConfig.ShakerControl.ValvePolarity == Shaker.Model.Polarity.Positive;
-            ShakerFpga.Instance.ValveBias.Value = MainConfig.ShakerControl.ServoValveBias;
-            ShakerFpga.Instance.MaxDisplacementIntegral.Value = MainConfig.ShakerControl.MaxDisplacementIntegral;
-            ShakerFpga.Instance.DisplacementBias.Value = MainConfig.ShakerControl.DisplacementBias;
-            ShakerFpga.Instance.MaxJitterAcceleration.Value =Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerSecurity.MaxJitterAcceleration,MainConfig.ShakerSensitivity.Acceleration);
-            ShakerFpga.Instance.MaxJitterDisplacement.Value = Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerSecurity.MaxJitterDisplacement, MainConfig.ShakerSensitivity.Displacement);
-            ShakerFpga.Instance.OilStopped.Value = MainConfig.ShakerControl.OilStopped;
-            ShakerFpga.Instance.DisplacementOpenLoop.Value = MainConfig.ShakerControl.DisplacementOpenLoop;
-            ShakerFpga.Instance.OpenLoopDisplacement.Value = MainConfig.ShakerControl.OpenLoopDisplacement;
-            ShakerFpga.Instance.OutSignal.Value = MainConfig.ShakerControl.OutSignal;
-            ShakerFpga.Instance.OutSignalGain.Value = MainConfig.ShakerControl.OutSignalGain;
-            ShakerFpga.Instance.SelfLoop.Value = MainConfig.ShakerControl.SelfLoop;
-            ShakerFpga.Instance.AccelerationPolarity.Value = MainConfig.ShakerControl.AccelerationPolarity == Shaker.Model.Polarity.Positive;
-            ShakerFpga.Instance.InitialLocation.Value = Tools.Tools.QuantitiesToVoltage(MainConfig.ShakerConfig.InitialLocation, MainConfig.ShakerSensitivity.Displacement);
-            CalcSynthesisAmplitude(MainConfig.ShakerStatus.CurrentFrequency);
-            int index = FindFreqIndex(MainConfig.SweepFreqConfig.FreqControls, MainConfig.ShakerStatus.CurrentFrequency);
-            float lnfreq = MathF.Log(MainConfig.ShakerStatus.CurrentFrequency);
-            ShakerFpga.Instance.UpperWarn.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.UpperWarnSlope, MainConfig.SweepFreqConfig.UpperWarnOffset, index,lnfreq);
-            ShakerFpga.Instance.UpperStop.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.UpperDowntimeSlope, MainConfig.SweepFreqConfig.UpperDowntimeOffset, index, lnfreq);
-            ShakerFpga.Instance.LowerWarn.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.LowerWarnSlope, MainConfig.SweepFreqConfig.LowerWarnOffset, index, lnfreq);
-            ShakerFpga.Instance.LowerStop.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.LowerDowntimeSlope, MainConfig.SweepFreqConfig.LowerDowntimeOffset, index, lnfreq);
 
         }
 
@@ -60,52 +30,31 @@ namespace ShakerService
         }
         public void StartGen()
         {
-            float startfreq = MainConfig.SweepFreqConfig.SignalType == Shaker.Model.SignalType.Fixed ? MainConfig.SweepFreqConfig.MinFreq : (MainConfig.SweepFreqConfig.SweepDirection == Shaker.Model.SweepDirection.Down ? MainConfig.SweepFreqConfig.MaxFreq : MainConfig.SweepFreqConfig.MinFreq);
-            float lnfre = MathF.Log(startfreq);
-            int freqindex = FindFreqIndex(MainConfig.SweepFreqConfig.FreqControls, startfreq);
-            float endaccvolage = CalcAccAmpt(MainConfig.SweepFreqConfig.AccSlope, MainConfig.SweepFreqConfig.AccOffset, freqindex, lnfre);
-            float startdisp = AccelerationToDisplacement(endaccvolage * MainConfig.SweepFreqConfig.SweepStartLevel, startfreq);
-            ShakerFpga.Instance.InitialDisplacement.Value = startdisp;
-            ShakerFpga.Instance.TargetAcceleration.Value = endaccvolage * MainConfig.SweepFreqConfig.SweepLevelGain;
-            ShakerFpga.Instance.MinFrequency.Value = startfreq;
-            ShakerFpga.Instance.MaxFrequency.Value = MainConfig.SweepFreqConfig.SweepType == Shaker.Model.SweepType.Linear ? MainConfig.SweepFreqConfig.MinFreq : MainConfig.SweepFreqConfig.MaxFreq;
-            ShakerFpga.Instance.SweepCount.Value = MainConfig.SweepFreqConfig.SweepCount;
-            ShakerFpga.Instance.SweepSpeed.Value = MainConfig.SweepFreqConfig.SweepSpeed;
-            ShakerFpga.Instance.SweepDown.Value = MainConfig.SweepFreqConfig.SweepDirection == Shaker.Model.SweepDirection.Down;
-            ShakerFpga.Instance.TargetDisplacement.Value = AccelerationToDisplacement(endaccvolage, startfreq);
-            ShakerFpga.Instance.Linear.Value = MainConfig.SweepFreqConfig.SweepType == Shaker.Model.SweepType.Linear;
-            ShakerFpga.Instance.MaxFixedFrequencyTime.Value = (ulong)(MainConfig.SweepFreqConfig.SweepTime * MainConfig.ShakerConfig.SampleRate * (MainConfig.SweepFreqConfig.SignalType == Shaker.Model.SignalType.Fixed ? 1 : MainConfig.SweepFreqConfig.SweepCount));
-            ShakerFpga.Instance.UpperStop.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.UpperDowntimeSlope, MainConfig.SweepFreqConfig.UpperDowntimeOffset, freqindex, lnfre);
-            ShakerFpga.Instance.UpperWarn.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.UpperWarnSlope, MainConfig.SweepFreqConfig.UpperWarnOffset, freqindex, lnfre);
-            ShakerFpga.Instance.LowerStop.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.LowerDowntimeSlope, MainConfig.SweepFreqConfig.LowerDowntimeOffset, freqindex, lnfre);
-            ShakerFpga.Instance.LowerWarn.Value = CalcAccAmpt(MainConfig.SweepFreqConfig.LowerWarnSlope, MainConfig.SweepFreqConfig.LowerWarnOffset, freqindex, lnfre);
-            ShakerFpga.Instance.SignalStop.Value = false;
-            ShakerFpga.Instance.SignalStart.Value = true;
-        }
-        /// <summary>
-        /// 位移电压转加速度电压
-        /// </summary>
-        /// <param name="displacementV">位移电压值</param>
-        /// <param name="freq">当前频率</param>
-        /// <returns>加速度电压</returns>
-        private float DisplacementToAcceleration(float displacementV,float freq)
-        {
-           var disq= Tools.Tools.VoltageToQuantities(displacementV, MainConfig.ShakerSensitivity.Displacement);
-            var accq = disq * MathF.Pow(2 * 3.14f * freq, 2) / 9800;
-            return Tools.Tools.QuantitiesToVoltage(accq, MainConfig.ShakerSensitivity.Acceleration);
-        }
-        /// <summary>
-        /// 加速度电压转位移电压
-        /// </summary>
-        /// <param name="accelerationV">加速度电压</param>
-        /// <param name="freq">当前频率</param>
-        /// <returns>位移电压</returns>
-        private float AccelerationToDisplacement(float accelerationV,float freq)
-        {
-            var accq = Tools.Tools.VoltageToQuantities(accelerationV, MainConfig.ShakerSensitivity.Acceleration);
-            var disq = accq * 9800 / MathF.Pow(2 * 3.14f * freq, 2);
-            return Tools.Tools.QuantitiesToVoltage(disq, MainConfig.ShakerSensitivity.Displacement);
+            switch(ServiceShakerControlViewModel.Instance.PageType)
+            {
+                case Shaker.Models.MainPageType.StartPage:
+
+                    break;
+                case Shaker.Models.MainPageType.RandomPage:
+                    ShakerFpga.Instance.OutSignal.Value = false;
+                    ShakerFpga.Instance.TestType.Value = (ushort)Data.TestType.Random;
+                    break;
+                case Shaker.Models.MainPageType.OutSignal:
+                    ShakerFpga.Instance.OutSignal.Value = true; 
+                    ShakerFpga.Instance.SignalStop.Value = false;
+                    ShakerFpga.Instance.SignalStart.Value = true;
+                    break;
+                case Shaker.Models.MainPageType.SinePage:
+                    ShakerFpga.Instance.OutSignal.Value = false;
+                    ServiceSweepConfigViewModel.Instance.SetFpga();
+                    ShakerFpga.Instance.TestType.Value = (ushort)Data.TestType.Sine;
+                    ShakerFpga.Instance.SignalStop.Value = false;
+                    ShakerFpga.Instance.SignalStart.Value = true;
+                    break;
+            }
+            
         }
+
         private void StopSignalGen()
         {
             ShakerFpga.Instance.SignalStart.Value = false;
@@ -114,7 +63,7 @@ namespace ShakerService
         private void ZeroChange(float currentZero)
         {
             ShakerFpga.Instance.LastZeroDifference.Value = ShakerFpga.Instance.Location.Value;
-            ShakerFpga.Instance.GivenLocation.Value = Tools.Tools.QuantitiesToVoltage(currentZero, MainConfig.ShakerSensitivity.Displacement);
+            ShakerFpga.Instance.GivenLocation.Value = Tools.Tools.QuantitiesToVoltage(currentZero, ServiceShakerConfigViewModel.Instance.DisplacementSensitivity);
             ShakerFpga.Instance.ChangeZero.Value = true;
         }
         private void ValvePower(bool power)

+ 0 - 64
Shaker/Tools/ServiceConfigTool.cs

@@ -14,21 +14,6 @@ namespace ShakerService.Tools
     {
         private static MessagePackSerializerOptions options = TypelessContractlessStandardResolver.Options.WithOmitAssemblyVersion(true);
 
-        private static string DBPath = System.AppDomain.CurrentDomain.BaseDirectory + "Shaker.cfg";
-        private static string Path = System.AppDomain.CurrentDomain.BaseDirectory + "Service.cfg";
-        public static void SaveShakerConfig(Shaker.Model.MainWindowModel config)
-        {
-            if (System.IO.File.Exists(DBPath)) System.IO.File.Delete(DBPath);
-            try
-            {
-                config ??= new Shaker.Model.MainWindowModel();
-                System.IO.File.WriteAllText(DBPath,Newtonsoft.Json.JsonConvert.SerializeObject(config, Newtonsoft.Json.Formatting.Indented));
-            }
-            catch
-            {
-
-            }
-        }
         public static byte[] GetBytes<T>(this T value)
         {
             return MessagePack.MessagePackSerializer.Serialize(value,options);
@@ -37,54 +22,5 @@ namespace ShakerService.Tools
         {
             return MessagePackSerializer.Deserialize<T>(data,options);
         }
-        public static Shaker.Model.MainWindowModel ReadShakerConfig()
-        {
-            Shaker.Model.MainWindowModel config = new Shaker.Model.MainWindowModel();
-            if (System.IO.File.Exists(DBPath))
-            {
-                try
-                {
-                    config = Newtonsoft.Json.JsonConvert.DeserializeObject<Shaker.Model.MainWindowModel>(System.IO.File.ReadAllText(DBPath));
-                }
-                catch
-                {
-
-                }
-            }
-            config ??= new Shaker.Model.MainWindowModel();
-            SaveShakerConfig(config);
-            return config;
-        }
-        public static void SaveServiceConfig(ServiceConfig config)
-        {
-            if (System.IO.File.Exists(Path)) System.IO.File.Delete(Path);
-            try
-            {
-                config ??= new ServiceConfig();
-                System.IO.File.WriteAllText(Path, Newtonsoft.Json.JsonConvert.SerializeObject(config, Newtonsoft.Json.Formatting.Indented));
-            }
-            catch
-            {
-
-            }
-        }
-        public static ServiceConfig ReadServiceConfig()
-        {
-            ServiceConfig config = new ServiceConfig();
-            if (System.IO.File.Exists(Path))
-            {
-                try
-                {
-                    config = Newtonsoft.Json.JsonConvert.DeserializeObject<ServiceConfig>(System.IO.File.ReadAllText(Path));
-                }
-                catch
-                {
-
-                }
-            }
-            config ??= new ServiceConfig();
-            SaveServiceConfig(config);
-            return config;
-        }
     }
 }

+ 15 - 1
Shaker/ViewModel/BaseServiceViewModel.cs

@@ -10,6 +10,7 @@ namespace ShakerService.ViewModel
 {
     internal class BaseServiceViewModel<TModel> : IServiceViewModel<TModel> where TModel : IModel
     {
+        private protected bool _NeedSendData = false;
         public BaseServiceViewModel()
         {
             if(typeof(TModel).IsAnsiClass && !typeof(TModel).IsAbstract)
@@ -24,15 +25,28 @@ namespace ShakerService.ViewModel
         [AllowNull]
         public TModel Model { get; private set; }
 
+        public virtual void SetFpga()
+        {
+
+        }
         public virtual void UpModel(TModel model)
         {
             Model = model;
         }
+        private protected void SetProperty<T>(ref T field, T newValue)
+        {
+            if (EqualityComparer<T>.Default.Equals(field, newValue))
+            {
+                return ;
+            }
+            field = newValue;
+            _NeedSendData = true;
+        }
 
         private protected virtual void SaveData()
         {
             Communication.Instance.DbConnection.DeleteAll<TModel>();
-            Communication.Instance.DbConnection.InsertOrReplace(Model);
+            Communication.Instance.DbConnection.Insert(Model);
         }
         public virtual void SendData()
         {

+ 18 - 0
Shaker/ViewModel/SerivceValveConfigItemViewModel.cs

@@ -0,0 +1,18 @@
+using Shaker.Model;
+
+namespace ShakerService.ViewModel
+{
+    internal sealed class  SerivceValveConfigItemViewModel:BaseServiceViewModel<ValveConfigItemModel>
+    {
+        public SerivceValveConfigItemViewModel():base()
+        {
+
+        }
+        public SerivceValveConfigItemViewModel(ValveConfigItemModel model):base(model)
+        {
+
+        }
+        public float Bias => Model.Bias;
+        public float OpenLoopDrive => Model.OpenLoopDrive;
+    }
+}

+ 19 - 0
Shaker/ViewModel/ServiceAccelerationConfigViewModel.cs

@@ -0,0 +1,19 @@
+using Shaker.Model;
+
+namespace ShakerService.ViewModel
+{
+    internal class ServiceAccelerationConfigViewModel:BaseServiceViewModel<AccelerationConfigModel>
+    {
+        public ServiceAccelerationConfigViewModel():base()
+        {
+
+        }
+        public ServiceAccelerationConfigViewModel(AccelerationConfigModel model):base(model)
+        {
+
+        }
+        public float Weight => Model.Weight;
+        public float Sensitivity =>Model.Sensitivity;
+        public Shaker.Model.Polarity Polarity => Model.Polarity;
+    }
+}

+ 20 - 0
Shaker/ViewModel/ServiceAnalogSignalConfigViewModel.cs

@@ -0,0 +1,20 @@
+using Shaker.Model;
+using Shaker.Models;
+
+namespace ShakerService.ViewModel
+{
+    internal class ServiceAnalogSignalConfigViewModel:BaseServiceViewModel<AnalogSignalConfigModel>
+    {
+        public ServiceAnalogSignalConfigViewModel():base()
+        {
+
+        }
+        public ServiceAnalogSignalConfigViewModel(AnalogSignalConfigModel model):base(model)
+        {
+
+        }
+        public string Name =>Model.Name;
+        public string Unit =>Model.Unit;
+        public AnalogType AnalogType => Model.AnalogType;
+    }
+}

+ 0 - 21
Shaker/ViewModel/ServiceMainViewModel.cs

@@ -1,21 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace ShakerService.ViewModel
-{
-    internal class ServiceMainViewModel
-    {
-        private ServiceMainViewModel()
-        {
-
-        }
-        static ServiceMainViewModel()
-        {
-
-        }
-        public static ServiceMainViewModel Instance { get; } = new ServiceMainViewModel();
-    }
-}

+ 1 - 0
Shaker/ViewModel/ServiceRandomConfigViewModel.cs

@@ -35,6 +35,7 @@ namespace ShakerService.ViewModel
             Communication.Instance.DbConnection.CreateTable<RandomPlanItemModel>(tableName:nameof(PlanItems));
             model.PlanItems = Communication.Instance.DbConnection.Query<RandomPlanItemModel>($"select * from {nameof(PlanItems)}")?.ToList() ?? new List<RandomPlanItemModel>();
             UpModel(model);
+            SaveData();
             Communication.Instance.Context.GetEvent<RandomConfigModel>().Subscrip((sender, args) =>
             {
                 UpModel(args.Data);

+ 159 - 0
Shaker/ViewModel/ServiceShakerConfigViewModel.cs

@@ -0,0 +1,159 @@
+using Shaker.Model;
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Metrics;
+using System.Linq;
+using System.Runtime.Versioning;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService.ViewModel
+{
+    internal class ServiceShakerConfigViewModel:BaseServiceViewModel<Shaker.Models.ShakerConfigModel>
+    {
+        public AccelerationSynthesisType SynthesisType { get => Model.SynthesisType; }
+        public float OutSignalGain { get => Model.OutSignalGain;  }
+
+        public uint MaxRiseCount => Model.MaxRiseCount;
+        public uint MaxZeroChangedCount => Model.MaxZeroChangedCount;
+        public uint MaxSignalCount => Model.MaxSignalCount;
+        public uint MaxEmergencyStopCount => Model.MaxEmergencyStopCount;
+        public uint MaxStopWindowCount => MaxStopWindowCount;
+        public uint MaxAdjustCount => Model.MaxAdjustCount;
+        public uint MaxFallCount => Model.MaxFallCount;
+        public uint StartCount => Model.StartCount;
+        public float InitialLocation { get => Model.InitialLocation; }
+        public uint SampleRate => Model.SampleRate;
+        public uint FPGAClock => Model.FPGAClock;
+        public int ChannelCount => Model.AnalogSignalConfigs.Count;
+        public float MaxFrequency { get => Model.MaxFrequency; }
+        public float MinFrequency { get => Model.MinFrequency;}
+
+        public float MaxOutInput { get => Model.MaxOutInput;  }
+        public float MaxAcceleration { get => Model.MaxAcceleration;  }
+        public float MaxDisplacement { get => Model.MaxDisplacement;  }
+        public float MaxDriver { get => Model.MaxDriver;}
+        public float MaxJitterAcceleration { get => Model.MaxJitterAcceleration; }
+        public float MaxJitterDisplacement { get => Model.MaxJitterDisplacement; }
+        public float MaxVelocity { get => Model.MaxVelocity; }
+        public int AccelerationSensorCount => Model.AccelerationConfigs.Count;
+        public List<ServiceAnalogSignalConfigViewModel> AnalogSignals { get; } = new List<ServiceAnalogSignalConfigViewModel>();
+        public List<ServiceAccelerationConfigViewModel> Accelerations { get; } = new List<ServiceAccelerationConfigViewModel>();
+        public float DisplacementSensitivity { get => Model.DisplacementSensitivity; }
+        public float AccelerationSensitivity => Accelerations.Count > 0 ? Accelerations[0].Sensitivity : 1;
+        private ServiceShakerConfigViewModel()
+        {
+            Communication.Instance.DbConnection.CreateTable<Shaker.Models.ShakerConfigModel>();
+            var model = Communication.Instance.DbConnection.Query<Shaker.Models.ShakerConfigModel>($"select * from {nameof(Shaker.Models.ShakerConfigModel)} LIMIT 1")?.FirstOrDefault() ?? new Shaker.Models.ShakerConfigModel();
+            Communication.Instance.DbConnection.CreateTable<AnalogSignalConfigModel>(tableName: nameof(AnalogSignals));
+            model.AnalogSignalConfigs = Communication.Instance.DbConnection.Query<AnalogSignalConfigModel>($"select * from {nameof(AnalogSignals)}") ??new List<AnalogSignalConfigModel>();
+            int count = model.AnalogSignalConfigs.Count;
+            if(count<ServiceConfigViewModel.Instance.AnalogCount)
+            {
+                model.AnalogSignalConfigs.AddRange(Enumerable.Range(0, ServiceConfigViewModel.Instance.AnalogCount - count).Select(x => new AnalogSignalConfigModel()));
+            }
+            Communication.Instance.DbConnection.CreateTable<AccelerationConfigModel>(tableName: nameof(Accelerations));
+            model.AccelerationConfigs = Communication.Instance.DbConnection.Query<AccelerationConfigModel>($"select * from {nameof(Accelerations)}") ?? new List<AccelerationConfigModel>();
+            count = model.AccelerationConfigs.Count;
+            if(count<ServiceConfigViewModel.Instance.AccelerationCount)
+            {
+                model.AccelerationConfigs.AddRange(Enumerable.Range(0, ServiceConfigViewModel.Instance.AccelerationCount - count).Select(x => new AccelerationConfigModel()));
+            }
+            UpModel(model);
+            SaveData();
+            Communication.Instance.Context.GetEvent<Shaker.Models.ShakerConfigModel>().Subscrip((sender, args) =>
+            {
+                UpModel(model);
+                SetFpga();
+                ServiceSweepConfigViewModel.Instance.SetFpga();
+                SaveData();
+            });
+        }
+        public override void SetFpga()
+        {
+            base.SetFpga();
+            ShakerFpga.Instance.MaxRiseCount.Value = MaxRiseCount;
+            ShakerFpga.Instance.MaxZeroChangedCount.Value = MaxZeroChangedCount;
+            ShakerFpga.Instance.MaxSignalCount.Value =MaxSignalCount;
+            ShakerFpga.Instance.MaxEmergencyStopCount.Value = MaxEmergencyStopCount;
+            ShakerFpga.Instance.MaxStopWindowCount.Value = MaxStopWindowCount;
+            ShakerFpga.Instance.MaxFallCount.Value = MaxFallCount;
+            ShakerFpga.Instance.InitialLocation.Value = Tools.Tools.QuantitiesToVoltage(InitialLocation, DisplacementSensitivity);
+            ShakerFpga.Instance.SampleRate.Value = SampleRate;
+            ShakerFpga.Instance.SampleInterval.Value = 1f /SampleRate;
+            ShakerFpga.Instance.RiseInterval.Value = Tools.Tools.CalcInterval(MaxRiseCount);
+            ShakerFpga.Instance.ZeroChangedInterval.Value = Tools.Tools.CalcInterval(MaxZeroChangedCount);
+            ShakerFpga.Instance.EmergencyStopInterval.Value = Tools.Tools.CalcInterval(MaxEmergencyStopCount);
+            ShakerFpga.Instance.FallInterval.Value = Tools.Tools.CalcInterval(MaxFallCount);
+            ShakerFpga.Instance.StopWindowInterval.Value = Tools.Tools.CalcInterval(MaxStopWindowCount);
+            ShakerFpga.Instance.SignalInterval.Value = Tools.Tools.CalcInterval(MaxSignalCount);
+            ShakerFpga.Instance.MaxOutInput.Value = MaxOutInput;
+            ShakerFpga.Instance.WarnOutInput.Value = MaxOutInput * 0.8f;
+            ShakerFpga.Instance.MaxAcceleration.Value = Tools.Tools.QuantitiesToVoltage(MaxAcceleration, AccelerationSensitivity);
+            ShakerFpga.Instance.WarnAcceleration.Value = Tools.Tools.QuantitiesToVoltage(MaxAcceleration * 0.8f, AccelerationSensitivity);
+            ShakerFpga.Instance.MaxDisplacement.Value = Tools.Tools.QuantitiesToVoltage(MaxDisplacement, DisplacementSensitivity);
+            ShakerFpga.Instance.WarnDisplacement.Value = Tools.Tools.QuantitiesToVoltage(MaxDisplacement * 0.8f, DisplacementSensitivity);
+            ShakerFpga.Instance.MaxDriver.Value =MaxDriver;
+            ShakerFpga.Instance.AccelerationPolarity.Values = Accelerations.Select(x => x.Polarity == Shaker.Model.Polarity.Positive).ToArray();
+            ShakerFpga.Instance.MaxAdjustCount.Value = MaxAdjustCount;
+            ShakerFpga.Instance.AdjustInverval.Value = Tools.Tools.CalcInterval(MaxAdjustCount);
+            ShakerFpga.Instance.StartCount.Value = StartCount;
+            ShakerFpga.Instance.LoopRate.Value = FPGAClock / SampleRate;
+            ShakerFpga.Instance.SynthesisType.Value = (ushort)SynthesisType;
+            ShakerFpga.Instance.OutSignalGain.Value = OutSignalGain;
+            ShakerFpga.Instance.MaxAdjustCount.Value = MaxAdjustCount;
+            ShakerFpga.Instance.StartCount.Value = StartCount;
+            ShakerFpga.Instance.MaxJitterAcceleration.Value = Tools.Tools.QuantitiesToVoltage(MaxJitterAcceleration, AccelerationSensitivity);
+            ShakerFpga.Instance.MaxJitterDisplacement.Value = Tools.Tools.QuantitiesToVoltage(MaxJitterDisplacement, DisplacementSensitivity);
+        }
+        public override void UpModel(Shaker.Models.ShakerConfigModel model)
+        {
+            base.UpModel(model);
+            model.AnalogSignalConfigs ??= new List<AnalogSignalConfigModel>();
+            model.AccelerationConfigs ??= new List<AccelerationConfigModel>();
+            int count = model.AnalogSignalConfigs.Count;
+            if (count < ServiceConfigViewModel.Instance.AnalogCount)
+            {
+                model.AnalogSignalConfigs.AddRange(Enumerable.Range(0, ServiceConfigViewModel.Instance.AnalogCount - count).Select(x => new AnalogSignalConfigModel()));
+            }
+            else if(count>ServiceConfigViewModel.Instance.AnalogCount)
+            {
+                model.AnalogSignalConfigs = model.AnalogSignalConfigs.Take(ServiceConfigViewModel.Instance.AnalogCount).ToList();
+            }
+            model.AccelerationConfigs = Communication.Instance.DbConnection.Query<AccelerationConfigModel>($"select * from {nameof(Accelerations)}") ?? new List<AccelerationConfigModel>();
+            count = model.AccelerationConfigs.Count;
+            if (count < ServiceConfigViewModel.Instance.AccelerationCount)
+            {
+                model.AccelerationConfigs.AddRange(Enumerable.Range(0, ServiceConfigViewModel.Instance.AccelerationCount - count).Select(x => new AccelerationConfigModel()));
+            }
+            else if(count>ServiceConfigViewModel.Instance.AccelerationCount)
+            {
+                model.AccelerationConfigs = model.AccelerationConfigs.Take(ServiceConfigViewModel.Instance.AccelerationCount).ToList();
+            }
+            AnalogSignals.Clear();
+            Accelerations.Clear();
+            if(model.AnalogSignalConfigs.Count>0)
+            {
+                AnalogSignals.AddRange(model.AnalogSignalConfigs.Select(x => new ServiceAnalogSignalConfigViewModel(x)));
+            }
+            if(model.AccelerationConfigs.Count > 0)
+            {
+                Accelerations.AddRange(model.AccelerationConfigs.Select(x => new ServiceAccelerationConfigViewModel(x)));
+            }
+        }
+        private protected override void SaveData()
+        {
+            base.SaveData();
+            Communication.Instance.DbConnection.DeleteAll<AnalogSignalConfigModel>(tableName: nameof(AnalogSignals));
+            Communication.Instance.DbConnection.InsertAll(Model.AnalogSignalConfigs, tableName: nameof(AnalogSignals));
+            Communication.Instance.DbConnection.DeleteAll<AccelerationConfigModel>(tableName: nameof(Accelerations));
+            Communication.Instance.DbConnection.InsertAll(Model.AccelerationConfigs, tableName: nameof(Accelerations));
+        }
+        static ServiceShakerConfigViewModel()
+        {
+
+        }
+        public static ServiceShakerConfigViewModel Instance { get; } = new ServiceShakerConfigViewModel();
+    }
+}

+ 117 - 0
Shaker/ViewModel/ServiceShakerControlViewModel.cs

@@ -0,0 +1,117 @@
+using Shaker.Model;
+using Shaker.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ShakerService.ViewModel
+{
+    internal class ServiceShakerControlViewModel:BaseServiceViewModel<ShakerControlModel>
+    {
+        public MainPageType PageType => Model.PageType;
+        public int MaxControlItemCount => Model.MaxControlItemCount;
+        public float MaxValveVoltage =>Model.MaxValveVoltage;
+        public float MinValveVoltage=>Model.MinValveVoltage;
+        public float MaxDisplacementVoltage=>Model.MaxDisplacementVoltage;
+        public float MinDisplacementVoltage =>Model.MinDisplacementVoltage;
+        public Polarity ValvePolarity =>Model.ValvePolarity;
+        public bool SelfLoop=>Model.SelfLoop;
+        public bool Debug =>Model.Debug;
+        public float DisplacementP =>Model.DisplacementP;
+        public float DisplacementI =>Model.DisplacementI;
+        public float FlutterFrequency =>Model.FlutterFrequency;
+        public float FlutterAmpt =>Model.FlutterAmpt;
+        public int ServoValveCount => Model.ValveConfig.Count;
+        public List<SerivceValveConfigItemViewModel> ValveConfig { get; } = new List<SerivceValveConfigItemViewModel>();
+        public List<ServiceSweepControlItemViewModel> SweepControlItems { get; } = new List<ServiceSweepControlItemViewModel>();
+        public float MaxDisplacementIntegral => Model.MaxDisplacementIntegral;
+        public float DisplacementBias => Model.DisplacementBias;
+        public bool OilStopped => Model.OilStopped;
+        public bool DisplacementOpenLoop => Model.DisplacementOpenLoop;
+        public bool OutSignal => Model.OutSignal;
+        private ServiceShakerControlViewModel()
+        {
+            Communication.Instance.DbConnection.CreateTable<ShakerControlModel>();
+            var model = Communication.Instance.DbConnection.Query<ShakerControlModel>($"select * from {nameof(ShakerControlModel)} LIMIT 1")?.FirstOrDefault() ?? new ShakerControlModel();
+            model.PageType = MainPageType.StartPage;
+            Communication.Instance.DbConnection.CreateTable<ValveConfigItemModel>(tableName: nameof(ValveConfig));
+            model.ValveConfig = Communication.Instance.DbConnection.Query<ValveConfigItemModel>($"select * from {nameof(ValveConfig)}") ?? new List<ValveConfigItemModel>();
+            Communication.Instance.DbConnection.CreateTable<SweepControlItemModel>(tableName:nameof(SweepControlItems));
+            model.ControlItems.AddRange(Communication.Instance.DbConnection.Query<SweepControlItemModel>($"select * from {nameof(SweepControlItems)}") ?? new List<SweepControlItemModel>());
+
+            int count = model.ValveConfig.Count;
+            if(count<ServiceConfigViewModel.Instance.ValveCount)
+            {
+                model.ValveConfig.AddRange(Enumerable.Range(0, ServiceConfigViewModel.Instance.ValveCount - count).Select(x => new ValveConfigItemModel()));
+            }
+            UpModel(model);
+            SaveData();
+            Communication.Instance.Context.GetEvent<ShakerControlModel>().Subscrip((sender, args) =>
+            {
+                UpModel(model);
+                SetFpga();
+                SaveData();
+            });
+        }
+        static ServiceShakerControlViewModel()
+        {
+
+        }
+        public override void SetFpga()
+        {
+            base.SetFpga();
+            ShakerFpga.Instance.ServoValvePolarity.Value = ValvePolarity == Polarity.Positive;
+            ShakerFpga.Instance.OilStopped.Value = OilStopped;
+            ShakerFpga.Instance.DisplacementOpenLoop.Value = DisplacementOpenLoop;
+            ShakerFpga.Instance.OutSignal.Value = OutSignal;
+            ShakerFpga.Instance.DisplacementBias.Value = DisplacementBias;
+            ShakerFpga.Instance.DisplacementI.Value = DisplacementI;
+            ShakerFpga.Instance.DisplacementP.Value = DisplacementP;
+            ShakerFpga.Instance.SelfLoop.Value = SelfLoop;
+            ShakerFpga.Instance.Debug.Value = Debug;
+            ShakerFpga.Instance.FlutterAmpt.Value = FlutterAmpt;
+            ShakerFpga.Instance.FlutterFrequency.Value = FlutterFrequency;
+            ShakerFpga.Instance.ValveBias.Value = ValveConfig.Select(x => x.Bias).ToArray();
+            ShakerFpga.Instance.OpenLoopDisplacement.Value = ValveConfig.Select(x => x.OpenLoopDrive).ToArray();
+        }
+        public override void UpModel(ShakerControlModel model)
+        {
+            model.ValveConfig ??= new List<ValveConfigItemModel>();
+            model.ControlItems ??= new List<SweepControlItemModel>();
+            int count = model.ValveConfig.Count;
+            if (count < ServiceConfigViewModel.Instance.ValveCount)
+            {
+                model.ValveConfig.AddRange(Enumerable.Range(0, ServiceConfigViewModel.Instance.ValveCount - count).Select(x => new ValveConfigItemModel()));
+            }
+            else if(count>ServiceConfigViewModel.Instance.ValveCount)
+            {
+                model.ValveConfig = model.ValveConfig.Take(ServiceConfigViewModel.Instance.ValveCount).ToList();
+            }
+            base.UpModel(model);
+
+            ValveConfig.Clear();
+            SweepControlItems.Clear();
+            if(model.ValveConfig.Count>0)
+            {
+                ValveConfig.AddRange(model.ValveConfig.Select(x => new SerivceValveConfigItemViewModel(x)));
+            }
+            if(model.ControlItems.Count>0)
+            {
+                SweepControlItems.AddRange(model.ControlItems.Select(x => new ServiceSweepControlItemViewModel(x)));
+            }
+        }
+        private protected override void SaveData()
+        {
+            base.SaveData();
+
+            Communication.Instance.DbConnection.DeleteAll<ValveConfigItemModel>(tableName: nameof(ValveConfig));
+            Communication.Instance.DbConnection.InsertAll(Model.ValveConfig, tableName: nameof(ValveConfig));
+
+            Communication.Instance.DbConnection.DeleteAll<SweepControlItemModel>(tableName: nameof(SweepControlItems));
+            Communication.Instance.DbConnection.InsertAll(Model.ControlItems, tableName: nameof(SweepControlItems));
+        }
+        public static ServiceShakerControlViewModel Instance { get; } = new ServiceShakerControlViewModel();
+    }
+}

+ 64 - 17
Shaker/ViewModel/ServiceShakerStatusViewModel.cs

@@ -9,22 +9,69 @@ namespace ShakerService.ViewModel
 {
     internal class ServiceShakerStatusViewModel:BaseServiceViewModel<ShakerStatusModel>
     {
-        public RTStatus RTStatus {get=>Model.RTStatus; set=>Model.RTStatus = value; }
-        public bool Start { get => Model.Start; set => Model.Start = value; }
-        public float SynthesisAmplitude { get=>Model.SynthesisAmplitude; set=>Model.SynthesisAmplitude = value; }
-        public bool IsTableRised {get=>Model.IsTableRised; set=>Model.IsTableRised = value; }
-        public bool IsTableDroped {get=>Model.IsTableDroped; set=>Model.IsTableDroped = value; }
-        public bool IsFaultRelease {get=>Model.IsFaultRelease; set=>Model.IsFaultRelease = value; }
-        public uint RiseCount { get=>Model.RiseCount; set=>Model.RiseCount = value; }
-        public uint SignalGenStopCount {get=>Model.SignalGenStopCount; set=>Model.SignalGenStopCount = value; }
-        public uint EmergencyStopCount {get=>Model.EmergencyStopCount; set=>Model.EmergencyStopCount = value; }
-        public bool IsSignalGenStoped {get=>Model.IsSignalGenStoped; set=>Model.IsSignalGenStoped = value; }
-        public uint ZeroChangedCount {get=>Model.ZeroChangedCount; set=>Model.ZeroChangedCount = value; }
-        public ushort WarnCode {get=>Model.WarnCode; set=>Model.WarnCode = value; }
-        public float CurrentFrequency {get=>Model.CurrentFrequency; set=>Model.CurrentFrequency = value; }
-        public bool ClosedValve {get=>Model.ClosedValve; set=>Model.ClosedValve = value; }
-        public uint DropCount {get=>Model.DropCount; set=>Model.DropCount = value; }
-        public ushort ErrorCode {get=>Model.ErrorCode; set=>Model.ErrorCode = value; }
-        public bool ValvePower {get=>Model.ValvePower; set=>Model.ValvePower = value; }
+        private ServiceShakerStatusViewModel()
+        {
+
+        }
+        static ServiceShakerStatusViewModel()
+        {
+
+        }
+        public void ReadFpgaData()
+        {
+            _NeedSendData = false;
+            RTStatus = (RTStatus)ShakerFpga.Instance.RTStatus.Value;
+            var val = ShakerFpga.Instance.Rised.Value;
+            if(val!=IsTableRised)
+            {
+                IsTableRised = val;
+                Communication.Instance.Context.GetEvent(nameof(IsTableRised)).Publish(this, null, val);
+            }
+            val = ShakerFpga.Instance.Falled.Value;
+            if(val!=IsTableDroped)
+            {
+                IsTableDroped = val;
+                Communication.Instance.Context.GetEvent(nameof(IsTableDroped)).Publish(this, null, val);
+            }
+            val = ShakerFpga.Instance.Troubleshooting.Value;
+            if(val!=IsFaultRelease)
+            {
+                IsFaultRelease = val;
+                Communication.Instance.Context.GetEvent(nameof(IsFaultRelease)).Publish(this, null, val);
+            }
+            val = ShakerFpga.Instance.SignalFinish.Value;
+            if(val!=IsSignalGenStoped)
+            {
+                IsSignalGenStoped = val;
+                Communication.Instance.Context.GetEvent(nameof(IsSignalGenStoped)).Publish(this, null, val);
+            }
+            val = ShakerFpga.Instance.ErrorCloseVavle.Value;
+            if (val != ClosedValve)
+            {
+                ClosedValve = val;
+                Communication.Instance.Context.GetEvent(nameof(ClosedValve)).Publish(this, null, val);
+            }
+            RiseCount = ShakerFpga.Instance.RiseIndex.Value;
+            SignalGenStopCount = ShakerFpga.Instance.StopWindowIndex.Value;
+            EmergencyStopCount = ShakerFpga.Instance.EmergencyStopIndex.Value;
+            ZeroChangedCount = ShakerFpga.Instance.ZeroChangedIndex.Value;
+            WarnCode = ShakerFpga.Instance.WarnCode.Value;
+            ErrorCode = ShakerFpga.Instance.ErrorCode.Value;
+            if(_NeedSendData) SendData();
+        }
+        public static ServiceShakerStatusViewModel Instance { get; } = new ServiceShakerStatusViewModel();
+        public RTStatus RTStatus {get=>Model.RTStatus; set=>SetProperty(ref Model.RTStatus , value); }
+        public bool IsTableRised {get=>Model.IsTableRised; set=>SetProperty(ref Model.IsTableRised , value); }
+        public bool IsTableDroped {get=>Model.IsTableDroped; set=>SetProperty(ref Model.IsTableDroped, value); }
+        public bool IsFaultRelease {get=>Model.IsFaultRelease; set=>SetProperty(ref Model.IsFaultRelease, value); }
+        public uint RiseCount { get=>Model.RiseCount; set=>SetProperty(ref Model.RiseCount, value); }
+        public uint SignalGenStopCount {get=>Model.SignalGenStopCount; set=>SetProperty(ref Model.SignalGenStopCount, value); }
+        public uint EmergencyStopCount {get=>Model.EmergencyStopCount; set=>SetProperty(ref Model.EmergencyStopCount, value); }
+        public bool IsSignalGenStoped {get=>Model.IsSignalGenStoped; set=>SetProperty(ref Model.IsSignalGenStoped, value); }
+        public uint ZeroChangedCount {get=>Model.ZeroChangedCount; set=>SetProperty(ref Model.ZeroChangedCount, value); }
+        public ushort WarnCode {get=>Model.WarnCode; set=>SetProperty(ref Model.WarnCode, value); }
+        public bool ClosedValve {get=>Model.ClosedValve; set=>SetProperty(ref Model.ClosedValve, value); }
+        public uint DropCount {get=>Model.DropCount; set=>SetProperty(ref Model.DropCount, value); }
+        public ushort ErrorCode {get=>Model.ErrorCode; set=>SetProperty(ref Model.ErrorCode, value); }
     }
 }

Деякі файли не було показано, через те що забагато файлів було змінено