| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811 |
- using System;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Threading.Tasks;
- using TeamAAS.Feeder.Interfaces;
- using TeamAAS.Feeder.Models;
- using TeamAAS.Feeder.UI;
- using TeamAAS.Feeder.Enums;
- namespace TeamAAS.ViewModels
- {
- public partial class SettingViewModel
- {
- public ObservableCollection<FeederInfo> Feeders { get; }
- private System.ComponentModel.PropertyChangedEventHandler _feederInfoHandler;
- private FeederInfo _selectedFeeder;
- public FeederInfo SelectedFeeder
- {
- get { return _selectedFeeder; }
- set
- {
- if (SetProperty(ref _selectedFeeder, value))
- {
- // 监听选中供料器的品牌变化:品牌决定连接方式约束与调试页
- if (_feederInfoHandler == null)
- {
- _feederInfoHandler = (s, e) =>
- {
- if (e.PropertyName == nameof(FeederInfo.FeederBrand))
- {
- // Team 品牌只支持 TCP 连接
- if (_selectedFeeder?.FeederBrand == FeederBrand.Team &&
- _selectedFeeder.ConnectType != FeederConnectType.TCP)
- {
- _selectedFeeder.ConnectType = FeederConnectType.TCP;
- }
- RaisePropertyChanged(nameof(ShowSerialConnection));
- RefreshFeederDebugHost();
- }
- };
- }
- if (_selectedFeeder != null)
- {
- _selectedFeeder.PropertyChanged -= _feederInfoHandler;
- _selectedFeeder.PropertyChanged += _feederInfoHandler;
- }
- RaisePropertyChanged(nameof(HasSelectedFeeder));
- RaisePropertyChanged(nameof(CurrentAction));
- RaisePropertyChanged(nameof(HasConnectedDevice));
- RaisePropertyChanged(nameof(CurrentSequences));
- RaisePropertyChanged(nameof(ShowSerialConnection));
- SelectedSequence = _selectedFeeder?.Sequences?.FirstOrDefault();
- RefreshFeederDebugHost();
- }
- }
- }
- private object _currentFeederDebugPage;
- /// <summary>品牌专属调试页(由 [Feeder] 特性 DebugPageType 创建);null = 使用通用手动调试面板</summary>
- public object CurrentFeederDebugPage
- {
- get { return _currentFeederDebugPage; }
- private set
- {
- if (SetProperty(ref _currentFeederDebugPage, value))
- RaisePropertyChanged(nameof(HasFeederCustomPage));
- }
- }
- /// <summary>选中品牌是否声明了专属调试页(true=显示专属页,false=显示通用手动调试面板)</summary>
- public bool HasFeederCustomPage => _currentFeederDebugPage != null;
- /// <summary>是否显示串口连接参数(Team 品牌仅支持 TCP,不显示)</summary>
- public bool ShowSerialConnection => _selectedFeeder != null && _selectedFeeder.FeederBrand != FeederBrand.Team;
- /// <summary>按选中的供料器刷新调试区:有专属页则创建并绑定,否则回退通用手动调试面板</summary>
- private void RefreshFeederDebugHost()
- {
- (_currentFeederDebugPage as IFeederDebugPage)?.UnbindFeeder();
- CurrentFeederDebugPage = null;
- if (_selectedFeeder == null) return;
- try
- {
- var feeder = _feederManager.GetOrCreateDevice(_selectedFeeder);
- if (feeder == null) return;
- CurrentFeederDebugPage = FeederDebugPageFactory.Create(feeder);
- }
- catch (Exception ex)
- {
- System.Diagnostics.Debug.WriteLine($"加载供料器调试页失败: {ex.Message}");
- }
- }
- public bool HasSelectedFeeder => _selectedFeeder != null;
- private IFeeder _activeDevice;
- public bool HasConnectedDevice => _activeDevice?.IsConnected ?? false;
- #region 调试属性
- public int[] VibrationSetList { get; } = Enumerable.Range(1, 11).ToArray();
- public string[] ActionLetterList { get; } = { "← A 左", "↙ B 左下", "↖ C 左上", "↓ D 下", "↑ E 上", "→ F 右", "↘ G 右下", "↗ H 右上", "⤨ I 散开", "⇔ J 水平聚集", "⇕ K 垂直聚集" };
- public WaveShape[] WaveShapeList { get; } = { WaveShape.None, WaveShape.SignWave, WaveShape.SawToothWave, WaveShape.TriangleWave };
- private int _selectedVibrationSetIndex;
- public int SelectedVibrationSetIndex
- {
- get { return _selectedVibrationSetIndex; }
- set
- {
- if (SetProperty(ref _selectedVibrationSetIndex, value))
- RaisePropertyChanged(nameof(CurrentAction));
- }
- }
- private int _selectedActionIndex;
- public int SelectedActionIndex
- {
- get { return _selectedActionIndex; }
- set
- {
- if (SetProperty(ref _selectedActionIndex, value))
- RaisePropertyChanged(nameof(CurrentAction));
- }
- }
- private int _currentDuration = 500;
- public int CurrentDuration
- {
- get { return _currentDuration; }
- set { SetProperty(ref _currentDuration, value); }
- }
- public SingleActionParam CurrentAction
- {
- get
- {
- if (SelectedFeeder == null || SelectedFeeder.ActionGroups == null) return null;
- int idx = SelectedVibrationSetIndex < 0 ? 0 : SelectedVibrationSetIndex > 10 ? 10 : SelectedVibrationSetIndex;
- return SelectedFeeder.ActionGroups[idx];
- }
- }
- private bool _isSyncChanging;
- public bool IsSyncChanging
- {
- get { return _isSyncChanging; }
- set { SetProperty(ref _isSyncChanging, value); }
- }
- private int _globalAmplitude = 50;
- public int GlobalAmplitude
- {
- get { return _globalAmplitude; }
- set
- {
- if (SetProperty(ref _globalAmplitude, value) && IsSyncChanging && CurrentAction != null)
- {
- CurrentAction.Motor1.Amplitude = (ushort)value;
- CurrentAction.Motor2.Amplitude = (ushort)value;
- CurrentAction.Motor3.Amplitude = (ushort)value;
- CurrentAction.Motor4.Amplitude = (ushort)value;
- }
- }
- }
- private int _globalFrequency = 100;
- public int GlobalFrequency
- {
- get { return _globalFrequency; }
- set
- {
- if (SetProperty(ref _globalFrequency, value) && IsSyncChanging && CurrentAction != null)
- {
- CurrentAction.Motor1.Frequency = (ushort)value;
- CurrentAction.Motor2.Frequency = (ushort)value;
- CurrentAction.Motor3.Frequency = (ushort)value;
- CurrentAction.Motor4.Frequency = (ushort)value;
- }
- }
- }
- private string _feederStatusText = "未连接";
- public string FeederStatusText
- {
- get { return _feederStatusText; }
- set { SetProperty(ref _feederStatusText, value); }
- }
- #endregion
- private void AddFeeder()
- {
- try
- {
- int maxNo = Feeders.Count > 0 ? Feeders.Max(f => f.FeederNo) : 0;
- var newFeeder = new FeederInfo
- {
- FeederNo = maxNo + 1,
- FeederName = $"供料器{maxNo + 1}",
- };
- _feederManager.Add(newFeeder);
- RefreshFeederList();
- SelectedFeeder = Feeders.FirstOrDefault(f => f.Id == newFeeder.Id);
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("添加供料器失败", ex);
- }
- }
- private void DeleteFeeder()
- {
- if (SelectedFeeder == null) return;
- if (!DialogHelper.ConfirmYesNo(
- $"确认删除 \"{SelectedFeeder.FeederName}\" 吗?",
- "确认删除"))
- {
- return;
- }
- try
- {
- _feederManager.Remove(SelectedFeeder.Id);
- RefreshFeederList();
- SelectedFeeder = null;
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("删除供料器失败", ex);
- }
- }
- private void SaveFeederConfig()
- {
- try
- {
- if (_feederManager.SaveConfig())
- DialogHelper.Success("供料器配置已保存");
- else
- DialogHelper.ShowError("供料器配置保存失败");
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("保存供料器配置失败", ex);
- }
- }
- public void ApplyFeederEdit(FeederInfo edited)
- {
- try
- {
- _feederManager.Add(edited);
- _feederManager.SaveConfig();
- RefreshFeederList();
- DialogHelper.Success("供料器属性已更新并保存");
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("应用供料器属性失败", ex);
- }
- }
- private void RefreshFeederList()
- {
- // 只恢复用户此前显式选中的供料器;列表加载本身不产生选中项
- //(WPF 选择器默认会自动选中首项,导致未选设备时调试页就被创建)
- Guid? selectedId = _selectedFeeder?.Id;
- Feeders.Clear();
- var infos = _feederManager.GetAll();
- foreach (var info in infos)
- Feeders.Add(info);
- if (selectedId.HasValue)
- SelectedFeeder = Feeders.FirstOrDefault(f => f.Id == selectedId.Value);
- DeleteFeederCommand?.RaiseCanExecuteChanged();
- }
- #region 硬件通讯
- private async Task ConnectFeederAsync()
- {
- if (SelectedFeeder == null) return;
- try
- {
- FeederStatusText = $"正在连接 {SelectedFeeder.FeederName} ({SelectedFeeder.IP}:{SelectedFeeder.Port})...";
- _activeDevice = _feederManager.GetOrCreateDevice(SelectedFeeder);
- _activeDevice.MessageExchanged += OnFeederMessageExchanged;
- _activeDevice.ConnectionChanged += (dev, online) =>
- {
- RaisePropertyChanged(nameof(HasConnectedDevice));
- FeederStatusText = online ? $"{dev.Name} 已就绪" : "连接断开";
- };
- await _activeDevice.ConnectAsync();
- AppLogger.Info($"供料器已连接: {SelectedFeeder.FeederName} ({SelectedFeeder.IP}:{SelectedFeeder.Port})", "Feeder");
- FeederStatusText = $"{SelectedFeeder.FeederName} 已就绪";
- RaisePropertyChanged(nameof(HasConnectedDevice));
- }
- catch (Exception ex)
- {
- FeederStatusText = "连接失败";
- DialogHelper.ShowError("供料器连接失败", ex);
- }
- }
- private async void DisconnectFeeder()
- {
- if (_activeDevice == null) return;
- try
- {
- await _activeDevice.DisconnectAsync();
- AppLogger.Info($"供料器已断开: {_activeDevice.Name}", "Feeder");
- FeederStatusText = "已断开";
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("断开连接失败", ex);
- }
- RaisePropertyChanged(nameof(HasConnectedDevice));
- }
- private async void ToggleBacklight()
- {
- if (_activeDevice == null || !_activeDevice.IsConnected)
- {
- DialogHelper.Warning("请先连接供料器");
- return;
- }
- try
- {
- bool currentlyOn = await _activeDevice.QueryBacklightAsync();
- if (currentlyOn)
- {
- await _activeDevice.CloseBacklightAsync();
- SelectedFeeder.IsBacklightOn = false;
- FeederStatusText = "背光关";
- }
- else
- {
- await _activeDevice.OpenBacklightAsync();
- SelectedFeeder.IsBacklightOn = true;
- FeederStatusText = "背光开";
- }
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("背光控制失败", ex);
- }
- }
- private async Task ExecuteDirectionAsync(int dir)
- {
- if (_activeDevice == null || !_activeDevice.IsConnected)
- {
- DialogHelper.Warning("请先连接供料器");
- return;
- }
- try
- {
- var action = (FeederAction)dir;
- FeederStatusText = $"执行方向: {action}";
- await _activeDevice.RunDirectionAsync(action, CurrentDuration);
- AppLogger.Info($"供料器方向执行: {action} 持续 {CurrentDuration}ms", "Feeder");
- FeederStatusText = $"方向 {action} 执行完成";
- }
- catch (Exception ex)
- {
- FeederStatusText = "执行失败";
- DialogHelper.ShowError("方向执行失败", ex);
- }
- }
- private async Task StopFeederAsync()
- {
- if (_activeDevice == null) return;
- try
- {
- await _activeDevice.StopAsync();
- FeederStatusText = "停止振动";
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("停止失败", ex);
- }
- }
- private async Task ExecuteCurrentActionAsync()
- {
- if (_activeDevice == null || !_activeDevice.IsConnected)
- {
- DialogHelper.Warning("请先连接供料器");
- return;
- }
- try
- {
- // 先下载当前振动集参数到设备
- await _activeDevice.SetActionParamAsync(SelectedVibrationSetIndex, CurrentAction);
- // 再执行
- await _activeDevice.RunDirectionAsync((FeederAction)SelectedActionIndex, CurrentDuration);
- FeederStatusText = $"执行振动集 {SelectedVibrationSetIndex + 1} ({ActionLetterList[SelectedActionIndex]})";
- }
- catch (Exception ex)
- {
- FeederStatusText = "执行失败";
- DialogHelper.ShowError("执行动作失败", ex);
- }
- }
- private async Task DownloadFeederParamsAsync()
- {
- if (_activeDevice == null || !_activeDevice.IsConnected)
- {
- DialogHelper.Warning("请先连接供料器");
- return;
- }
- if (SelectedFeeder == null) return;
- try
- {
- FeederStatusText = "下载参数中...";
- await _activeDevice.DownloadAllParamsAsync(SelectedFeeder);
- AppLogger.Info($"供料器下载振动集参数: {SelectedFeeder.FeederName}", "Feeder");
- await _activeDevice.SaveToDeviceAsync();
- FeederStatusText = "参数已下载并保存到设备";
- DialogHelper.Success("参数已下载到设备");
- }
- catch (Exception ex)
- {
- FeederStatusText = "下载失败";
- DialogHelper.ShowError("下载参数失败", ex);
- }
- }
- #endregion
- #region 配方
- private ObservableCollection<FeederRecipe> _recipes = new ObservableCollection<FeederRecipe>();
- public ObservableCollection<FeederRecipe> Recipes
- {
- get { return _recipes; }
- set { SetProperty(ref _recipes, value); }
- }
- private FeederRecipe _selectedRecipe;
- public FeederRecipe SelectedRecipe
- {
- get { return _selectedRecipe; }
- set { SetProperty(ref _selectedRecipe, value); }
- }
- private void SaveCurrentAsRecipe()
- {
- if (SelectedFeeder == null)
- {
- DialogHelper.Warning("请先选择供料器");
- return;
- }
- string name = DialogHelper.Input("配方名称", "保存配方", SelectedFeeder.FeederName + "_配方");
- if (string.IsNullOrWhiteSpace(name)) return;
- if (Recipes.Any(r => string.Equals(r.RecipeName, name, StringComparison.OrdinalIgnoreCase)))
- {
- DialogHelper.Warning($"配方 \"{name}\" 已存在,请换一个名称");
- return;
- }
- try
- {
- var recipe = new FeederRecipe
- {
- RecipeName = name,
- Description = $"从 {SelectedFeeder.FeederName} 导出",
- Brand = SelectedFeeder.FeederBrand,
- };
- foreach (var g in SelectedFeeder.ActionGroups)
- recipe.ActionGroups.Add(g.Clone());
- foreach (var s in SelectedFeeder.Sequences)
- recipe.Sequences.Add(s.Clone());
- if (_feederManager.SaveRecipe(recipe))
- {
- DialogHelper.Success($"配方 \"{name}\" 已保存");
- RefreshRecipeList();
- }
- else
- {
- DialogHelper.ShowError("配方保存失败");
- }
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("保存配方失败", ex);
- }
- }
- private void LoadRecipeToCurrent()
- {
- if (SelectedRecipe == null)
- {
- DialogHelper.Warning("请先选择配方");
- return;
- }
- if (SelectedFeeder == null)
- {
- DialogHelper.Warning("请先选择供料器");
- return;
- }
- try
- {
- SelectedFeeder.ActionGroups.Clear();
- foreach (var g in SelectedRecipe.ActionGroups)
- SelectedFeeder.ActionGroups.Add(g.Clone());
- SelectedFeeder.Sequences.Clear();
- foreach (var s in SelectedRecipe.Sequences)
- SelectedFeeder.Sequences.Add(s.Clone());
- SelectedSequence = SelectedFeeder.Sequences.FirstOrDefault();
- RaisePropertyChanged(nameof(CurrentSequences));
- SaveFeederConfigSilent();
- DialogHelper.Success($"配方 \"{SelectedRecipe.RecipeName}\" 已加载到 {SelectedFeeder.FeederName}");
- }
- catch (Exception ex)
- {
- DialogHelper.ShowError("加载配方失败", ex);
- }
- }
- private async Task ApplyRecipeToDevice()
- {
- if (SelectedRecipe == null)
- {
- DialogHelper.Warning("请先选择配方");
- return;
- }
- if (_activeDevice == null || !_activeDevice.IsConnected)
- {
- DialogHelper.Warning("请先连接供料器");
- return;
- }
- try
- {
- FeederStatusText = $"应用配方 \"{SelectedRecipe.RecipeName}\"...";
- for (int i = 0; i < SelectedRecipe.ActionGroups.Count && i < 11; i++)
- {
- await _activeDevice.SetActionParamAsync(i, SelectedRecipe.ActionGroups[i]);
- }
- await _activeDevice.SaveToDeviceAsync();
- FeederStatusText = "配方已应用到设备";
- DialogHelper.Success("配方已下载到设备");
- }
- catch (Exception ex)
- {
- FeederStatusText = "配方应用失败";
- DialogHelper.ShowError("配方应用失败", ex);
- }
- }
- private void DeleteSelectedRecipe()
- {
- if (SelectedRecipe == null) return;
- if (!DialogHelper.ConfirmYesNo($"确认删除配方 \"{SelectedRecipe.RecipeName}\" 吗?", "确认删除"))
- return;
- if (_feederManager.DeleteRecipe(SelectedRecipe.RecipeName))
- {
- DialogHelper.Success("配方已删除");
- RefreshRecipeList();
- }
- }
- private void RefreshRecipeList()
- {
- Recipes.Clear();
- foreach (var r in _feederManager.GetRecipes())
- Recipes.Add(r);
- }
- #endregion
- #region 序列集(送料流程)
- public ObservableCollection<SequenceSet> CurrentSequences
- => _selectedFeeder?.Sequences;
- private SequenceSet _selectedSequence;
- public SequenceSet SelectedSequence
- {
- get { return _selectedSequence; }
- set
- {
- if (SetProperty(ref _selectedSequence, value))
- {
- RaisePropertyChanged(nameof(CurrentSequenceSteps));
- }
- }
- }
- public ObservableCollection<SequenceStep> CurrentSequenceSteps
- => _selectedSequence?.Steps;
- private SequenceStep _selectedStep;
- public SequenceStep SelectedStep
- {
- get { return _selectedStep; }
- set
- {
- if (SetProperty(ref _selectedStep, value))
- RaisePropertyChanged(nameof(HasSelectedStep));
- }
- }
- public bool HasSelectedStep => _selectedStep != null;
- private string _sequenceStatusText = "";
- public string SequenceStatusText
- {
- get { return _sequenceStatusText; }
- set { SetProperty(ref _sequenceStatusText, value); }
- }
- private System.Threading.CancellationTokenSource _sequenceCts;
- private void AddSequence()
- {
- if (SelectedFeeder == null)
- {
- DialogHelper.Warning("请先选择供料器");
- return;
- }
- string name = DialogHelper.Input("流程名称", "新建流程", "新流程");
- if (string.IsNullOrWhiteSpace(name)) return;
- if (SelectedFeeder.Sequences.Any(s => string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase)))
- {
- DialogHelper.Warning($"流程 \"{name}\" 已存在,请换一个名称");
- return;
- }
- var seq = new SequenceSet { Name = name };
- SelectedFeeder.Sequences.Add(seq);
- SelectedSequence = seq;
- RenumberSteps();
- SaveFeederConfigSilent();
- }
- private void DeleteSequence()
- {
- if (SelectedSequence == null) return;
- if (!DialogHelper.ConfirmYesNo($"确认删除流程 \"{SelectedSequence.Name}\" 吗?", "确认"))
- return;
- var list = CurrentSequences;
- int idx = list.IndexOf(SelectedSequence);
- list.Remove(SelectedSequence);
- SelectedSequence = list.Count > 0 ? list[Math.Min(idx, list.Count - 1)] : null;
- RaisePropertyChanged(nameof(CurrentSequenceSteps));
- RenumberSteps();
- SaveFeederConfigSilent();
- }
- private void RenameSequence()
- {
- if (SelectedSequence == null) return;
- string name = DialogHelper.Input("流程名称", "重命名", SelectedSequence.Name);
- if (string.IsNullOrWhiteSpace(name)) return;
- if (!string.Equals(name, SelectedSequence.Name, StringComparison.OrdinalIgnoreCase) &&
- SelectedFeeder.Sequences.Any(s => string.Equals(s.Name, name, StringComparison.OrdinalIgnoreCase)))
- {
- DialogHelper.Warning($"流程 \"{name}\" 已存在,请换一个名称");
- return;
- }
- SelectedSequence.Name = name;
- SaveFeederConfigSilent();
- }
- private void AddSequenceStep(string type)
- {
- if (SelectedSequence == null)
- {
- DialogHelper.Warning("请先选择或创建一个流程");
- return;
- }
- var step = new SequenceStep
- {
- StepType = type == "Delay" ? SequenceStepType.Delay : SequenceStepType.Direction,
- TimeMs = type == "Delay" ? 300 : 500,
- Direction = FeederAction.Right,
- Enabled = true,
- };
- SelectedSequence.Steps.Add(step);
- RenumberSteps();
- SaveFeederConfigSilent();
- }
- private void MoveUpStep()
- {
- if (SelectedStep == null || CurrentSequenceSteps == null) return;
- int idx = CurrentSequenceSteps.IndexOf(SelectedStep);
- if (idx <= 0) return;
- CurrentSequenceSteps.Move(idx, idx - 1);
- SelectedStep = CurrentSequenceSteps[idx - 1];
- RenumberSteps();
- SaveFeederConfigSilent();
- }
- private void MoveDownStep()
- {
- if (SelectedStep == null || CurrentSequenceSteps == null) return;
- int idx = CurrentSequenceSteps.IndexOf(SelectedStep);
- if (idx < 0 || idx >= CurrentSequenceSteps.Count - 1) return;
- CurrentSequenceSteps.Move(idx, idx + 1);
- SelectedStep = CurrentSequenceSteps[idx + 1];
- RenumberSteps();
- SaveFeederConfigSilent();
- }
- private void DeleteStep()
- {
- if (SelectedStep == null || CurrentSequenceSteps == null) return;
- CurrentSequenceSteps.Remove(SelectedStep);
- SelectedStep = null;
- RenumberSteps();
- SaveFeederConfigSilent();
- }
- private void RenumberSteps()
- {
- if (CurrentSequenceSteps == null) return;
- for (int i = 0; i < CurrentSequenceSteps.Count; i++)
- CurrentSequenceSteps[i].Index = i + 1;
- }
- private void SaveFeederConfigSilent()
- {
- if (SelectedFeeder == null) return;
- try { _feederManager.SaveConfig(); } catch { }
- }
- private async Task ExecuteSequenceAsync()
- {
- if (SelectedSequence == null)
- {
- DialogHelper.Warning("请先选择流程");
- return;
- }
- if (_activeDevice == null || !_activeDevice.IsConnected)
- {
- DialogHelper.Warning("请先连接供料器");
- return;
- }
- _sequenceCts = new System.Threading.CancellationTokenSource();
- var token = _sequenceCts.Token;
- try
- {
- int stepIdx = 0;
- foreach (var step in SelectedSequence.Steps)
- {
- stepIdx++;
- if (!step.Enabled) continue;
- if (token.IsCancellationRequested) break;
- if (step.StepType == SequenceStepType.Delay)
- {
- SequenceStatusText = $"等待 {step.TimeMs}ms... ({stepIdx}/{SelectedSequence.Steps.Count})";
- await Task.Delay(step.TimeMs, token);
- }
- else
- {
- SequenceStatusText = $"{step.Direction} 振动 {step.TimeMs}ms ({stepIdx}/{SelectedSequence.Steps.Count})";
- await _activeDevice.RunDirectionAsync(step.Direction, step.TimeMs > 0 ? step.TimeMs : (int?)null);
- }
- }
- if (token.IsCancellationRequested)
- SequenceStatusText = "流程已停止";
- else
- SequenceStatusText = "流程执行完成";
- }
- catch (TaskCanceledException)
- {
- SequenceStatusText = "流程已停止";
- }
- catch (Exception ex)
- {
- SequenceStatusText = "流程执行异常";
- DialogHelper.ShowError("流程执行异常", ex);
- }
- }
- private void StopSequence()
- {
- _sequenceCts?.Cancel();
- try { _activeDevice?.StopAsync(); } catch { }
- }
- #endregion
- }
- }
|