| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- using TeamAAS.Core;
- using TeamAAS.Feeder.Interfaces;
- using TeamAAS.FlowEditor.Models;
- using TeamAAS.FlowEditor.Plugins;
- using TeamAAS.Feeder.Models;
- using Plugins.Feeder.Models;
- namespace Plugins.Feeder
- {
- [Plugin("供料器送料", PluginCategory.硬件模块, typeof(FeederPluginModel),
- "PackageVariant")]
- [Serializable]
- public class FeederPlugin : BasePlugin<FeederPluginModel>
- {
- public override List<OutputField> DeclareOutputs() => new List<OutputField>
- {
- new OutputField("供料器", typeof(string)),
- new OutputField("流程", typeof(string)),
- new OutputField("执行步数", typeof(int)),
- new OutputField("结果", typeof(bool)),
- };
- public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
- {
- var res = new Dictionary<string, object>();
- results = res;
- // 统一失败出口:写 Error + 结果=false + 记 1 级错误日志(任何阈值都落盘)
- NodeRunStatus Fail(string message)
- {
- res["Error"] = message;
- res["结果"] = false;
- Log(1, $"供料器送料失败: {message}", TeamAAS.LogLevel.Error);
- return NodeRunStatus.Failed;
- }
- var mgr = Service<IFeederManager>();
- if (mgr == null)
- return Fail("FeederManager 未初始化");
- Log(3, $"开始送料,供料器={Model.FeederName}, 流程={Model.SequenceKey}");
- var info = mgr.GetAll().FirstOrDefault(f =>
- string.Equals(f.FeederName, Model.FeederName, StringComparison.OrdinalIgnoreCase));
- if (info == null)
- return Fail($"未找到供料器 \"{Model.FeederName}\"");
- res["供料器"] = info.FeederName;
- // SequenceKey 格式: "供料器名/流程名" 或纯 "流程名"
- var seqName = Model.SequenceKey;
- var slashIdx = seqName?.IndexOf('/') ?? -1;
- if (slashIdx >= 0) seqName = seqName.Substring(slashIdx + 1);
- var seq = info.Sequences.FirstOrDefault(s =>
- string.Equals(s.Name, seqName, StringComparison.OrdinalIgnoreCase));
- if (seq == null)
- return Fail($"供料器 \"{info.FeederName}\" 上不存在流程 \"{seqName}\"");
- res["流程"] = seq.Name;
- var enabledSteps = seq.Steps.Where(s => s.Enabled).ToList();
- res["执行步数"] = enabledSteps.Count;
- Log(4, $"流程 \"{seq.Name}\" 启用步骤 {enabledSteps.Count} 个");
- var device = mgr.GetOrCreateDevice(info);
- if (device == null)
- return Fail("创建设备实例失败");
- try
- {
- if (!device.IsConnected && Model.AutoConnect)
- {
- try { device.ConnectAsync().GetAwaiter().GetResult(); }
- catch (Exception ex)
- {
- return Fail($"连接供料器失败: {ex.Message}");
- }
- }
- if (!device.IsConnected)
- return Fail($"供料器 \"{info.FeederName}\" 未连接");
- int stepIdx = 0;
- foreach (var step in enabledSteps)
- {
- token.ThrowIfCancellationRequested();
- stepIdx++;
- if (step.StepType == SequenceStepType.Delay)
- {
- Log(4, $"第{stepIdx}步: 延时 {step.TimeMs}ms");
- Task.Delay(step.TimeMs, token).Wait(token);
- }
- else
- {
- try
- {
- Log(4, $"第{stepIdx}步: 方向={step.Direction}, 时长={step.TimeMs}ms");
- device.RunDirectionAsync(step.Direction, step.TimeMs)
- .GetAwaiter().GetResult();
- }
- catch (Exception ex)
- {
- return Fail($"第{stepIdx}步执行失败: {ex.Message}");
- }
- }
- }
- if (Model.StopWhenDone)
- {
- try { device.StopAsync().GetAwaiter().GetResult(); } catch { }
- }
- res["结果"] = true;
- Log(2, $"送料完成,供料器={info.FeederName}, 流程={seq.Name}, 执行 {enabledSteps.Count} 步");
- return NodeRunStatus.Success;
- }
- catch (OperationCanceledException)
- {
- try { device.StopAsync().GetAwaiter().GetResult(); } catch { }
- return Fail("用户取消");
- }
- catch (Exception ex)
- {
- try { device.StopAsync().GetAwaiter().GetResult(); } catch { }
- return Fail(ex.Message);
- }
- }
- }
- }
|