Newer
Older
Correlator / Correlator / ViewModel / HomePageViewModel.cs
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using Correlator.Model;
using Correlator.SensorHubTag;
using Correlator.UserControlPage;
using Correlator.Util;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using HandyControl.Controls;
using LiveCharts.Defaults;
using LiveCharts.Geared;
using MathWorks.MATLAB.NET.Arrays;
using Newtonsoft.Json;
using MessageBox = HandyControl.Controls.MessageBox;

namespace Correlator.ViewModel
{
    public class HomePageViewModel : ViewModelBase
    {
        #region RelayCommand

        public RelayCommand ShutDownCommand { get; set; }
        public RelayCommand LeftSensorCommand { get; set; }
        public RelayCommand RightSensorCommand { get; set; }
        public RelayCommand FilterCommand { get; set; }
        public RelayCommand NoiseCommand { get; set; }
        public RelayCommand AudioCommand { get; set; }
        public RelayCommand SnapShotCommand { get; set; }
        public RelayCommand ResetParamCommand { get; set; }
        public RelayCommand StartCalculateCommand { get; set; }
        public RelayCommand SaveAudioCommand { get; set; }
        public RelayCommand OpenMenuCommand { get; set; }

        #endregion

        #region Property

        private string _currentTime;

        public string CurrentTime
        {
            get => _currentTime;
            set
            {
                _currentTime = value;
                RaisePropertyChanged(() => CurrentTime);
            }
        }

        private double _battery;

        public double Battery
        {
            get => _battery;
            set
            {
                _battery = value;
                RaisePropertyChanged(() => Battery);
            }
        }

        /// <summary>
        /// 发射机A电量 0-100
        /// </summary>
        private double _transmitterABattery;

        public double TransmitterABattery
        {
            get => _transmitterABattery;
            set
            {
                _transmitterABattery = value;
                RaisePropertyChanged(() => TransmitterABattery);
            }
        }

        /// <summary>
        /// 发射机B电量 0-100
        /// </summary>
        private double _transmitterBBattery;

        public double TransmitterBBattery
        {
            get => _transmitterBBattery;
            set
            {
                _transmitterBBattery = value;
                RaisePropertyChanged(() => TransmitterBBattery);
            }
        }

        /// <summary>
        /// 发射机A信号强度0-5
        /// </summary>
        private int _transmitterASignalIntensity;

        public int TransmitterASignalIntensity
        {
            get => _transmitterASignalIntensity;
            set
            {
                _transmitterASignalIntensity = value;
                RaisePropertyChanged(() => TransmitterASignalIntensity);
            }
        }

        /// <summary>
        /// 发射机B信号强度0-5
        /// </summary>
        private int _transmitterBSignalIntensity;

        public int TransmitterBSignalIntensity
        {
            get => _transmitterBSignalIntensity;
            set
            {
                _transmitterBSignalIntensity = value;
                RaisePropertyChanged(() => TransmitterBSignalIntensity);
            }
        }

        /// <summary>
        /// 发射机A是否故障
        /// </summary>
        private bool _transmitterAFault;

        public bool TransmitterAFault
        {
            get => _transmitterAFault;
            set
            {
                _transmitterAFault = value;
                RaisePropertyChanged(() => TransmitterAFault);
            }
        }

        /// <summary>
        /// 发射机B是否故障
        /// </summary>
        private bool _transmitterBFault;

        public bool TransmitterBFault
        {
            get => _transmitterBFault;
            set
            {
                _transmitterBFault = value;
                RaisePropertyChanged(() => TransmitterBFault);
            }
        }

        /// <summary>
        /// 开始/停止
        /// </summary>
        private bool _startState;

        public bool StartState
        {
            get => _startState;
            set
            {
                _startState = value;
                RaisePropertyChanged(() => StartState);
            }
        }

        /// <summary>
        /// 发射机A距离 
        /// </summary>
        private double _transmitterADistance;

        public double TransmitterADistance
        {
            get => _transmitterADistance;
            set
            {
                _transmitterADistance = value;
                RaisePropertyChanged(() => TransmitterADistance);
            }
        }

