FeederDebugViewModel.cs 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. using System;
  2. using System.Collections.ObjectModel;
  3. using System.Linq;
  4. using System.Threading;
  5. using System.Threading.Tasks;
  6. using Prism.Commands;
  7. using Prism.Mvvm;
  8. using TeamAAS.Feeder.Enums;
  9. using TeamAAS.Feeder.Interfaces;
  10. using TeamAAS.Feeder.Models;
  11. namespace TeamAAS.Feeder.UI
  12. {
  13. /// <summary>
  14. /// 通用(Team 品牌)供料器调试页的视图模型:从宿主 SettingViewModel 下沉而来(Phase 2 迁移)。
  15. /// 绑定一个 <see cref="IFeeder"/> 设备实例 + 其 <see cref="FeederInfo"/> 配置,直接调用设备 API。
  16. /// IFeederManager 经 TeamAAS.Global.ServiceRegistry 拉取(避免 Feeder 库反向依赖 TeamAAS.Core)。
  17. /// 方向/振动集/序列集/料斗IO/输入触发/系统参数/背光 全部在此,与硬件库调试页范式一致。
  18. /// </summary>
  19. public class FeederDebugViewModel : BindableBase
  20. {
  21. private const string LogSource = "Feeder";
  22. private IFeeder _feeder;
  23. private FeederInfo _info;
  24. private IFeederManager _manager;
  25. private CancellationTokenSource _sequenceCts;
  26. public FeederDebugViewModel()
  27. {
  28. FeederDirectionCommand = new DelegateCommand<object>(async p => await ExecuteDirectionAsync(Convert.ToInt32(p)));
  29. StopFeederActionCommand = new DelegateCommand(async () => await StopFeederAsync());
  30. ToggleBacklightCommand = new DelegateCommand(async () => await ToggleBacklightAsync());
  31. ExecuteActionCommand = new DelegateCommand(async () => await ExecuteCurrentActionAsync());
  32. DownloadParamCommand = new DelegateCommand(async () => await DownloadFeederParamsAsync());
  33. AddSequenceCommand = new DelegateCommand(AddSequence);
  34. DeleteSequenceCommand = new DelegateCommand(DeleteSequence);
  35. RenameSequenceCommand = new DelegateCommand(RenameSequence);
  36. AddSequenceStepCommand = new DelegateCommand<string>(AddSequenceStep);
  37. MoveUpStepCommand = new DelegateCommand(MoveUpStep);
  38. MoveDownStepCommand = new DelegateCommand(MoveDownStep);
  39. DeleteStepCommand = new DelegateCommand(DeleteStep);
  40. ExecuteSequenceCommand = new DelegateCommand(async () => await ExecuteSequenceAsync());
  41. StopSequenceCommand = new DelegateCommand(StopSequence);
  42. ReadHopperParamCommand = new DelegateCommand(async () => await ReadHopperParamAsync());
  43. WriteHopperParamCommand = new DelegateCommand(async () => await WriteHopperParamAsync());
  44. RunHopperOutputCommand = new DelegateCommand(async () => await RunHopperOutputAsync());
  45. StopHopperOutputCommand = new DelegateCommand(async () => await StopHopperOutputAsync());
  46. ReadInputTriggerCommand = new DelegateCommand(async () => await ReadInputTriggerAsync());
  47. WriteInputTriggerCommand = new DelegateCommand(async () => await WriteInputTriggerAsync());
  48. ReadSystemParamCommand = new DelegateCommand(async () => await ReadSystemParamAsync());
  49. WriteSystemParamCommand = new DelegateCommand(async () => await WriteSystemParamAsync());
  50. }
  51. /// <summary>绑定供料器设备(页面装载/选中时由 IFeederDebugPage.BindFeeder 调用)。</summary>
  52. public void Bind(IFeeder feeder)
  53. {
  54. _feeder = feeder;
  55. try { _manager = TeamAAS.Global.ServiceRegistry.Default.GetService<IFeederManager>(); }
  56. catch { _manager = null; }
  57. _info = null;
  58. if (_feeder != null && _manager != null)
  59. {
  60. try { _info = _manager.GetAll().FirstOrDefault(f => f.Id == _feeder.Id); }
  61. catch { _info = null; }
  62. }
  63. SelectedSequence = _info?.Sequences?.FirstOrDefault();
  64. StatusText = _feeder == null ? "未连接" : (_feeder.IsConnected ? $"{_feeder.Name} 已就绪" : "未连接");
  65. RaisePropertyChanged(nameof(Info));
  66. RaisePropertyChanged(nameof(CurrentAction));
  67. RaisePropertyChanged(nameof(CurrentSequences));
  68. RaisePropertyChanged(nameof(HasSelectedStep));
  69. }
  70. /// <summary>解绑(切换供料器/页面卸载)。</summary>
  71. public void Unbind()
  72. {
  73. try { _sequenceCts?.Cancel(); } catch { }
  74. _feeder = null;
  75. _info = null;
  76. }
  77. private string _statusText = "未连接";
  78. public string StatusText { get { return _statusText; } set { SetProperty(ref _statusText, value); } }
  79. /// <summary>当前绑定供料器的配置模型(方向/振动集/序列/背光状态等的数据源);未绑定时为 null。</summary>
  80. public FeederInfo Info { get { return _info; } }
  81. private bool EnsureConnected()
  82. {
  83. if (_feeder == null || !_feeder.IsConnected)
  84. {
  85. TeamAAS.DialogHelper.Warning("请先连接供料器");
  86. return false;
  87. }
  88. return true;
  89. }
  90. private void SaveSilent()
  91. {
  92. if (_info == null || _manager == null) return;
  93. try { _manager.SaveConfig(); } catch { }
  94. }
  95. #region 振动集 / 方向
  96. public int[] VibrationSetList { get; } = Enumerable.Range(1, 11).ToArray();
  97. public string[] ActionLetterList { get; } = { "← A 左", "↙ B 左下", "↖ C 左上", "↓ D 下", "↑ E 上", "→ F 右", "↘ G 右下", "↗ H 右上", "⤨ I 散开", "⇔ J 水平聚集", "⇕ K 垂直聚集" };
  98. private int _selectedVibrationSetIndex;
  99. public int SelectedVibrationSetIndex
  100. {
  101. get { return _selectedVibrationSetIndex; }
  102. set { if (SetProperty(ref _selectedVibrationSetIndex, value)) RaisePropertyChanged(nameof(CurrentAction)); }
  103. }
  104. private int _selectedActionIndex;
  105. public int SelectedActionIndex
  106. {
  107. get { return _selectedActionIndex; }
  108. set { if (SetProperty(ref _selectedActionIndex, value)) RaisePropertyChanged(nameof(CurrentAction)); }
  109. }
  110. private int _currentDuration = 500;
  111. public int CurrentDuration { get { return _currentDuration; } set { SetProperty(ref _currentDuration, value); } }
  112. public SingleActionParam CurrentAction
  113. {
  114. get
  115. {
  116. if (_info == null || _info.ActionGroups == null) return null;
  117. int idx = SelectedVibrationSetIndex < 0 ? 0 : SelectedVibrationSetIndex > 10 ? 10 : SelectedVibrationSetIndex;
  118. return _info.ActionGroups[idx];
  119. }
  120. }
  121. private bool _isSyncChanging;
  122. public bool IsSyncChanging { get { return _isSyncChanging; } set { SetProperty(ref _isSyncChanging, value); } }
  123. private int _globalAmplitude = 50;
  124. public int GlobalAmplitude
  125. {
  126. get { return _globalAmplitude; }
  127. set
  128. {
  129. if (SetProperty(ref _globalAmplitude, value) && IsSyncChanging && CurrentAction != null)
  130. {
  131. CurrentAction.Motor1.Amplitude = (ushort)value;
  132. CurrentAction.Motor2.Amplitude = (ushort)value;
  133. CurrentAction.Motor3.Amplitude = (ushort)value;
  134. CurrentAction.Motor4.Amplitude = (ushort)value;
  135. }
  136. }
  137. }
  138. private int _globalFrequency = 100;
  139. public int GlobalFrequency
  140. {
  141. get { return _globalFrequency; }
  142. set
  143. {
  144. if (SetProperty(ref _globalFrequency, value) && IsSyncChanging && CurrentAction != null)
  145. {
  146. CurrentAction.Motor1.Frequency = (ushort)value;
  147. CurrentAction.Motor2.Frequency = (ushort)value;
  148. CurrentAction.Motor3.Frequency = (ushort)value;
  149. CurrentAction.Motor4.Frequency = (ushort)value;
  150. }
  151. }
  152. }
  153. public DelegateCommand<object> FeederDirectionCommand { get; }
  154. public DelegateCommand StopFeederActionCommand { get; }
  155. public DelegateCommand ToggleBacklightCommand { get; }
  156. public DelegateCommand ExecuteActionCommand { get; }
  157. public DelegateCommand DownloadParamCommand { get; }
  158. private async Task ExecuteDirectionAsync(int dir)
  159. {
  160. if (!EnsureConnected()) return;
  161. try
  162. {
  163. var action = (FeederAction)dir;
  164. StatusText = $"执行方向: {action}";
  165. await _feeder.RunDirectionAsync(action, CurrentDuration);
  166. TeamAAS.AppLogger.Info($"供料器方向执行: {action} 持续 {CurrentDuration}ms", LogSource);
  167. StatusText = $"方向 {action} 执行完成";
  168. }
  169. catch (Exception ex) { StatusText = "执行失败"; TeamAAS.DialogHelper.ShowError("方向执行失败", ex); }
  170. }
  171. private async Task StopFeederAsync()
  172. {
  173. if (_feeder == null) return;
  174. try { await _feeder.StopAsync(); StatusText = "停止振动"; }
  175. catch (Exception ex) { TeamAAS.DialogHelper.ShowError("停止失败", ex); }
  176. }
  177. private async Task ToggleBacklightAsync()
  178. {
  179. if (!EnsureConnected()) return;
  180. try
  181. {
  182. bool on = await _feeder.QueryBacklightAsync();
  183. if (on) { await _feeder.CloseBacklightAsync(); if (_info != null) _info.IsBacklightOn = false; StatusText = "背光关"; }
  184. else { await _feeder.OpenBacklightAsync(); if (_info != null) _info.IsBacklightOn = true; StatusText = "背光开"; }
  185. RaisePropertyChanged(nameof(Info));
  186. }
  187. catch (Exception ex) { TeamAAS.DialogHelper.ShowError("背光控制失败", ex); }
  188. }
  189. private async Task ExecuteCurrentActionAsync()
  190. {
  191. if (!EnsureConnected()) return;
  192. try
  193. {
  194. await _feeder.SetActionParamAsync(SelectedVibrationSetIndex, CurrentAction);
  195. await _feeder.RunDirectionAsync((FeederAction)SelectedActionIndex, CurrentDuration);
  196. StatusText = $"执行振动集 {SelectedVibrationSetIndex + 1} ({ActionLetterList[SelectedActionIndex]})";
  197. }
  198. catch (Exception ex) { StatusText = "执行失败"; TeamAAS.DialogHelper.ShowError("执行动作失败", ex); }
  199. }
  200. private async Task DownloadFeederParamsAsync()
  201. {
  202. if (!EnsureConnected() || _info == null) return;
  203. try
  204. {
  205. StatusText = "下载参数中...";
  206. await _feeder.DownloadAllParamsAsync(_info);
  207. TeamAAS.AppLogger.Info($"供料器下载振动集参数: {_info.FeederName}", LogSource);
  208. await _feeder.SaveToDeviceAsync();
  209. StatusText = "参数已下载并保存到设备";
  210. TeamAAS.DialogHelper.Success("参数已下载到设备");
  211. }
  212. catch (Exception ex) { StatusText = "下载失败"; TeamAAS.DialogHelper.ShowError("下载参数失败", ex); }
  213. }
  214. #endregion
  215. #region 序列集(送料流程)
  216. public ObservableCollection<SequenceSet> CurrentSequences => _info?.Sequences;
  217. private SequenceSet _selectedSequence;
  218. public SequenceSet SelectedSequence
  219. {
  220. get { return _selectedSequence; }
  221. set { if (SetProperty(ref _selectedSequence, value)) RaisePropertyChanged(nameof(CurrentSequenceSteps)); }
  222. }
  223. public ObservableCollection<SequenceStep> CurrentSequenceSteps => _selectedSequence?.Steps;
  224. private SequenceStep _selectedStep;
  225. public SequenceStep SelectedStep
  226. {
  227. get { return _selectedStep; }
  228. set { if (SetProperty(ref _selectedStep, value)) RaisePropertyChanged(nameof(HasSelectedStep)); }
  229. }
  230. public bool HasSelectedStep => _selectedStep != null;
  231. private string _sequenceStatusText = "";
  232. public string SequenceStatusText { get { return _sequenceStatusText; } set { SetProperty(ref _sequenceStatusText, value); } }
  233. public DelegateCommand AddSequenceCommand { get; }
  234. public DelegateCommand DeleteSequenceCommand { get; }
  235. public DelegateCommand RenameSequenceCommand { get; }
  236. public DelegateCommand<string> AddSequenceStepCommand { get; }
  237. public DelegateCommand MoveUpStepCommand { get; }
  238. public DelegateCommand MoveDownStepCommand { get; }
  239. public DelegateCommand DeleteStepCommand { get; }
  240. public DelegateCommand ExecuteSequenceCommand { get; }
  241. public DelegateCommand StopSequenceCommand { get; }
  242. private void AddSequence()
  243. {
  244. if (_info == null) { TeamAAS.DialogHelper.Warning("请先选择供料器"); return; }
  245. string name = TeamAAS.DialogHelper.Input("流程名称", "新建流程", "新流程");
  246. if (string.IsNullOrWhiteSpace(name)) return;
  247. if (_info.Sequences.Any(s => string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase)))
  248. { TeamAAS.DialogHelper.Warning($"流程 \"{name}\" 已存在,请换一个名称"); return; }
  249. var seq = new SequenceSet { Name = name };
  250. _info.Sequences.Add(seq);
  251. SelectedSequence = seq;
  252. RenumberSteps();
  253. SaveSilent();
  254. }
  255. private void DeleteSequence()
  256. {
  257. if (SelectedSequence == null) return;
  258. if (!TeamAAS.DialogHelper.ConfirmYesNo($"确认删除流程 \"{SelectedSequence.Name}\" 吗?", "确认")) return;
  259. var list = CurrentSequences;
  260. int idx = list.IndexOf(SelectedSequence);
  261. list.Remove(SelectedSequence);
  262. SelectedSequence = list.Count > 0 ? list[Math.Min(idx, list.Count - 1)] : null;
  263. RaisePropertyChanged(nameof(CurrentSequenceSteps));
  264. RenumberSteps();
  265. SaveSilent();
  266. }
  267. private void RenameSequence()
  268. {
  269. if (SelectedSequence == null || _info == null) return;
  270. string name = TeamAAS.DialogHelper.Input("流程名称", "重命名", SelectedSequence.Name);
  271. if (string.IsNullOrWhiteSpace(name)) return;
  272. if (!string.Equals(name, SelectedSequence.Name, StringComparison.OrdinalIgnoreCase) &&
  273. _info.Sequences.Any(s => string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase)))
  274. { TeamAAS.DialogHelper.Warning($"流程 \"{name}\" 已存在,请换一个名称"); return; }
  275. SelectedSequence.Name = name;
  276. SaveSilent();
  277. }
  278. private void AddSequenceStep(string type)
  279. {
  280. if (SelectedSequence == null) { TeamAAS.DialogHelper.Warning("请先选择或创建一个流程"); return; }
  281. var step = new SequenceStep
  282. {
  283. StepType = type == "Delay" ? SequenceStepType.Delay : SequenceStepType.Direction,
  284. TimeMs = type == "Delay" ? 300 : 500,
  285. Direction = FeederAction.Right,
  286. Enabled = true,
  287. };
  288. SelectedSequence.Steps.Add(step);
  289. RenumberSteps();
  290. SaveSilent();
  291. }
  292. private void MoveUpStep()
  293. {
  294. if (SelectedStep == null || CurrentSequenceSteps == null) return;
  295. int idx = CurrentSequenceSteps.IndexOf(SelectedStep);
  296. if (idx <= 0) return;
  297. CurrentSequenceSteps.Move(idx, idx - 1);
  298. SelectedStep = CurrentSequenceSteps[idx - 1];
  299. RenumberSteps();
  300. SaveSilent();
  301. }
  302. private void MoveDownStep()
  303. {
  304. if (SelectedStep == null || CurrentSequenceSteps == null) return;
  305. int idx = CurrentSequenceSteps.IndexOf(SelectedStep);
  306. if (idx < 0 || idx >= CurrentSequenceSteps.Count - 1) return;
  307. CurrentSequenceSteps.Move(idx, idx + 1);
  308. SelectedStep = CurrentSequenceSteps[idx + 1];
  309. RenumberSteps();
  310. SaveSilent();
  311. }
  312. private void DeleteStep()
  313. {
  314. if (SelectedStep == null || CurrentSequenceSteps == null) return;
  315. CurrentSequenceSteps.Remove(SelectedStep);
  316. SelectedStep = null;
  317. RenumberSteps();
  318. SaveSilent();
  319. }
  320. private void RenumberSteps()
  321. {
  322. if (CurrentSequenceSteps == null) return;
  323. for (int i = 0; i < CurrentSequenceSteps.Count; i++)
  324. CurrentSequenceSteps[i].Index = i + 1;
  325. }
  326. private async Task ExecuteSequenceAsync()
  327. {
  328. if (SelectedSequence == null) { TeamAAS.DialogHelper.Warning("请先选择流程"); return; }
  329. if (!EnsureConnected()) return;
  330. _sequenceCts = new CancellationTokenSource();
  331. var token = _sequenceCts.Token;
  332. try
  333. {
  334. int stepIdx = 0;
  335. foreach (var step in SelectedSequence.Steps)
  336. {
  337. stepIdx++;
  338. if (!step.Enabled) continue;
  339. if (token.IsCancellationRequested) break;
  340. if (step.StepType == SequenceStepType.Delay)
  341. {
  342. SequenceStatusText = $"等待 {step.TimeMs}ms... ({stepIdx}/{SelectedSequence.Steps.Count})";
  343. await Task.Delay(step.TimeMs, token);
  344. }
  345. else
  346. {
  347. SequenceStatusText = $"{step.Direction} 振动 {step.TimeMs}ms ({stepIdx}/{SelectedSequence.Steps.Count})";
  348. await _feeder.RunDirectionAsync(step.Direction, step.TimeMs > 0 ? step.TimeMs : (int?)null);
  349. }
  350. }
  351. SequenceStatusText = token.IsCancellationRequested ? "流程已停止" : "流程执行完成";
  352. }
  353. catch (TaskCanceledException) { SequenceStatusText = "流程已停止"; }
  354. catch (Exception ex) { SequenceStatusText = "流程执行异常"; TeamAAS.DialogHelper.ShowError("流程执行异常", ex); }
  355. }
  356. private void StopSequence()
  357. {
  358. try { _sequenceCts?.Cancel(); } catch { }
  359. try { var t = _feeder?.StopAsync(); } catch { }
  360. }
  361. #endregion
  362. #region 料斗输入输出
  363. public int[] HopperGroupList { get; } = Enumerable.Range(0, 26).ToArray();
  364. private int _selectedHopperGroup;
  365. public int SelectedHopperGroup { get { return _selectedHopperGroup; } set { SetProperty(ref _selectedHopperGroup, value); } }
  366. private HopperOutputParam _hopperParam = new HopperOutputParam();
  367. public HopperOutputParam HopperParam { get { return _hopperParam; } set { SetProperty(ref _hopperParam, value); } }
  368. public DelegateCommand ReadHopperParamCommand { get; }
  369. public DelegateCommand WriteHopperParamCommand { get; }
  370. public DelegateCommand RunHopperOutputCommand { get; }
  371. public DelegateCommand StopHopperOutputCommand { get; }
  372. private async Task ReadHopperParamAsync()
  373. {
  374. if (!EnsureConnected()) return;
  375. try
  376. {
  377. StatusText = $"读取料斗输出参数(组 {SelectedHopperGroup})...";
  378. HopperParam = await _feeder.GetHopperParamAsync(SelectedHopperGroup);
  379. StatusText = "料斗输出参数已读取";
  380. }
  381. catch (Exception ex) { StatusText = "读取料斗参数失败"; TeamAAS.AppLogger.Error("读取料斗输出参数失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("读取料斗参数失败", ex); }
  382. }
  383. private async Task WriteHopperParamAsync()
  384. {
  385. if (!EnsureConnected()) return;
  386. try
  387. {
  388. StatusText = $"下载料斗输出参数(组 {SelectedHopperGroup})...";
  389. await _feeder.SetHopperParamAsync(SelectedHopperGroup, HopperParam);
  390. StatusText = "料斗输出参数已下载";
  391. TeamAAS.DialogHelper.Success("料斗输出参数已下载到设备");
  392. }
  393. catch (Exception ex) { StatusText = "下载料斗参数失败"; TeamAAS.AppLogger.Error("下载料斗输出参数失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("下载料斗参数失败", ex); }
  394. }
  395. private async Task RunHopperOutputAsync()
  396. {
  397. if (!EnsureConnected()) return;
  398. try
  399. {
  400. int id = SelectedHopperGroup + 1;
  401. StatusText = $"执行料斗动作 {id}...";
  402. await _feeder.RunHopperOutputAsync(id, HopperParam.HopperDuration > 0 ? HopperParam.HopperDuration : (int?)null);
  403. StatusText = $"料斗动作 {id} 执行完成";
  404. }
  405. catch (Exception ex) { StatusText = "料斗动作执行失败"; TeamAAS.AppLogger.Error("执行料斗动作失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("料斗动作执行失败", ex); }
  406. }
  407. private async Task StopHopperOutputAsync()
  408. {
  409. if (_feeder == null) return;
  410. try { await _feeder.StopHopperOutputAsync(); StatusText = "料斗振动已停止"; }
  411. catch (Exception ex) { TeamAAS.AppLogger.Error("停止料斗振动失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("停止料斗振动失败", ex); }
  412. }
  413. #endregion
  414. #region 输入触发序列ID
  415. private int _inputTrigger1;
  416. public int InputTrigger1 { get { return _inputTrigger1; } set { SetProperty(ref _inputTrigger1, value); } }
  417. private int _inputTrigger2;
  418. public int InputTrigger2 { get { return _inputTrigger2; } set { SetProperty(ref _inputTrigger2, value); } }
  419. public DelegateCommand ReadInputTriggerCommand { get; }
  420. public DelegateCommand WriteInputTriggerCommand { get; }
  421. private async Task ReadInputTriggerAsync()
  422. {
  423. if (!EnsureConnected()) return;
  424. try
  425. {
  426. InputTrigger1 = await _feeder.GetInputTriggerAsync(0);
  427. InputTrigger2 = await _feeder.GetInputTriggerAsync(1);
  428. StatusText = $"输入触发已读取: 输入1={InputTrigger1} 输入2={InputTrigger2}";
  429. }
  430. catch (Exception ex) { StatusText = "读取输入触发失败"; TeamAAS.AppLogger.Error("读取输入触发序列ID失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("读取输入触发失败", ex); }
  431. }
  432. private async Task WriteInputTriggerAsync()
  433. {
  434. if (!EnsureConnected()) return;
  435. try
  436. {
  437. await _feeder.SetInputTriggerAsync(0, InputTrigger1);
  438. await _feeder.SetInputTriggerAsync(1, InputTrigger2);
  439. StatusText = "输入触发已写入";
  440. TeamAAS.DialogHelper.Success("输入触发参数已写入设备");
  441. }
  442. catch (Exception ex) { StatusText = "写入输入触发失败"; TeamAAS.AppLogger.Error("写入输入触发序列ID失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("写入输入触发失败", ex); }
  443. }
  444. #endregion
  445. #region 系统参数(超时/背光)
  446. private FeederSystemParam _systemParam = new FeederSystemParam();
  447. public FeederSystemParam SystemParam { get { return _systemParam; } set { SetProperty(ref _systemParam, value); } }
  448. public DelegateCommand ReadSystemParamCommand { get; }
  449. public DelegateCommand WriteSystemParamCommand { get; }
  450. private async Task ReadSystemParamAsync()
  451. {
  452. if (!EnsureConnected()) return;
  453. try
  454. {
  455. StatusText = "读取系统参数...";
  456. SystemParam = await _feeder.GetSystemParamAsync();
  457. StatusText = "系统参数已读取";
  458. }
  459. catch (Exception ex) { StatusText = "读取系统参数失败"; TeamAAS.AppLogger.Error("读取供料器系统参数失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("读取系统参数失败", ex); }
  460. }
  461. private async Task WriteSystemParamAsync()
  462. {
  463. if (!EnsureConnected()) return;
  464. try
  465. {
  466. StatusText = "写入系统参数...";
  467. await _feeder.SetSystemParamAsync(SystemParam);
  468. StatusText = "系统参数已写入并保存";
  469. TeamAAS.DialogHelper.Success("系统参数已写入设备");
  470. }
  471. catch (Exception ex) { StatusText = "写入系统参数失败"; TeamAAS.AppLogger.Error("写入供料器系统参数失败", ex, LogSource); TeamAAS.DialogHelper.ShowError("写入系统参数失败", ex); }
  472. }
  473. #endregion
  474. }
  475. }