PickScrewAccuracyAnalyzerViewModel.cs 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. using MaterialDesignThemes.Wpf;
  2. using Newtonsoft.Json;
  3. using Prism.Commands;
  4. using Prism.Events;
  5. using Prism.Ioc;
  6. using Prism.Mvvm;
  7. using Prism.Regions;
  8. using Prism.Services.Dialogs;
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Collections.ObjectModel;
  12. using System.IO;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading;
  16. using System.Threading.Tasks;
  17. using System.Web.UI.WebControls;
  18. using System.Windows;
  19. using System.Windows.Threading;
  20. using TeamAAS_VP.Core;
  21. using TeamAAS_VP.Core.PLCs;
  22. using TeamAAS_VP.Events;
  23. using TeamAAS_VP.Interfaces;
  24. using TeamAAS_VP.Models;
  25. using TeamAAS_VP.Models.PLC;
  26. using TeamAAS_VP.Models.Torque;
  27. using TeamAAS_VP.Resources.Languages;
  28. using TeamAAS_VP.Services;
  29. using TeamAAS_VP.ViewModels.Product;
  30. using static TeamAAS_VP.ViewModels.Product.VisionDynamicAccuracyAnalyzerViewModel;
  31. namespace TeamAAS_VP.ViewModels.Home
  32. {
  33. public class PickScrewAccuracyAnalyzerViewModel : BindableBase, IDialogAware
  34. {
  35. IRegionManager _regionManager;
  36. IEventAggregator _eventAggregator;
  37. IContainerProvider _container;
  38. IDialogService _dialogService;
  39. IRobotService _robotService;
  40. ISystemDatabaseService _systemDatabaseService;
  41. IConfigService _configService;
  42. IPlcService _plcService;
  43. TorqueService _torqueService;
  44. //测试过程中控制取消的CTS
  45. CancellationTokenSource _cts;
  46. public PickScrewAccuracyAnalyzerViewModel(IRegionManager regionManager, IEventAggregator ea, IContainerProvider container,
  47. IDialogService dialogService, IRobotService robotService, ISystemDatabaseService systemDatabaseService,
  48. IConfigService configService, TorqueService torqueService, IPlcService plcService)
  49. {
  50. _eventAggregator = ea;
  51. _configService = configService;
  52. _container = container;
  53. _robotService = robotService;
  54. _torqueService = torqueService;
  55. _plcService = plcService;
  56. management = _container.Resolve<Management>();
  57. MessageQueue = new SnackbarMessageQueue(TimeSpan.FromSeconds(2));
  58. }
  59. #region 属性
  60. private SnackbarMessageQueue _MessageQueue;
  61. public SnackbarMessageQueue MessageQueue
  62. {
  63. get { return _MessageQueue; }
  64. set { SetProperty(ref _MessageQueue, value); }
  65. }
  66. private Management _management;
  67. public Management management
  68. {
  69. get { return _management; }
  70. set { SetProperty(ref _management, value); }
  71. }
  72. private int _MoveSpeed = 100;
  73. /// <summary>
  74. /// 移动速度
  75. /// </summary>
  76. public int MoveSpeed
  77. {
  78. get { return _MoveSpeed; }
  79. set { SetProperty(ref _MoveSpeed, value); }
  80. }
  81. private double _CycleTime;
  82. /// <summary>
  83. /// 单次的时长
  84. /// </summary>
  85. public double CycleTime
  86. {
  87. get { return _CycleTime; }
  88. set { SetProperty(ref _CycleTime, value); }
  89. }
  90. private int _RepeatCount = 10;
  91. /// <summary>
  92. /// 重复次数
  93. /// </summary>
  94. public int RepeatCount
  95. {
  96. get { return _RepeatCount; }
  97. set { SetProperty(ref _RepeatCount, value); }
  98. }
  99. private int _CurrentProgress;
  100. /// <summary>
  101. /// 当前进度
  102. /// </summary>
  103. public int CurrentProgress
  104. {
  105. get { return _CurrentProgress; }
  106. set { SetProperty(ref _CurrentProgress, value); }
  107. }
  108. private int _SuccessCount;
  109. /// <summary>
  110. /// 成功次数
  111. /// </summary>
  112. public int SuccessCount
  113. {
  114. get { return _SuccessCount; }
  115. set { SetProperty(ref _SuccessCount, value); }
  116. }
  117. private int _FailCount;
  118. /// <summary>
  119. /// 失败次数
  120. /// </summary>
  121. public int FailCount
  122. {
  123. get { return _FailCount; }
  124. set { SetProperty(ref _FailCount, value); }
  125. }
  126. private double _SuccessRate;
  127. /// <summary>
  128. /// 成功率
  129. /// </summary>
  130. public double SuccessRate
  131. {
  132. get { return _SuccessRate; }
  133. set { SetProperty(ref _SuccessRate, value); }
  134. }
  135. private string _Message = "等待开始...";
  136. public string Message
  137. {
  138. get { return _Message; }
  139. set { SetProperty(ref _Message, value); }
  140. }
  141. private bool _IsRunning;
  142. public bool IsRunning
  143. {
  144. get { return _IsRunning; }
  145. set { SetProperty(ref _IsRunning, value); }
  146. }
  147. private IRobot _Robot;
  148. public IRobot Robot
  149. {
  150. get { return _Robot; }
  151. set { SetProperty(ref _Robot, value); }
  152. }
  153. private ObservableCollection<PickDynamicTestResult> _TestResults;
  154. /// <summary>
  155. /// 测试结果列表
  156. /// </summary>
  157. public ObservableCollection<PickDynamicTestResult> TestResults
  158. {
  159. get { return _TestResults; }
  160. set { SetProperty(ref _TestResults, value); }
  161. }
  162. private RPoint _PointA = new RPoint();
  163. private TorqueProduceModel _Points;
  164. public TorqueProduceModel Points
  165. {
  166. get { return _Points; }
  167. set { SetProperty(ref _Points, value); }
  168. }
  169. private bool _IsScrewProvide2;
  170. public bool IsScrewProvide2
  171. {
  172. get { return _IsScrewProvide2; }
  173. set { SetProperty(ref _IsScrewProvide2, value); }
  174. }
  175. private bool _IsScrewProvide1;
  176. public bool IsScrewProvide1
  177. {
  178. get { return _IsScrewProvide1; }
  179. set { SetProperty(ref _IsScrewProvide1, value); }
  180. }
  181. #endregion
  182. #region 命令
  183. private DelegateCommand _StopTestCommand;
  184. public DelegateCommand StopTestCommand =>
  185. _StopTestCommand ?? (_StopTestCommand = new DelegateCommand(() => { _cts?.Cancel(); }, () => IsRunning).ObservesProperty(() => IsRunning));
  186. //暂停测试命令
  187. private DelegateCommand _PauseTestCommand;
  188. public DelegateCommand PauseTestCommand =>
  189. _PauseTestCommand ?? (_PauseTestCommand = new DelegateCommand(() => { _cts?.Cancel(); }, () => IsRunning).ObservesProperty(() => IsRunning));
  190. private DelegateCommand _LoadedCommand;
  191. public DelegateCommand LoadedCommand =>
  192. _LoadedCommand ?? (_LoadedCommand = new DelegateCommand(ExecuteLoadedCommand));
  193. private DelegateCommand _StartTestCommand;
  194. public DelegateCommand StartTestCommand =>
  195. _StartTestCommand ?? (_StartTestCommand = new DelegateCommand(ExecuteStartTestCommand).ObservesProperty(() => IsRunning));
  196. private DelegateCommand _SingleTestCommand;
  197. public DelegateCommand SingleTestCommand =>
  198. _SingleTestCommand ?? (_SingleTestCommand = new DelegateCommand(ExecuteSingleTestCommand));
  199. private DelegateCommand _ExportCSVCommand;
  200. public DelegateCommand ExportCSVCommand =>
  201. _ExportCSVCommand ?? (_ExportCSVCommand = new DelegateCommand(ExecuteExportCSVCommand, () => !IsRunning).ObservesProperty(() => IsRunning));
  202. private DelegateCommand _ClearDataCommand;
  203. public DelegateCommand ClearDataCommand =>
  204. _ClearDataCommand ?? (_ClearDataCommand = new DelegateCommand(ExecuteClearDataCommand, () => !IsRunning).ObservesProperty(() => IsRunning));
  205. #endregion
  206. /// <summary>
  207. /// 保存配置
  208. /// </summary>
  209. private void SaveConfig()
  210. {
  211. try
  212. {
  213. var ConfigModel = new PickScrewAccuracyAnalyzerrConfigModel
  214. {
  215. RepeatCount = this.RepeatCount,
  216. MoveSpeed = this.MoveSpeed,
  217. IsScrewProvide1 = this.IsScrewProvide1,
  218. IsScrewProvide2 = this.IsScrewProvide2,
  219. };
  220. FileHelper.WriteJsonFile(ConfigModel, FilePath.PickScrewAccuracyAnalyzerrConfigurationPath);
  221. }
  222. catch (Exception ex)
  223. {
  224. LogHelper.WriteLogError("保存视觉动态精度分析仪配置时出错", ex);
  225. }
  226. }
  227. private void ExecuteLoadedCommand()
  228. {
  229. try
  230. {
  231. var res = FileHelper.ReadJsonFile<PickScrewAccuracyAnalyzerrConfigModel>(FilePath.PickScrewAccuracyAnalyzerrConfigurationPath);
  232. this.RepeatCount = res.RepeatCount;
  233. this.MoveSpeed = res.MoveSpeed;
  234. this.IsScrewProvide2 = res.IsScrewProvide2;
  235. this.IsScrewProvide1 = res.IsScrewProvide1;
  236. }
  237. catch (Exception ex)
  238. {
  239. MessageBox.Show(ex.Message);
  240. }
  241. }
  242. private void ExecuteSingleTestCommand()
  243. {
  244. }
  245. private async void ExecuteStartTestCommand()
  246. {
  247. IsRunning = true;
  248. _cts = new CancellationTokenSource();
  249. CurrentProgress = 0;
  250. SuccessCount = 0;
  251. SuccessRate = 0;
  252. FailCount = 0;
  253. TestResults = new ObservableCollection<PickDynamicTestResult>();
  254. Message = "测试进行中...";
  255. PlcAddressConfig addressConfig = _configService.GetPlcAddresses();
  256. OpcUaClientPLC plc = _plcService.GetPlcByNumber(addressConfig.PlcNo) as OpcUaClientPLC;
  257. try
  258. {
  259. var result = System.Windows.MessageBox.Show("确定进行连续测试吗?", "提示", System.Windows.MessageBoxButton.YesNo, System.Windows.MessageBoxImage.Question);
  260. if (result != System.Windows.MessageBoxResult.Yes)
  261. {
  262. return;
  263. }
  264. if (Robot == null || !Robot.IsConnected)
  265. {
  266. SendTaskMessage("机器人未连接,无法示教!");
  267. return;
  268. }
  269. //为机器人设置移动速度
  270. await Robot.CalibParameAsync(new PickInfo(), MoveSpeed, 0, false, 0, 0);
  271. while (CurrentProgress < RepeatCount)
  272. {
  273. if (IsScrewProvide1)
  274. {
  275. while(!await plc.ReadNodeAsync<bool>(addressConfig.ScrewProvide1.Address))
  276. {
  277. Message = "螺丝供料机1未到位,可暂停等待";
  278. if (_cts.Token.IsCancellationRequested)
  279. {
  280. Message = "测试已取消!";
  281. break;
  282. }
  283. }
  284. }
  285. if (IsScrewProvide2)
  286. {
  287. while (!await plc.ReadNodeAsync<bool>(addressConfig.ScrewProvide2.Address))
  288. {
  289. Message = "螺丝供料机2未到位,可暂停等待";
  290. if (_cts.Token.IsCancellationRequested)
  291. {
  292. Message = "测试已取消!";
  293. break;
  294. }
  295. }
  296. }
  297. DateTime startTime = DateTime.Now;
  298. if (_cts.Token.IsCancellationRequested)
  299. {
  300. Message = "测试已取消!";
  301. break;
  302. }
  303. bool isSuccess1 = await _torqueService.Throw_Screw_Async(Robot, plc, addressConfig, Points, MoveSpeed);
  304. if (!isSuccess1)
  305. {
  306. SendTaskMessage("机器人移动到抛料点失败!");
  307. return;
  308. }
  309. if (_cts.Token.IsCancellationRequested)
  310. {
  311. Message = "测试已取消!";
  312. break;
  313. }
  314. bool isSuccess2 = await _torqueService.Pick_Screw_Async(Robot, plc, addressConfig, Points);
  315. if (isSuccess2)
  316. {
  317. SuccessCount++;
  318. CycleTime = DateTime.Now.Subtract(startTime).TotalSeconds;
  319. TestResults.Add(new PickDynamicTestResult()
  320. {
  321. Index = CurrentProgress + 1,
  322. X_Position = Points.TorquePoints[1].X_Position,
  323. Y_Position = Points.TorquePoints[1].Y_Position,
  324. Z_Position = Points.TorquePoints[1].Z_Position_Start,
  325. Timestamp = DateTime.Now,
  326. CycleTime = this.CycleTime,
  327. IsPickSuccess = isSuccess2
  328. });
  329. }
  330. else
  331. {
  332. FailCount++;
  333. CycleTime = DateTime.Now.Subtract(startTime).TotalSeconds;
  334. TestResults.Add(new PickDynamicTestResult()
  335. {
  336. Index = CurrentProgress + 1,
  337. X_Position = Points.TorquePoints[1].X_Position,
  338. Y_Position = Points.TorquePoints[1].Y_Position,
  339. Z_Position = Points.TorquePoints[1].Z_Position_Start,
  340. Timestamp = DateTime.Now,
  341. CycleTime = this.CycleTime,
  342. IsPickSuccess = isSuccess2
  343. });
  344. }
  345. CurrentProgress++;
  346. SuccessRate = (double)SuccessCount / CurrentProgress * 100;
  347. SendTaskMessage($"测试进行中... {CurrentProgress}/{RepeatCount}");
  348. }
  349. if (CurrentProgress >= RepeatCount)
  350. {
  351. Message = "测试完成!";
  352. }
  353. }
  354. catch (Exception ex)
  355. {
  356. LogHelper.WriteLogError("取料重复测试时出错!", ex);
  357. }
  358. finally
  359. {
  360. await _torqueService.Throw_Screw_Async(Robot, plc, addressConfig, Points, MoveSpeed);
  361. IsRunning = false;
  362. }
  363. }
  364. public void SendTaskMessage(string msg)
  365. {
  366. App.Current.Dispatcher.Invoke(() =>
  367. {
  368. _eventAggregator.GetEvent<SnackbarMessageNotification>().Publish(new MessageParameter() { Msg = msg, Duration = 1 });
  369. });
  370. }
  371. private void ExecuteExportCSVCommand()
  372. {
  373. if (TestResults == null || TestResults.Count == 0)
  374. {
  375. SendTaskMessage("无测试数据,无法导出。");
  376. return;
  377. }
  378. try
  379. {
  380. var dlg = new Microsoft.Win32.SaveFileDialog
  381. {
  382. DefaultExt = "csv",
  383. Filter = "CSV 文件 (*.csv)|*.csv|所有文件 (*.*)|*.*",
  384. FileName = "TestResults.csv",
  385. Title = "保存测试结果为 CSV"
  386. };
  387. bool? dlgResult = dlg.ShowDialog();
  388. if (dlgResult != true)
  389. return;
  390. string path = dlg.FileName;
  391. if (File.Exists(path))
  392. {
  393. File.Delete(path);
  394. }
  395. using (StreamWriter sw = new StreamWriter(path, true))
  396. {
  397. //初始化文件,写入标题行
  398. sw.WriteLine("序号,状态,位置X,位置Y,位置Z,循环时间,时间戳");
  399. foreach (var item in TestResults)
  400. {
  401. sw.WriteLine($"{item.Index},{item.IsPickSuccess},{item.X_Position},{item.Y_Position},{item.Z_Position},{item.CycleTime},{item.Timestamp}");
  402. }
  403. }
  404. }
  405. catch (Exception ex)
  406. {
  407. MessageBox.Show("写入数据失败" + ex);
  408. }
  409. }
  410. private void ExecuteClearDataCommand()
  411. {
  412. TestResults.Clear();
  413. }
  414. #region 继承
  415. public string Title { get; set; } = "动态取料测试";
  416. public event Action<IDialogResult> RequestClose;
  417. public bool CanCloseDialog()
  418. {
  419. return true;
  420. }
  421. public void OnDialogClosed()
  422. {
  423. SaveConfig();
  424. }
  425. public void OnDialogOpened(IDialogParameters parameters)
  426. {
  427. if (parameters.ContainsKey("PickScrewPoint") && parameters.ContainsKey("Robot"))
  428. {
  429. Points = parameters.GetValue<TorqueProduceModel>("PickScrewPoint");
  430. Robot = parameters.GetValue<IRobot>("Robot");
  431. }
  432. }
  433. #endregion
  434. }
  435. }