using Cognex.VisionPro; using Cognex.VisionPro.ToolBlock; using System; using System.Collections.Generic; using System.Linq; using System.Threading; using TeamAAS.FlowEditor.Execution; using TeamAAS.FlowEditor.Models; using TeamAAS.FlowEditor.Plugins; using TeamAAS.Camera.Images; using Plugins.Vpp.Converters; using Plugins.Vpp.Models; using Plugins.Vpp.Views; namespace Plugins.Vpp { [Serializable] [Plugin("VPP工具块", PluginCategory.Vpp模块, typeof(VppToolBlockModel), typeof(VppToolBlockEditView), "CogOutline", NodeShape = NodeCategory.Normal, Description = "Cognex VisionPro ToolBlock 节点 - 配置输入映射后执行 VPP 工具链")] public class VppToolBlockPlugin : BasePlugin { /// /// 动态输出声明(跑之前就能被绑定树索引): /// 1) ToolBlock 的输出终端——在工具块编辑器里配置后即确定,直接读实时终端名/类型; /// 2) 输出图层N——数量取决于工具块内部工具,只有运行后才知道,读上次运行学习到的快照 ; /// 3) 固定状态输出 结果。 /// public override List DeclareOutputs() { var list = new List(); // 1) 工具块输出终端(名称 + 声明类型) try { if (Model?.ToolBlock?.Outputs != null) { foreach (CogToolBlockTerminal t in Model.ToolBlock.Outputs) { if (t == null || string.IsNullOrEmpty(t.Name)) continue; list.Add(new OutputField(t.Name, t.ValueType ?? typeof(object))); } } } catch { } // 2) 运行图层(读取上次运行学习到的数量快照) int layers = Model?.LastLayerCount ?? 0; for (int i = 1; i <= layers; i++) list.Add(new OutputField($"输出图层{i}", typeof(ICogRecord))); // 3) 固定状态 list.Add(new OutputField("结果", typeof(bool))); return list; } public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary results) { results = new Dictionary(); try { Log(3, $"开始执行 VPP 工具块,输入映射 {Model.InputMappings?.Count ?? 0} 项"); // 1. 配置输入映射 foreach (var mapping in Model.InputMappings) { if (string.IsNullOrWhiteSpace(mapping.InputName)) continue; object value = null; if (!string.IsNullOrWhiteSpace(mapping.Source?.Formula)) value = RegistryOrDebug.ResolveFormula(GetModel.FlowId, mapping.Source.Formula); else value = mapping.Source?.Value; // GenImage → ICogImage(VisionPro 工具需要 ICogImage 输入) if (value is GenImage genImg) value = GenImageConverter.ToCogImage(genImg); var input = Model.ToolBlock.Inputs[mapping.InputName]; if (input != null) { input.Value = value; Log(4, $"输入终端[{mapping.InputName}] ← {(value?.GetType().Name ?? "null")}"); } else { Log(2, $"工具块不存在输入终端[{mapping.InputName}],已跳过", TeamAAS.LogLevel.Warning); } } // 2. 运行 ToolBlock Model.ToolBlock.Run(); Log(3, $"工具块运行结束,Result={Model.ToolBlock.RunStatus.Result}"); // 3. 收集输出 foreach (CogToolBlockTerminal output in Model.ToolBlock.Outputs) { results[output.Name] = output.Value; Log(4, $"输出终端[{output.Name}] = {output.Value}"); } // 4. 收集图层(RunRecord 的 SubRecords) var record = Model.ToolBlock.CreateLastRunRecord(); int layerCount = record?.SubRecords?.Count ?? 0; if (record?.SubRecords != null) { for (int i = 0; i < record.SubRecords.Count; i++) { results[$"输出图层{i + 1}"] = record.SubRecords[i]; } } // 学习并持久化图层数量,供下次 DeclareOutputs 在跑之前声明 输出图层N if (layerCount != Model.LastLayerCount) Model.LastLayerCount = layerCount; Log(3, $"收集输出图层 {layerCount} 个"); // 5. 检查结果 if (Model.ToolBlock.RunStatus.Result != CogToolResultConstants.Accept) { results["VPP异常"] = $"VP反馈: {Model.ToolBlock.RunStatus.Result}"; results["结果"] = false; Log(1, $"工具块未通过: {Model.ToolBlock.RunStatus.Result}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } results["结果"] = true; Log(2, $"工具块执行成功,图层 {layerCount} 个"); return NodeRunStatus.Success; } catch (Exception ex) { results["VPP异常"] = ex.Message; results["结果"] = false; Log(1, $"工具块执行异常: {ex.Message}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } } } }