using System; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using Correlator.Dialog; using Correlator.Model; using Correlator.SensorHubTag; using Correlator.Service; using Correlator.Util; using Correlator.View; using GalaSoft.MvvmLight; using GalaSoft.MvvmLight.Command; using GalaSoft.MvvmLight.Messaging; using HandyControl.Controls; using MathWorks.MATLAB.NET.Arrays; using Newtonsoft.Json; using ComboBox = System.Windows.Controls.ComboBox; using MessageBox = HandyControl.Controls.MessageBox; namespace Correlator.ViewModel { public class HomePageProViewModel : ViewModelBase { #region 变量 private readonly DispatcherTimer _timer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; private readonly DispatcherTimer _batteryTimer = new DispatcherTimer { Interval = TimeSpan.FromMinutes(5) }; //计算时间 private int _runningSeconds; //运行时间Timer private readonly DispatcherTimer _runningTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) }; private bool _isResetParam; private readonly ISoundSpeedDataService _soundSpeedDataService; //加速度计下发指令Timer private readonly DispatcherTimer _accelerometerCommandTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(10) }; //水听器下发指令Timer private readonly DispatcherTimer _hydrophoneCommandTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(10) }; private HomePageProWindow _homePageWindow; private string _locateDataDir; private int _locateTimes; private string _snapShotPath = string.Empty; //自动截屏倒计时 private readonly DispatcherTimer _snapShotTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) }; //Matlab算法 private readonly CorrelatorSingle.Correlator _correlator = new CorrelatorSingle.Correlator(); #endregion #region VM属性 private string _currentTime; public string CurrentTime { get => _currentTime; private set { _currentTime = value; RaisePropertyChanged(); } } /// <summary> /// 红色发射机信号强度0-5 /// </summary> private int _redTransmitterSignalIntensity; public int RedTransmitterSignalIntensity { get => _redTransmitterSignalIntensity; private set { _redTransmitterSignalIntensity = value; RaisePropertyChanged(); } } /// <summary> /// 蓝色发射机信号强度0-5 /// </summary> private int _blueTransmitterSignalIntensity; public int BlueTransmitterSignalIntensity { get => _blueTransmitterSignalIntensity; private set { _blueTransmitterSignalIntensity = value; RaisePropertyChanged(); } } /// <summary> /// 绑定干扰频段值 /// </summary> private string _interferenceFrequency = "无"; public string InterferenceFrequency { get => _interferenceFrequency; private set { _interferenceFrequency = value; RaisePropertyChanged(); } } /// <summary> /// 绑定过信噪比 /// </summary> private string _snr = "无"; public string Snr { get => _snr; private set { _snr = value; RaisePropertyChanged(); } } /// <summary> /// 绑定过滤器值 /// </summary> private string _filterValue = " ~ Hz"; public string FilterValue { get => _filterValue; private set { _filterValue = value; RaisePropertyChanged(); } } /// <summary> /// 绑定声速值 /// </summary> private string _soundSpeed = "0"; public string SoundSpeed { get => _soundSpeed; private set { _soundSpeed = value; RaisePropertyChanged(); } } /// <summary> /// 红色发射机是否故障 /// </summary> private bool _redTransmitterState; public bool RedTransmitterState { get => _redTransmitterState; set { _redTransmitterState = value; RaisePropertyChanged(); } } /// <summary> /// 蓝色发射机是否故障 /// </summary> private bool _blueTransmitterState; public bool BlueTransmitterState { get => _blueTransmitterState; private set { _blueTransmitterState = value; RaisePropertyChanged(); } } /// <summary> /// 红色发射机距离 /// </summary> private double _redTransmitterDistance; public double RedTransmitterDistance { get => _redTransmitterDistance; private set { _redTransmitterDistance = value; RaisePropertyChanged(); } } /// <summary> /// 蓝色发射机距离 /// </summary> private double _blueTransmitterDistance; public double BlueTransmitterDistance { get => _blueTransmitterDistance; private set { _blueTransmitterDistance = value; RaisePropertyChanged(); } } /// <summary> /// 红色发射机电量 0-100 /// </summary> private double _redTransmitterBattery; public double RedTransmitterBattery { get => _redTransmitterBattery; set { _redTransmitterBattery = value; RaisePropertyChanged(); } } /// <summary> /// 蓝色发射机电量 0-100 /// </summary> private double _blueTransmitterBattery; public double BlueTransmitterBattery { get => _blueTransmitterBattery; set { _blueTransmitterBattery = value; RaisePropertyChanged(); } } /// <summary> /// 绑定经过了值 /// </summary> private string _elapseTime = "0"; public string ElapseTime { get => _elapseTime; private set { _elapseTime = value; RaisePropertyChanged(); } } private double _computerBattery; public double ComputerBattery { get => _computerBattery; set { _computerBattery = value; RaisePropertyChanged(); } } private string _connectColorBrush = "LightGray"; public string ConnectColorBrush { get => _connectColorBrush; private set { _connectColorBrush = value; RaisePropertyChanged(); } } private ObservableCollection<string> _pipeMaterialsArray; public ObservableCollection<string> PipeMaterialsArray { get => _pipeMaterialsArray; private set { _pipeMaterialsArray = value; RaisePropertyChanged(); } } // private string _pipeName = string.Empty; private string _pipeName = "铸铁"; public string PipeName { get => _pipeName; set { _pipeName = value; RaisePropertyChanged(); } } // private string _pipeDiameter = string.Empty; private string _pipeDiameter = "300"; public string PipeDiameter { get => _pipeDiameter; set { _pipeDiameter = value; RaisePropertyChanged(); } } // private string _pipeLength = string.Empty; private string _pipeLength = "150"; public string PipeLength { get => _pipeLength; set { _pipeLength = value; RaisePropertyChanged(); } } private string _frequencyInterval = "100 ~ 3000Hz"; public string FrequencyInterval { get => _frequencyInterval; private set { _frequencyInterval = value; RaisePropertyChanged(); } } // private string _lowFrequency = string.Empty; private string _lowFrequency = "100"; public string LowFrequency { get => _lowFrequency; set { _lowFrequency = value; RaisePropertyChanged(); } } private string _highFrequency = string.Empty; public string HighFrequency { get => _highFrequency; set { _highFrequency = value; RaisePropertyChanged(); } } //是否已开始采集或者计算数据 private bool _startButtonIsEnabled = true; public bool StartButtonEnabled { get => _startButtonIsEnabled; private set { _startButtonIsEnabled = value; RaisePropertyChanged(); } } private string _applicationVersion = "Ver 1.0.0.0"; public string ApplicationVersion { get => _applicationVersion; private set { _applicationVersion = value; RaisePropertyChanged(); } } #endregion #region PC电量状态 [DllImport("kernel32.dll", EntryPoint = "GetSystemPowerStatus")] private static extern void GetSystemPowerStatus(ref SystemConfig.SystemPowerStatus lpSystemPowerStatus); #endregion #region RelayCommand public RelayCommand<HomePageProWindow> WindowLoadedCommand { set; get; } public RelayCommand<ComboBox> PipeItemSelectedCommand { set; get; } public RelayCommand SoundSettingsCommand { private set; get; } public RelayCommand SaveAudioCommand { private set; get; } public RelayCommand ResetParamCommand { private set; get; } public RelayCommand SnapShotCommand { private set; get; } public RelayCommand StartCalculateCommand { private set; get; } #endregion public HomePageProViewModel(IPipeMaterialDataService dataService, ISoundSpeedDataService soundSpeedDataService) { _soundSpeedDataService = soundSpeedDataService; //获取版本号 ApplicationVersion = "Ver " + Application.ResourceAssembly.GetName().Version; RegisterMessage(); TimerTick(); _pipeMaterialsArray = new ObservableCollection<string>(); var pipeMaterials = dataService.GetPipeMaterial(); foreach (var material in pipeMaterials) { PipeMaterialsArray.Add(material.ChineseMaterial); } InitRelayCommand(); } /// <summary> /// 消息监听注册 /// </summary> private void RegisterMessage() { Messenger.Default.Register<DevStatus>(this, MessengerToken.RedSensorStatus, dev => { "HomePageProViewModel".WriteLog("Red Sensor收到消息:" + JsonConvert.SerializeObject(dev)); //新协议不计算实际信号 RedTransmitterBattery = Convert.ToDouble(dev.Cell); RedTransmitterSignalIntensity = 5; RedTransmitterState = true; FlowStatus.RedSensorIsEnable = true; }); Messenger.Default.Register<DevStatus>(this, MessengerToken.BlueSensorStatus, dev => { "HomePageProViewModel".WriteLog("Blue Sensor收到消息:" + JsonConvert.SerializeObject(dev)); //新协议不计算实际信号 BlueTransmitterBattery = Convert.ToDouble(dev.Cell); BlueTransmitterSignalIntensity = 5; BlueTransmitterState = true; FlowStatus.BlueSensorIsEnable = true; }); //计算测试数据 Messenger.Default.Register<CorrelatorDataModel>(this, MessengerToken.HomePageDeviceData, it => { //开始计算停止收集指令 if (FlowStatus.IsHydrophone) { _hydrophoneCommandTimer.Stop(); } else { _accelerometerCommandTimer.Stop(); } //给音频数据赋值 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); "HomePageViewModel".WriteLog("定位数据路径:" + fileName); //同步保存截图,需要等待Task出结果并且渲染完成,才能保存截图 _snapShotPath = _locateDataDir + "\\快照." + _locateTimes + "." + DateTime.Now.ToString("HHmmss") + ".png"; if (task.Result) { _snapShotTimer.Start(); } //插入新纪录 configModel.Pipe++; configModel.LocateTimes++; manager.Insert(configModel); } catch (Exception e) { "HomePageViewModel".WriteLog(e.Message); } } }); //水听器 Messenger.Default.Register<byte[]>(this, MessengerToken.ShowCheckResponseDialog, timeBytes => { new CheckResponseDialog(timeBytes) { Owner = _homePageWindow }.ShowDialog(); }); } /// <summary> /// 各种定时器 /// </summary> private void TimerTick() { //实时显示时间 _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; //同时监听串口状态 ConnectColorBrush = SerialPortManager.Get.Sp.IsOpen ? "LimeGreen" : "LightGray"; }; _timer.Start(); //获取电池电量 var sysPower = new SystemConfig.SystemPowerStatus(); GetSystemPowerStatus(ref sysPower); ComputerBattery = sysPower.BatteryPercent == 255 ? 100 : sysPower.BatteryPercent; _batteryTimer.Tick += delegate { GetSystemPowerStatus(ref sysPower); ComputerBattery = sysPower.BatteryPercent == 255 ? 100 : sysPower.BatteryPercent; }; _batteryTimer.Start(); //计算时间Timer _runningTimer.Tick += delegate { _runningSeconds++; ElapseTime = _runningSeconds.ToString(); if (_runningSeconds >= 90) { _runningTimer.Stop(); MessageBox.Show("接收不到数据,请点击复位并重新开始采集数据", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); } }; //加速度计下发指令Timer _accelerometerCommandTimer.Tick += delegate { if (FlowStatus.CanCollectData) { CommandSender.SendCorrelatorWakeUpCmd(SerialPortManager.Get.Sp); } }; //水听器下发指令Timer _hydrophoneCommandTimer.Tick += delegate { if (FlowStatus.CanCollectData) { CommandSender.SendHydrophoneWakeUpCmd(SerialPortManager.Get.Sp); } }; //自动截屏Timer _snapShotTimer.Tick += delegate { _snapShotTimer.Stop(); if (!string.IsNullOrEmpty(_snapShotPath)) { _snapShotPath.SnapShot(); "HomePageProViewModel".WriteLog("截屏路径:" + _snapShotPath); } }; } /// <summary> /// 事件指令 /// </summary> private void InitRelayCommand() { WindowLoadedCommand = new RelayCommand<HomePageProWindow>(it => { _homePageWindow = it; Debug.WriteLine("HomePageProViewModel => 加载"); it.AccelerationRadioButton.Checked += delegate { FlowStatus.IsHydrophone = false; FrequencyInterval = "100 ~ 3000Hz"; }; it.HydrophonesRadioButton.Checked += delegate { FlowStatus.IsHydrophone = true; FrequencyInterval = "10 ~ 300Hz"; }; }); PipeItemSelectedCommand = new RelayCommand<ComboBox>(delegate(ComboBox box) { PipeName = box.SelectedItem.ToString(); }); SoundSettingsCommand = new RelayCommand(delegate { var speedDialog = new SoundSpeedDialog(_pipeName) { Owner = _homePageWindow }; speedDialog.ShowDialog(); }); SaveAudioCommand = new RelayCommand(delegate { if (FlowStatus.CorrelatorData != null) { 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); //重写头文件 wavFile.WriteHeader(stream, 7500, 2); Growl.Success("音频已保存"); //清空上次的缓存 FlowStatus.CorrelatorData = null; } else { MessageBox.Show("还未开始采集数据,无法保存音频", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); } }); ResetParamCommand = new RelayCommand(delegate { _isResetParam = true; ResetParam(); }); SnapShotCommand = new RelayCommand(delegate { var filePath = Constant.GetPictureDir() + "\\快照_" + DateTime.Now.ToString("yyyyMMddHHmmss") + ".png"; filePath.SnapShot(); }); StartCalculateCommand = new RelayCommand(delegate { if (!SerialPortManager.Get.Sp.IsOpen) { MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (string.IsNullOrEmpty(_pipeName)) { MessageBox.Show("请选择管道材料", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (string.IsNullOrEmpty(_pipeDiameter)) { MessageBox.Show("请输入管道直径", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (string.IsNullOrEmpty(_pipeLength)) { MessageBox.Show("请输入管道长度", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (string.IsNullOrEmpty(_lowFrequency) || string.IsNullOrEmpty(_highFrequency)) { MessageBox.Show("请输入完整的干扰频段", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } if (!(Regex.IsMatch(_lowFrequency, "^([1-9][0-9]*)$") && Regex.IsMatch(_highFrequency, "^([1-9][0-9]*)$"))) { MessageBox.Show("输入格式错误,请重新输入", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } var low = Convert.ToInt32(_lowFrequency); var high = Convert.ToInt32(_highFrequency); if (FlowStatus.IsHydrophone) { if (low < 10 || low > 300 || high < 10 || high > 300 || low >= high) { MessageBox.Show("频段范围10 ~ 300Hz,请重新输入", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } } else { if (low < 100 || low > 3000 || high < 100 || high > 3000 || low >= high) { MessageBox.Show("频段范围100 ~ 3000Hz,请重新输入", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } } _isResetParam = false; StartButtonEnabled = false; //声速 var soundVelocity = _soundSpeedDataService.GetSoundVelocity(_pipeName, Convert.ToInt32(_pipeDiameter)); SoundSpeed = soundVelocity.ToString(); //每次计算之前都需要判断是否已经完成之前的计算,然后清空上一次的计算数据 ResetParam(); //信号收发器正常之后就可以下发收集数据的指令了 FlowStatus.CanCollectData = true; //开始数据采集 if (FlowStatus.IsHydrophone) { _hydrophoneCommandTimer.Start(); } else { _accelerometerCommandTimer.Start(); } //记录计算时间 _runningTimer.Start(); }); } /// <summary> /// 重置参数 /// </summary> private void ResetParam() { if (_isResetParam) { // PipeDiameter = string.Empty; // PipeLength = string.Empty; // LowFrequency = string.Empty; PipeDiameter = "300"; PipeLength = "150"; LowFrequency = "100"; HighFrequency = string.Empty; SoundSpeed = "0"; //复位之后可以再次开始 StartButtonEnabled = true; } InterferenceFrequency = "无"; Snr = "无"; FilterValue = " ~ Hz"; RedTransmitterDistance = 0; ElapseTime = "0"; BlueTransmitterDistance = 0; _runningSeconds = 0; _runningTimer.Stop(); Messenger.Default.Send("", MessengerToken.ClearOscillogram); if (FlowStatus.IsHydrophone) { _hydrophoneCommandTimer.Stop(); } else { _accelerometerCommandTimer.Stop(); } FlowStatus.CanCollectData = false; } /// <summary> /// Matlab计算过程 /// </summary> /// <param name="dataModel">收集到的传感器数据</param> /// <returns>计算结果</returns> private bool CalculateData(CorrelatorDataModel dataModel) { DialogHub.Get.ShowLoadingDialog(_homePageWindow, "样品数据计算中,请稍后..."); var array = _correlator.locating(11, (MWNumericArray)dataModel.LeftDeviceDataArray, (MWNumericArray)dataModel.RightDeviceDataArray, Constant.SamplingRate, int.Parse(_pipeLength), int.Parse(_soundSpeed), 0, 0, 0, 0, _pipeName, int.Parse(_pipeDiameter), int.Parse(_pipeDiameter), 1, -1, -1, -1, int.Parse(_lowFrequency), int.Parse(_highFrequency)); //数据绑定 var snr = Convert.ToDouble(array[0].ToString()); //信噪比 Snr = snr.ToString("0.0") + ":1"; RedTransmitterDistance = Convert.ToDouble(array[1].ToString()); //距离A BlueTransmitterDistance = Convert.ToDouble(array[2].ToString()); //距离B //最大相关系数 var maxCorrelationCoefficient = Convert.ToDouble(array[3].ToString()); //时间差 var timeDiff = Convert.ToDouble(array[6].ToString()); //将数据发送到HomePageWindow.xaml.cs页面进行渲染 Messenger.Default.Send(array, MessengerToken.RenderOscillogram); 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"; _runningTimer.Stop(); StartButtonEnabled = true; //开始计算就不收集收据了 FlowStatus.CanCollectData = false; DialogHub.Get.DismissLoadingDialog(); return true; } } }