using System; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using Correlator.Dialog; using Correlator.Model; using Correlator.SensorHubTag; 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 MessageBox = HandyControl.Controls.MessageBox; using Window = System.Windows.Window; namespace Correlator.ViewModel { public class HomePageViewModel : ViewModelBase { #region RelayCommand public RelayCommand<HomePageWindow> WindowLoadedCommand { set; get; } public RelayCommand AudioCommand { private set; get; } public RelayCommand SaveAudioCommand { private set; get; } public RelayCommand ResetParamCommand { private set; get; } public RelayCommand StartCalculateCommand { private set; get; } #endregion #region Property private string _currentTime; public string CurrentTime { get => _currentTime; private 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; private set { _transmitterASignalIntensity = value; RaisePropertyChanged(() => TransmitterASignalIntensity); } } /// <summary> /// 发射机B信号强度0-5 /// </summary> private int _transmitterBSignalIntensity; public int TransmitterBSignalIntensity { get => _transmitterBSignalIntensity; private 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; private set { _transmitterBFault = value; RaisePropertyChanged(() => TransmitterBFault); } } /// <summary> /// 开始/停止 /// </summary> private bool _startState; public bool StartState { get => _startState; private set { _startState = value; RaisePropertyChanged(() => StartState); } } /// <summary> /// 发射机A距离 /// </summary> private double _transmitterADistance; public double TransmitterADistance { get => _transmitterADistance; private set { _transmitterADistance = value; RaisePropertyChanged(() => TransmitterADistance); } } /// <summary> /// 发射机B距离 /// </summary> private double _transmitterBDistance; public double TransmitterBDistance { get => _transmitterBDistance; private set { _transmitterBDistance = value; RaisePropertyChanged(() => TransmitterBDistance); } } /// <summary> /// 绑定声速值 /// </summary> private string _soundSpeed = string.Empty; public string SoundSpeed { get => _soundSpeed; private set { _soundSpeed = value; RaisePropertyChanged(() => SoundSpeed); } } /// <summary> /// 绑定经过了值 /// </summary> private string _passTime = string.Empty; public string PassTime { get => _passTime; private set { _passTime = value; RaisePropertyChanged(() => PassTime); } } /// <summary> /// 绑定干扰频段值 /// </summary> private string _noiseValue = string.Empty; public string NoiseValue { get => _noiseValue; private set { _noiseValue = value; RaisePropertyChanged(() => NoiseValue); } } /// <summary> /// 绑定过滤器值 /// </summary> private string _filterValue = string.Empty; public string FilterValue { get => _filterValue; private set { _filterValue = value; RaisePropertyChanged(() => FilterValue); } } /// <summary> /// 绑定过信噪比 /// </summary> private string _snr = string.Empty; public string Snr { get => _snr; private set { _snr = value; RaisePropertyChanged(() => Snr); } } /// <summary> /// 绑定管道值 /// </summary> private string _pipeline = string.Empty; public string PipeLine { get => _pipeline; private set { _pipeline = value; RaisePropertyChanged(() => PipeLine); } } #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 SystemConfig.SystemPowerStatus lpSystemPowerStatus); #endregion private HomePageWindow _homePageWindow; 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 readonly DispatcherTimer _snapShotTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(5) }; //加速度计下发指令Timer private readonly DispatcherTimer _accelerometerCommandTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(10) }; //水听器下发指令Timer private readonly DispatcherTimer _hydrophoneCommandTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(10) }; private string _locateDataDir; private int _locateTimes; private string _snapShotPath = string.Empty; //Matlab算法 private readonly CorrelatorSingle.Correlator _correlator = new CorrelatorSingle.Correlator(); public HomePageViewModel() { #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 TimerTick(); RegisterMessage(); InitCommand(); } /// <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; }; _timer.Start(); //获取电池电量 var sysPower = new SystemConfig.SystemPowerStatus(); GetSystemPowerStatus(ref sysPower); Battery = sysPower.BatteryPercent == 255 ? 100 : sysPower.BatteryPercent; _batteryTimer.Tick += delegate { GetSystemPowerStatus(ref sysPower); Battery = sysPower.BatteryPercent == 255 ? 100 : sysPower.BatteryPercent; }; _batteryTimer.Start(); //计算时间Timer _runningTimer.Tick += delegate { _runningSeconds++; PassTime = _runningSeconds.ToString(); if (_runningSeconds >= 90) { _runningTimer.Stop(); MessageBox.Show("接收不到数据,请点击复位并重新开始采集数据", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); } }; //自动截屏Timer _snapShotTimer.Tick += delegate { _snapShotTimer.Stop(); if (!string.IsNullOrEmpty(_snapShotPath)) { _snapShotPath.SnapShot(); "HomePageViewModel".WriteLog("截屏路径:" + _snapShotPath); } }; //加速度计下发指令Timer _accelerometerCommandTimer.Tick += delegate { if (FlowStatus.CanCollectData) { CommandSender.SendCorrelatorWakeUpCmd(SerialPortManager.Get.Sp); } }; //水听器下发指令Timer _hydrophoneCommandTimer.Tick += delegate { if (FlowStatus.CanCollectData) { CommandSender.SendHydrophoneWakeUpCmd(SerialPortManager.Get.Sp); } }; } /// <summary> /// 消息监听 /// </summary> private void RegisterMessage() { Messenger.Default.Register<DevStatus>(this, MessengerToken.RedSensorStatus, dev => { "HomePageViewModel".WriteLog("SensorA收到消息:" + JsonConvert.SerializeObject(dev)); TransmitterABattery = Convert.ToDouble(dev.Cell); var signalIntensity = Convert.ToInt32(dev.Signal).ToIntensity(); TransmitterASignalIntensity = signalIntensity; var sensorStatus = dev.Status == "1"; TransmitterAFault = sensorStatus; //将信号A数据缓存到FlowStatus FlowStatus.SensorASignalIntensity = signalIntensity; FlowStatus.SensorAIsEnable = sensorStatus; }); Messenger.Default.Register<DevStatus>(this, MessengerToken.BlueSensorStatus, dev => { "HomePageViewModel".WriteLog("SensorB收到消息:" + JsonConvert.SerializeObject(dev)); TransmitterBBattery = Convert.ToDouble(dev.Cell); var signalIntensity = Convert.ToInt32(dev.Signal).ToIntensity(); TransmitterBSignalIntensity = signalIntensity; var sensorStatus = dev.Status == "1"; TransmitterBFault = sensorStatus; //将信号B数据缓存到FlowStatus FlowStatus.SensorBSignalIntensity = signalIntensity; FlowStatus.SensorBIsEnable = sensorStatus; }); Messenger.Default.Register<byte[]>(this, MessengerToken.ShowCheckResponseDialog, timeBytes => { new CheckResponseDialog(timeBytes) { Owner = _homePageWindow }.ShowDialog(); }); // TODO 设备状态就绪,暂时不做逻辑处理,后期可以适当调整或者添加 Messenger.Default.Register<string>(this, MessengerToken.HomePageSignal, s => { }); Messenger.Default.Register<PipeMaterialModel>(this, MessengerToken.StartCalculate, it => { if (!it.IsReady) return; "HomePageViewModel".WriteLog("需要测算的管材是:" + JsonConvert.SerializeObject(it)); FlowStatus.SelectedMaterialModel = it; StartState = true; //信号收发器正常之后就可以下发收集数据的指令了 FlowStatus.CanCollectData = true; //绑定设置的参数 PipeLine = it.Diameter + "mm, " + it.Length + "m" + it.ChineseMaterial; SoundSpeed = it.SoundSpeed.ToString(); NoiseValue = it.LowFrequency + "-" + it.HighFrequency + "Hz"; //开始数据采集 if (FlowStatus.IsHydrophone) { _hydrophoneCommandTimer.Start(); } else { _accelerometerCommandTimer.Start(); } //记录计算时间 _runningTimer.Start(); }); //计算测试数据 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); } } }); } private void InitCommand() { WindowLoadedCommand = new RelayCommand<HomePageWindow>(it => { Debug.WriteLine("HomePageViewModel => 加载"); _homePageWindow = it; }); AudioCommand = new RelayCommand(delegate { if (!SerialPortManager.Get.Sp.IsOpen) { MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } var auditionWindow = new AuditionWindow { Owner = Window.GetWindow(_homePageWindow) }; auditionWindow.ShowDialog(); }); SaveAudioCommand = new RelayCommand(() => { if (FlowStatus.CorrelatorData != null) { SaveAudio(); } else { MessageBox.Show("还未开始采集数据,无法保存音频", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); } }); ResetParamCommand = new RelayCommand(ResetParam); StartCalculateCommand = new RelayCommand(delegate { if (!SerialPortManager.Get.Sp.IsOpen) { MessageBox.Show("串口状态异常,无法操作", "温馨提示", MessageBoxButton.OK, MessageBoxImage.Error); return; } //每次计算之前都需要判断是否已经完成之前的计算,然后清空上一次的计算数据 ResetParam(); var materialDialog = new SelectMaterialDialog { Owner = Window.GetWindow(_homePageWindow) }; materialDialog.ShowDialog(); }); } /// <summary> /// 重置参数 /// </summary> private void ResetParam() { StartState = false; FlowStatus.CanCollectData = false; if (FlowStatus.IsHydrophone) { _hydrophoneCommandTimer.Stop(); } else { _accelerometerCommandTimer.Stop(); } FilterValue = "未设置"; Snr = ""; PipeLine = "未设置"; SoundSpeed = "0"; NoiseValue = "未设置"; PassTime = "0"; _runningSeconds = 0; _runningTimer.Stop(); TransmitterADistance = 0; TransmitterBDistance = 0; //清空波形图 Messenger.Default.Send("", MessengerToken.ClearOscillogram); } /// <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); //重写头文件 wavFile.WriteHeader(stream, 7500, 2); Growl.Success("音频已保存"); //清空上次的缓存 FlowStatus.CorrelatorData = null; } /// <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, 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()); //时间差 // var timeDiff = Convert.ToDouble(array[6].ToString()); // SpeedDistance = timeDiff; // SpeedValue = timeDiff.ToString(CultureInfo.InvariantCulture) + "ms"; //将数据发送到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(); StartState = false; //开始计算就不收集收据了 FlowStatus.CanCollectData = false; DialogHub.Get.DismissLoadingDialog(); return true; } } }