        /// <summary>
        /// 发射机B距离
        /// </summary>
        private double _transmitterBDistance;

        public double TransmitterBDistance
        {
            get => _transmitterBDistance;
            set
            {
                _transmitterBDistance = value;
                RaisePropertyChanged(() => TransmitterBDistance);
            }
        }

        /// <summary>
        /// 绑定声速值
        /// </summary>
        private string _soundSpeed = string.Empty;

        public string SoundSpeed
        {
            get => _soundSpeed;
            set
            {
                _soundSpeed = value;
                RaisePropertyChanged(() => SoundSpeed);
            }
        }

        /// <summary>
        /// 绑定经过了值
        /// </summary>
        private string _passTime = string.Empty;

        public string PassTime
        {
            get => _passTime;
            set
            {
                _passTime = value;
                RaisePropertyChanged(() => PassTime);
            }
        }

        /// <summary>
        /// 绑定干扰频段值
        /// </summary>
        private string _noiseValue = string.Empty;

        public string NoiseValue
        {
            get => _noiseValue;
            set
            {
                _noiseValue = value;
                RaisePropertyChanged(() => NoiseValue);
            }
        }


        /// <summary>
        /// 绑定过滤器值
        /// </summary>
        private string _filterValue = string.Empty;

        public string FilterValue
        {
            get => _filterValue;
            set
            {
                _filterValue = value;
                RaisePropertyChanged(() => FilterValue);
            }
        }

        /// <summary>
        /// 绑定过信噪比
        /// </summary>
        private string _snr = string.Empty;

        public string Snr
        {
            get => _snr;
            set
            {
                _snr = value;
                RaisePropertyChanged(() => Snr);
            }
        }


        /// <summary>
        /// 绑定管道值
        /// </summary>
        private string _pipeline = string.Empty;

        public string PipeLine
        {
            get => _pipeline;
            set
            {
                _pipeline = value;
                RaisePropertyChanged(() => PipeLine);
            }
        }

        /// <summary>
        /// 最大相关系数
        /// </summary>
        private string _maxCorrelationCoefficient = string.Empty;

        public string MaxCorrelationCoefficient
        {
            get => _maxCorrelationCoefficient;
            set
            {
                _maxCorrelationCoefficient = value;
                RaisePropertyChanged(() => MaxCorrelationCoefficient);
            }
        }

        /// <summary>
        /// Chart点数据
        /// </summary>
        private GearedValues<ObservablePoint> _columnValues;

        public GearedValues<ObservablePoint> ColumnValues
        {
            get => _columnValues;
            set
            {
                _columnValues = value;
                RaisePropertyChanged(() => ColumnValues);
            }
        }

        #endregion

        #region ButtonIsEnabled

        private bool _filterButtonIsEnabled;

        public bool FilterButtonIsEnabled
        {
            get => _filterButtonIsEnabled;
            set
            {
                _filterButtonIsEnabled = value;
                RaisePropertyChanged(() => FilterButtonIsEnabled);
            }
        }

        private bool _audioButtonIsEnabled;

        public bool AudioButtonIsEnabled
        {
            get => _audioButtonIsEnabled;
            set
            {
                _audioButtonIsEnabled = value;
                RaisePropertyChanged(() => AudioButtonIsEnabled);
            }
        }

        private bool _snapButtonIsEnabled;

        public bool SnapButtonIsEnabled
        {
            get => _snapButtonIsEnabled;
            set
            {
                _snapButtonIsEnabled = value;
                RaisePropertyChanged(() => SnapButtonIsEnabled);
            }
        }

        private bool _resetButtonIsEnabled;

        public bool ResetButtonIsEnabled
        {
            get => _resetButtonIsEnabled;
            set
            {
                _resetButtonIsEnabled = value;
                RaisePropertyChanged(() => ResetButtonIsEnabled);
            }
        }

        private bool _startButtonIsEnabled;

        public bool StartButtonIsEnabled
        {
            get => _startButtonIsEnabled;
            set
            {
                _startButtonIsEnabled = value;
                RaisePropertyChanged(() => StartButtonIsEnabled);
            }
        }

        private bool _saveButtonIsEnabled;

