using MaterialDesignThemes.Wpf; using Newtonsoft.Json; using Prism.Commands; using Prism.Events; using Prism.Ioc; using Prism.Mvvm; using Prism.Regions; using Prism.Services.Dialogs; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web.UI.WebControls; using System.Windows; using System.Windows.Threading; using TeamAAS_VP.Core; using TeamAAS_VP.Core.PLCs; using TeamAAS_VP.Events; using TeamAAS_VP.Interfaces; using TeamAAS_VP.Models; using TeamAAS_VP.Models.PLC; using TeamAAS_VP.Models.Torque; using TeamAAS_VP.Resources.Languages; using TeamAAS_VP.Services; using TeamAAS_VP.ViewModels.Product; using static TeamAAS_VP.ViewModels.Product.VisionDynamicAccuracyAnalyzerViewModel; namespace TeamAAS_VP.ViewModels.Home { public class PickScrewAccuracyAnalyzerViewModel : BindableBase, IDialogAware { IRegionManager _regionManager; IEventAggregator _eventAggregator; IContainerProvider _container; IDialogService _dialogService; IRobotService _robotService; ISystemDatabaseService _systemDatabaseService; IConfigService _configService; IPlcService _plcService; TorqueService _torqueService; //测试过程中控制取消的CTS CancellationTokenSource _cts; public PickScrewAccuracyAnalyzerViewModel(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container, IDialogService dialogService, IRobotService robotService, ISystemDatabaseService systemDatabaseService, IConfigService configService, TorqueService torqueService, IPlcService plcService) { _eventAggregator = ea; _configService = configService; _container = container; _robotService = robotService; _torqueService = torqueService; _plcService = plcService; management = _container.Resolve(); MessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(2)); } #region 属性 private SnackbarMessageQueue _MessageQueue; public SnackbarMessageQueue MessageQueue { get { return _MessageQueue; } set { SetProperty(ref _MessageQueue, value); } } private Management _management; public Management management { get { return _management; } set { SetProperty(ref _management, value); } } private int _MoveSpeed = 100; /// /// 移动速度 /// public int MoveSpeed { get { return _MoveSpeed; } set { SetProperty(ref _MoveSpeed, value); } } private double _CycleTime; /// /// 单次的时长 /// public double CycleTime { get { return _CycleTime; } set { SetProperty(ref _CycleTime, value); } } private int _RepeatCount = 10; /// /// 重复次数 /// public int RepeatCount { get { return _RepeatCount; } set { SetProperty(ref _RepeatCount, value); } } private int _CurrentProgress; /// /// 当前进度 /// public int CurrentProgress { get { return _CurrentProgress; } set { SetProperty(ref _CurrentProgress, value); } } private int _SuccessCount; /// /// 成功次数 /// public int SuccessCount { get { return _SuccessCount; } set { SetProperty(ref _SuccessCount, value); } } private int _FailCount; /// /// 失败次数 /// public int FailCount { get { return _FailCount; } set { SetProperty(ref _FailCount, value); } } private double _SuccessRate; /// /// 成功率 /// public double SuccessRate { get { return _SuccessRate; } set { SetProperty(ref _SuccessRate, value); } } private string _Message = "等待开始..."; public string Message { get { return _Message; } set { SetProperty(ref _Message, value); } } private bool _IsRunning; public bool IsRunning { get { return _IsRunning; } set { SetProperty(ref _IsRunning, value); } } private IRobot _Robot; public IRobot Robot { get { return _Robot; } set { SetProperty(ref _Robot, value); } } private ObservableCollection _TestResults; /// /// 测试结果列表 /// public ObservableCollection TestResults { get { return _TestResults; } set { SetProperty(ref _TestResults, value); } } private RPoint _PointA = new RPoint(); private TorqueProduceModel _Points; public TorqueProduceModel Points { get { return _Points; } set { SetProperty(ref _Points, value); } } private bool _IsScrewProvide2; public bool IsScrewProvide2 { get { return _IsScrewProvide2; } set { SetProperty(ref _IsScrewProvide2, value); } } private bool _IsScrewProvide1; public bool IsScrewProvide1 { get { return _IsScrewProvide1; } set { SetProperty(ref _IsScrewProvide1, value); } } #endregion #region 命令 private DelegateCommand _StopTestCommand; public DelegateCommand StopTestCommand => _StopTestCommand ?? (_StopTestCommand = new DelegateCommand(() => { _cts?.Cancel(); }, () => IsRunning).ObservesProperty(() => IsRunning)); //暂停测试命令 private DelegateCommand _PauseTestCommand; public DelegateCommand PauseTestCommand => _PauseTestCommand ?? (_PauseTestCommand = new DelegateCommand(() => { _cts?.Cancel(); }, () => IsRunning).ObservesProperty(() => IsRunning)); private DelegateCommand _LoadedCommand; public DelegateCommand LoadedCommand => _LoadedCommand ?? (_LoadedCommand = new DelegateCommand(ExecuteLoadedCommand)); private DelegateCommand _StartTestCommand; public DelegateCommand StartTestCommand => _StartTestCommand ?? (_StartTestCommand = new DelegateCommand(ExecuteStartTestCommand).ObservesProperty(() => IsRunning)); private DelegateCommand _SingleTestCommand; public DelegateCommand SingleTestCommand => _SingleTestCommand ?? (_SingleTestCommand = new DelegateCommand(ExecuteSingleTestCommand)); private DelegateCommand _ExportCSVCommand; public DelegateCommand ExportCSVCommand => _ExportCSVCommand ?? (_ExportCSVCommand = new DelegateCommand(ExecuteExportCSVCommand, () => !IsRunning).ObservesProperty(() => IsRunning)); private DelegateCommand _ClearDataCommand; public DelegateCommand ClearDataCommand => _ClearDataCommand ?? (_ClearDataCommand = new DelegateCommand(ExecuteClearDataCommand, () => !IsRunning).ObservesProperty(() => IsRunning)); #endregion /// /// 保存配置 /// private void SaveConfig() { try { var ConfigModel = new PickScrewAccuracyAnalyzerrConfigModel { RepeatCount = this.RepeatCount, MoveSpeed = this.MoveSpeed, IsScrewProvide1 = this.IsScrewProvide1, IsScrewProvide2 = this.IsScrewProvide2, }; FileHelper.WriteJsonFile(ConfigModel, FilePath.PickScrewAccuracyAnalyzerrConfigurationPath); } catch (Exception ex) { LogHelper.WriteLogError("保存视觉动态精度分析仪配置时出错", ex); } } private void ExecuteLoadedCommand() { try { var res = FileHelper.ReadJsonFile(FilePath.PickScrewAccuracyAnalyzerrConfigurationPath); this.RepeatCount = res.RepeatCount; this.MoveSpeed = res.MoveSpeed; this.IsScrewProvide2 = res.IsScrewProvide2; this.IsScrewProvide1 = res.IsScrewProvide1; } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void ExecuteSingleTestCommand() { } private async void ExecuteStartTestCommand() { IsRunning = true; _cts = new CancellationTokenSource(); CurrentProgress = 0; SuccessCount = 0; SuccessRate = 0; FailCount = 0; TestResults = new ObservableCollection(); Message = "测试进行中..."; PlcAddressConfig addressConfig = _configService.GetPlcAddresses(); OpcUaClientPLC plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC; try { var result = System.Windows.MessageBox.Show("确定进行连续测试吗?", "提示", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question); if (result != System.Windows.MessageBoxResult.Yes) { return; } if (Robot == null || !Robot.IsConnected) { SendTaskMessage("机器人未连接,无法示教!"); return; } //为机器人设置移动速度 await Robot.CalibParameAsync(new PickInfo(), MoveSpeed, 0, false, 0, 0); while (CurrentProgress < RepeatCount) { if (IsScrewProvide1) { while(!await plc.ReadNodeAsync(addressConfig.ScrewProvide1.Address)) { Message = "螺丝供料机1未到位,可暂停等待"; if (_cts.Token.IsCancellationRequested) { Message = "测试已取消!"; break; } } } if (IsScrewProvide2) { while (!await plc.ReadNodeAsync(addressConfig.ScrewProvide2.Address)) { Message = "螺丝供料机2未到位,可暂停等待"; if (_cts.Token.IsCancellationRequested) { Message = "测试已取消!"; break; } } } DateTime startTime = DateTime.Now; if (_cts.Token.IsCancellationRequested) { Message = "测试已取消!"; break; } bool isSuccess1 = await _torqueService.Throw_Screw_Async(Robot, plc, addressConfig, Points, MoveSpeed); if (!isSuccess1) { SendTaskMessage("机器人移动到抛料点失败!"); return; } if (_cts.Token.IsCancellationRequested) { Message = "测试已取消!"; break; } bool isSuccess2 = await _torqueService.Pick_Screw_Async(Robot, plc, addressConfig, Points); if (isSuccess2) { SuccessCount++; CycleTime = DateTime.Now.Subtract(startTime).TotalSeconds; TestResults.Add(new PickDynamicTestResult() { Index = CurrentProgress + 1, X_Position = Points.TorquePoints[1].X_Position, Y_Position = Points.TorquePoints[1].Y_Position, Z_Position = Points.TorquePoints[1].Z_Position_Start, Timestamp = DateTime.Now, CycleTime = this.CycleTime, IsPickSuccess = isSuccess2 }); } else { FailCount++; CycleTime = DateTime.Now.Subtract(startTime).TotalSeconds; TestResults.Add(new PickDynamicTestResult() { Index = CurrentProgress + 1, X_Position = Points.TorquePoints[1].X_Position, Y_Position = Points.TorquePoints[1].Y_Position, Z_Position = Points.TorquePoints[1].Z_Position_Start, Timestamp = DateTime.Now, CycleTime = this.CycleTime, IsPickSuccess = isSuccess2 }); } CurrentProgress++; SuccessRate = (double)SuccessCount / CurrentProgress * 100; SendTaskMessage($"测试进行中... {CurrentProgress}/{RepeatCount}"); } if (CurrentProgress >= RepeatCount) { Message = "测试完成!"; } } catch (Exception ex) { LogHelper.WriteLogError("取料重复测试时出错!", ex); } finally { await _torqueService.Throw_Screw_Async(Robot, plc, addressConfig, Points, MoveSpeed); IsRunning = false; } } public void SendTaskMessage(string msg) { App.Current.Dispatcher.Invoke(() => { _eventAggregator.GetEvent().Publish(new MessageParameter() { Msg = msg, Duration = 1 }); }); } private void ExecuteExportCSVCommand() { if (TestResults == null || TestResults.Count == 0) { SendTaskMessage("无测试数据,无法导出。"); return; } try { var dlg = new Microsoft.Win32.SaveFileDialog { DefaultExt = "csv", Filter = "CSV 文件 (*.csv)|*.csv|所有文件 (*.*)|*.*", FileName = "TestResults.csv", Title = "保存测试结果为 CSV" }; bool? dlgResult = dlg.ShowDialog(); if (dlgResult != true) return; string path = dlg.FileName; if (File.Exists(path)) { File.Delete(path); } using (StreamWriter sw = new StreamWriter(path, true)) { //初始化文件,写入标题行 sw.WriteLine("序号,状态,位置X,位置Y,位置Z,循环时间,时间戳"); foreach (var item in TestResults) { sw.WriteLine($"{item.Index},{item.IsPickSuccess},{item.X_Position},{item.Y_Position},{item.Z_Position},{item.CycleTime},{item.Timestamp}"); } } } catch (Exception ex) { MessageBox.Show("写入数据失败" + ex); } } private void ExecuteClearDataCommand() { TestResults.Clear(); } #region 继承 public string Title { get; set; } = "动态取料测试"; public event Action RequestClose; public bool CanCloseDialog() { return true; } public void OnDialogClosed() { SaveConfig(); } public void OnDialogOpened(IDialogParameters parameters) { if (parameters.ContainsKey("PickScrewPoint") && parameters.ContainsKey("Robot")) { Points = parameters.GetValue("PickScrewPoint"); Robot = parameters.GetValue("Robot"); } } #endregion } }