        public bool SaveButtonIsEnabled
        {
            get => _saveButtonIsEnabled;
            set
            {
                _saveButtonIsEnabled = value;
                RaisePropertyChanged(() => SaveButtonIsEnabled);
            }
        }

        #endregion

        #region PC电量状态

        [DllImport("kernel32.dll", EntryPoint = "GetSystemPowerStatus")]
        private static extern void GetSystemPowerStatus(ref SystemPowerStatus lpSystemPowerStatus);

        /// <summary>
        /// 顺序不可更改
        /// </summary>
        private struct SystemPowerStatus
        {
            public ACLineStatus AcLineStatus; //0 = offline, 1 = Online, 255 = UnKnown Status.   
            public BatteryFlag BatteryFlag;
            public byte BatteryPercent;
            public SystemStatusFlag StatusFlag;
            public int BatteryLifeTime;
            public int BatteryFullLifeTime;
        }

        private enum ACLineStatus : byte
        {
            Offline = 0, //offline
            Online = 1, //Online
            UnKnownStatus = 255 // 未知
        }

        private enum BatteryFlag : byte
        {
            Middle = 0, // 电池未充电并且电池容量介于高电量和低电量之间
            High = 1, // 电池电量超过66%
            Low = 2, // 电池电量不足33%
            Critical = 4, // 电池电量不足百分之五
            Charging = 8, // 	充电中
            NoSystemBattery = 128, // 无系统电池
            UnKnownStatus = 255 // 无法读取电池标志信息
        }

        private enum SystemStatusFlag : byte
        {
            Off = 0, //  节电功能已关闭
            On = 1 //  节电功能已打开,节省电池。尽可能节约能源
        }

        #endregion

        //计算时间
        private int _runningSeconds;

        //运行时间Timer
        private readonly DispatcherTimer _runningTimer = new DispatcherTimer
        {
            Interval = TimeSpan.FromSeconds(1)
        };

        //自动截屏倒计时
        private readonly DispatcherTimer _snapShotTimer = new DispatcherTimer
        {
            Interval = TimeSpan.FromSeconds(5)
        };

        private string _locateDataDir;
        private int _locateTimes;
        private string _snapShotPath = string.Empty;

        //Matlab算法
        private readonly CorrelatorSingle.Correlator _correlator = new CorrelatorSingle.Correlator();

        public HomePageViewModel()
        {
            ShutDownCommand = new RelayCommand(() =>
            {
                var result = MessageBox.Show("是否确认关机?\r\n选择是,电脑将关机;\r\n选择否,应用将退出;\r\n选择取消,可继续操作应用",
                    "温馨提示", MessageBoxButton.YesNoCancel, MessageBoxImage.Question);
                switch (result)
                {
                    case MessageBoxResult.None:
                        break;
                    case MessageBoxResult.OK:
                        break;
                    case MessageBoxResult.Cancel:
                        break;
                    case MessageBoxResult.Yes:
                        var p = new Process();
                        p.StartInfo.FileName = "shutdown.exe";
                        p.StartInfo.Arguments = "-s -f -t 0";
                        p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                        p.Start();
                        break;
                    case MessageBoxResult.No:
                        Messenger.Default.Send("", MessengerToken.CloseHomePageWindow);
                        break;
                    default:
                        throw new ArgumentOutOfRangeException();
                }
            });

            DisplayCurrentTime();

            DisplayBattery();

            SerialPortManager.Instance.CheckSerialPortState();

            #region 默认值

            StartState = false;
            //过滤器数值展示
            FilterValue = "未设置";
            //信噪比数值展示
            Snr = "";
            //管道数值展示
            PipeLine = "未设置";
            //干扰频段
            NoiseValue = "未设置";
            //声速数值展示
            SoundSpeed = "0";
            //经过了数值展示
            PassTime = "0";

            //发射器A数值
            TransmitterABattery = 0;
            TransmitterADistance = 0;
            TransmitterASignalIntensity = 0;
            TransmitterAFault = true;

            //发射器B数值
            TransmitterBBattery = 0;
            TransmitterBDistance = 0;
            TransmitterBSignalIntensity = 0;
            TransmitterBFault = true;

            #endregion

            RegisterMessage();

            LeftSensorCommand = new RelayCommand(() =>
            {
                if (!SerialPortManager.Instance.PortIsReady())
                {
                    MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                SerialPortManager.Instance.ShowLeftSensorSignal();
            });
            RightSensorCommand = new RelayCommand(() =>
            {
                if (!SerialPortManager.Instance.PortIsReady())
                {
                    MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                SerialPortManager.Instance.ShowRightSensorSignal();
            });
            FilterCommand = new RelayCommand(() =>
            {
                if (!SerialPortManager.Instance.PortIsReady())
                {
                    MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                if (FlowStatus.SelectedMaterialModel == null || FlowStatus.CorrelatorData == null)
                {
                    MessageBox.Show("还未采集数据,无法进行频段筛选", "错误", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                var filterUserControl = new FilterUserControl();
                UserControlManager.UserControlMap["filterUserControl"] = filterUserControl;
                Messenger.Default.Send("", MessengerToken.AddFilter);
            });
            NoiseCommand = new RelayCommand(() =>
            {
                if (!SerialPortManager.Instance.PortIsReady())
                {
                    MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                var noiseUserControl = new NoiseUserControl();
                UserControlManager.UserControlMap["noiseUserControl"] = noiseUserControl;
                Messenger.Default.Send("", MessengerToken.AddNoise);
            });
            AudioCommand = new RelayCommand(() =>
            {
                if (!SerialPortManager.Instance.PortIsReady())
                {
                    MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                var auditionUserControl = new AuditionUserControl();
                UserControlManager.UserControlMap["auditionUserControl"] = auditionUserControl;
                Messenger.Default.Send("", MessengerToken.AddAudition);
            });
            SnapShotCommand = new RelayCommand(() =>
            {
                var filePath = Constant.GetPictureDir() + "\\快照_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".png";
                ImageHelper.SnapShot(filePath);
            });
            ResetParamCommand = new RelayCommand(ResetParam);
            StartCalculateCommand = new RelayCommand(() =>
            {
                if (SerialPort.GetPortNames().Length == 0)
                {
                    MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                if (FlowStatus.IsCompleteCalculateOnce)
                {
                    ResetParam();
                }

                var pipeMaterialUserControl = new PipeMaterialUserControl();
                UserControlManager.UserControlMap["pipeMaterialUserControl"] = pipeMaterialUserControl;
                Messenger.Default.Send("", MessengerToken.AddPipeMaterial);
            });
            SaveAudioCommand = new RelayCommand(() =>
            {
                if (FlowStatus.CorrelatorData != null)
                {
                    SaveAudio();
                }
                else
                {
                    MessageBox.Show("还未开始采集数据,无法保存音频", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            });
            OpenMenuCommand = new RelayCommand(() =>
            {
                var menuUserControl = new MenuUserControl();
                UserControlManager.UserControlMap["menuUserControl"] = menuUserControl;
                Messenger.Default.Send("", MessengerToken.AddMenu);
            });

            //计算时间Timer
            _runningTimer.Tick += delegate
            {
                _runningSeconds++;
                PassTime = _runningSeconds.ToString();
                if (_runningSeconds >= 90)
                {
                    _runningTimer.Stop();
                    var result = MessageBox.Show("接收不到数据,请重启软件", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error);
                    if (result == MessageBoxResult.OK)
                    {
                        Process.GetCurrentProcess().Kill();
                    }
                }
            };

            //自动截屏Timer
            _snapShotTimer.Tick += delegate
            {
                _snapShotTimer.Stop();
                if (!string.IsNullOrEmpty(_snapShotPath))
                {
                    ImageHelper.SnapShot(_snapShotPath);
                    LogWithConsole.WriteLine("截屏路径:" + _snapShotPath, "HomePageViewModel");
                }
            };
        }

        /// <summary>
        /// 实时显示时间
        /// </summary>
        private void DisplayCurrentTime()
        {
            var timer = new DispatcherTimer
            {
                Interval = TimeSpan.FromSeconds(1)
            };
            timer.Tick += delegate
            {
                var dateTime = DateTime.Now;
                var strDateTime = dateTime.ToString("yyyy年MM月dd日") +
                                  dateTime.ToString("\0 \0 \0 dddd \0 \0 \0", new CultureInfo("zh-cn")) +
                                  dateTime.ToString("HH:mm:ss");
                CurrentTime = strDateTime;
            };
            timer.Start();
        }

        /// <summary>
        /// 获取电池
        /// </summary>
        private void DisplayBattery()
        {
            var timerBattery = new DispatcherTimer
            {
                Interval = TimeSpan.FromSeconds(300)
            };

            var sysPower = new SystemPowerStatus();
            GetSystemPowerStatus(ref sysPower);
            Battery = sysPower.BatteryPercent == 255 ? 100 : sysPower.BatteryPercent;

            timerBattery.Tick += delegate
            {
                GetSystemPowerStatus(ref sysPower);
                Battery = sysPower.BatteryPercent == 255 ? 100 : sysPower.BatteryPercent;
            };
            timerBattery.Start();
        }

        /// <summary>
        /// 消息监听
        /// </summary>
        private void RegisterMessage()
        {
            Messenger.Default.Register<DevStatus>(this, MessengerToken.SensorADevStatus, dev =>
            {
                LogWithConsole.WriteLine("SensorA收到消息:" + JsonConvert.SerializeObject(dev), "HomePageViewModel");

                TransmitterABattery = Convert.ToDouble(dev.Cell);
                var signalIntensity = SerialPortManager.Instance.SetSignalIntensity(Convert.ToInt32(dev.Signal));
                TransmitterASignalIntensity = signalIntensity;
                var sensorStatus = dev.Status == "1";
                TransmitterAFault = sensorStatus;
                //将信号A数据缓存到FlowStatus
                FlowStatus.SensorASignalIntensity = signalIntensity;
                FlowStatus.SensorAIsEnable = sensorStatus;
            });

            Messenger.Default.Register<DevStatus>(this, MessengerToken.SensorBDevStatus, dev =>
            {
                LogWithConsole.WriteLine("SensorB收到消息:" + JsonConvert.SerializeObject(dev), "HomePageViewModel");

                TransmitterBBattery = Convert.ToDouble(dev.Cell);
                var signalIntensity = SerialPortManager.Instance.SetSignalIntensity(Convert.ToInt32(dev.Signal));
                TransmitterBSignalIntensity = signalIntensity;
                var sensorStatus = dev.Status == "1";
                TransmitterBFault = sensorStatus;
                //将信号B数据缓存到FlowStatus
                FlowStatus.SensorBSignalIntensity = signalIntensity;
                FlowStatus.SensorBIsEnable = sensorStatus;
            });

            // TODO 设备状态就绪,暂时不做逻辑处理,后期可以适当调整或者添加
            Messenger.Default.Register<string>(this, MessengerToken.HomePageSignal, s => { });

            Messenger.Default.Register<PipeMaterialModel>(this, MessengerToken.StartCalculate, it =>
            {
                if (!it.IsReady) return;
                LogWithConsole.WriteLine("需要测算的管材是:" + JsonConvert.SerializeObject(it), "HomePageViewModel");

                FlowStatus.SelectedMaterialModel = it;
                //{"Id":0,"EnglishMaterial":null,"ChineseMaterial":"球铁","Diameter":20.0,"Length":150.0,"SoundSpeed":1320,"LowFrequency":100,"HighFrequency":1000,"IsReady":true}
                StartState = true;
                //收集数据期间不允许收集信号
                FlowStatus.CanGetSignal = false;
                //信号收发器正常之后就可以下发收集数据的指令了
                FlowStatus.CanCollectData = true;
                //绑定设置的参数
                PipeLine = it.Diameter + "mm, " + it.Length + "m" + it.ChineseMaterial;
                SoundSpeed = it.SoundSpeed.ToString();
                NoiseValue = it.LowFrequency + "-" + it.HighFrequency + "Hz";

                //数据采集Task
                new Task(CollectData).Start();

                //记录计算时间
                _runningTimer.Start();
            });

            //计算测试数据
            Messenger.Default.Register<CorrelatorDataModel>(this, MessengerToken.HomePageDeviceData, it =>
            {
                //给音频数据赋值
                FlowStatus.CorrelatorData = it;
                using (var manager = new DataBaseManager())
                {
                    var today = DateTime.Now.ToString("yyyyMMdd");
                    var configModel = manager
                        .Table<CorrelatorConfigModel>()
                        .Where(x => x.Date == today)
                        .OrderBy(x => x.Date)
                        .LastOrDefault() ?? new CorrelatorConfigModel
                    {
                        Date = today,
                        Pipe = 1,
                        LocateTimes = 1,
                        ListenTimes = 1
                    };

                    //如果配置里面的日期相同,则取配置里面的Pipe作为index,如果配置里面的日期不相同,则默认index=1
                    var pipeIndex = configModel.Date.Equals(today) ? configModel.Pipe : 1;
                    _locateDataDir = Constant.GetLocateDataDir(pipeIndex);
                    _locateTimes = configModel.LocateTimes;

                    //计算
                    try
                    {
                        var task = new Task<bool>(() => CalculateData(it));
                        task.Start();

                        //异步保存定位数据
                        var fileName = _locateDataDir + "\\测试数据." + _locateTimes + "."
                                       + DateTime.Now.ToString("HHmmss") + ".txt";
                        StringUtil.SaveLocateData(it, fileName);
                        LogWithConsole.WriteLine("定位数据路径:" + fileName, "HomePageViewModel");

                        //同步保存截图,需要等待Task出结果并且渲染完成,才能保存截图
                        _snapShotPath = _locateDataDir + "\\快照." + _locateTimes + "." +
                                        DateTime.Now.ToString("HHmmss") + ".png";
                        if (task.Result)
                        {
                            _snapShotTimer.Start();
                        }

                        //插入新纪录
                        configModel.Pipe++;
                        configModel.LocateTimes++;
                        manager.Insert(configModel);
                    }
                    catch (Exception e)
                    {
                        LogWithConsole.WriteLine(e.Message, "HomePageViewModel");
                    }
                }
            });

            Messenger.Default.Register<int[]>(this, MessengerToken.ReStartCalculate, frequency =>
            {
                FlowStatus.SelectedMaterialModel.LowFrequency = frequency[0];
                FlowStatus.SelectedMaterialModel.HighFrequency = frequency[1];

                LogWithConsole.WriteLine("需要重新测算的管材是:" + JsonConvert.SerializeObject(FlowStatus.SelectedMaterialModel),
                    "HomePageViewModel");
                
                var task = new Task<bool>(() => CalculateData(FlowStatus.CorrelatorData));
                task.Start();

                //重新计算需要把截屏次数自增
                _locateTimes++;
                _snapShotPath = _locateDataDir + "\\快照." + _locateTimes + "." + DateTime.Now.ToString("HHmmss") +
                                ".png";
                if (task.Result)
                {
                    _snapShotTimer.Start();
                }
            });
        }

        /// <summary>
        /// 重置参数
        /// </summary>
        private void ResetParam()
        {
            StartState = false;
            FlowStatus.IsCompleteCalculateOnce = false;
            FilterValue = "未设置";
            Snr = "";
            PipeLine = "未设置";
            SoundSpeed = "0";
            NoiseValue = "未设置";
            PassTime = "0";
            //复位时将波形图数据清空
            ColumnValues?.Clear();
            _runningSeconds = 0;
            _runningTimer.Stop();
        }

        /// <summary>
        /// 保存音频
        /// </summary>
        private void SaveAudio()
        {
            var wavFile = new WavFile();
            var filePath = Constant.GetAudioDir() + "\\音频_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".wav";

            var stream = wavFile.CreateEmpty(filePath);
            wavFile.WriteFilestream(stream, FlowStatus.CorrelatorData.LeftDeviceDataArray,
                FlowStatus.CorrelatorData.RightDeviceDataArray);

            //写入数据,测试多轮时候保存数据采用下面方式
            // for (var i = 0; i < CorrelatorDataSaveThread.devDataValueMap[DevCode.Dev2].Count; i++)
            // {
            //     wavFile.WriteFilestream(stream, CorrelatorDataSaveThread.devDataValueMap[DevCode.Dev1][i],
            //         CorrelatorDataSaveThread.devDataValueMap[DevCode.Dev2][i]);
            // }

            //重写头文件
            wavFile.WriteHeader(stream, 7500, 2);
            Growl.Success("音频已保存");
            //清空上次的缓存
            FlowStatus.CorrelatorData = null;
        }

        /// <summary>
        /// 下发唤醒指令
        /// </summary>
        private void CollectData()
        {
            while (FlowStatus.CanCollectData)
            {
                SenderClass.SendCorrelatorWakeUpCmd(SerialPortManager.Instance.SerialPort);
                Thread.Sleep(10 * 1000);
            }
        }

        /// <summary>
        /// Matlab计算过程
        /// </summary>
        /// <param name="dataModel">收集到的传感器数据</param>
        /// <returns>计算结果</returns>
        private bool CalculateData(CorrelatorDataModel dataModel)
        {
            LogWithConsole.WriteLine("开始计算", "HomePageViewModel");
            var array = _correlator.locating(11,
                (MWNumericArray)dataModel.LeftDeviceDataArray, (MWNumericArray)dataModel.RightDeviceDataArray,
                Constant.SamplingRate,
                FlowStatus.SelectedMaterialModel.Length, FlowStatus.SelectedMaterialModel.SoundSpeed,
                0, 0,
                0, 0,
                FlowStatus.SelectedMaterialModel.ChineseMaterial,
                FlowStatus.SelectedMaterialModel.Diameter,
                FlowStatus.SelectedMaterialModel.Diameter,
                1, -1, -1, -1,
                FlowStatus.SelectedMaterialModel.LowFrequency,
                FlowStatus.SelectedMaterialModel.HighFrequency);

            //数据绑定
            var snr = Convert.ToDouble(array[0].ToString()); //信噪比
            Snr = snr.ToString("0.0") + ":1";
            TransmitterADistance = Convert.ToDouble(array[1].ToString()); //距离A
            TransmitterBDistance = Convert.ToDouble(array[2].ToString()); //距离B
            //最大相关系数  
            var maxCorrelationCoefficient = Convert.ToDouble(array[3].ToString());
            MaxCorrelationCoefficient = "最大相关系数:" + maxCorrelationCoefficient;

            //时间差
            // var timeDiff = Convert.ToDouble(array[6].ToString());

            // SpeedDistance = timeDiff;
            // SpeedValue = timeDiff.ToString(CultureInfo.InvariantCulture) + "ms";

            //柱状图纵坐标集合
            var yDoubles = GetArray((MWNumericArray)array[4]);
            //柱状图横坐标集合
            var xDoubles = GetArray((MWNumericArray)array[5]);
            //绑定柱状图
            ColumnValues = new GearedValues<ObservablePoint>();
            var count = xDoubles.Length;
            for (var i = 0; i < count; i++)
            {
                ColumnValues.Add(new ObservablePoint
                {
                    X = xDoubles[i],
                    Y = yDoubles[i]
                });
            }

            ColumnValues.WithQuality(Quality.Medium);

            var maxFreLowOut = Convert.ToInt32(array[6].ToString()); //低频
            var maxFreHighOut = Convert.ToInt32(array[7].ToString()); //高频
            var flag = Convert.ToBoolean(Convert.ToInt32(array[8].ToString())); //是否泄漏
            var totalNum = Convert.ToInt32(array[9].ToString()); //总的调用次数

            FilterValue = maxFreLowOut + "-" + maxFreHighOut + "Hz";

            //可以重新计算以及收集信号
            FlowStatus.IsCompleteCalculateOnce = true;
            _runningTimer.Stop();
            StartState = false;
            FlowStatus.CanGetSignal = true;
            return true;
        }

        private static double[] GetArray(MWNumericArray inputMw)
        {
            var num = inputMw.NumberOfElements;
            var outArray = new double[num];
            for (var i = 0; i < num; i++)
            {
                outArray[i] = Convert.ToDouble(inputMw[i + 1].ToString());
            }

            return outArray;
        }
    }
}