using System; using System.Collections.Generic; using System.Threading; using TeamAAS.FlowEditor.Execution; using TeamAAS.FlowEditor.Models; using TeamAAS.FlowEditor.Plugins; using Plugins.Vm.Models; using Plugins.Vm.Views; namespace Plugins.Vm { /// /// VM(海康 VisionMaster)流程/工具块节点。镜像 VppToolBlockPlugin 的行为: /// 配置输入映射 → 运行 VM 流程 → 收集输出终端与图层。所有 VM SDK 调用经 适配层。 /// [Serializable] [Plugin("VM工具块", PluginCategory.Vm模块, typeof(VmToolBlockModel), typeof(VmToolBlockEditView), "CogOutline", NodeShape = NodeCategory.Normal, Description = "海康 VisionMaster 流程节点 - 双击用 VM 自带界面配置流程,运行时执行 VM 方案")] public class VmToolBlockPlugin : BasePlugin { /// /// 动态输出声明(跑之前就能被绑定树索引): /// 1) 用户声明的输出终端名(); /// 2) 输出图层N——数量取决于 VM 流程内部,运行后学习到的快照 ; /// 3) 固定状态输出 结果。 /// public override List DeclareOutputs() { var list = new List(); if (Model?.OutputNames != null) { foreach (var name in Model.OutputNames) if (!string.IsNullOrWhiteSpace(name)) list.Add(new OutputField(name, typeof(object))); } int layers = Model?.LastLayerCount ?? 0; for (int i = 1; i <= layers; i++) list.Add(new OutputField($"输出图层{i}", typeof(object))); list.Add(new OutputField("结果", typeof(bool))); return list; } public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary results) { results = new Dictionary(); try { Log(3, $"开始执行 VM 流程[{Model.ProcedureName}],输入映射 {Model.InputMappings?.Count ?? 0} 项"); // 加载方案/流程(句柄缓存在模型的 [NonSerialized] 字段) // 方案路径/流程名变化时自动重载(调试期改方案后无需重启软件) if (Model.Solution != null && (!string.Equals(Model.LoadedSolutionPath, Model.SolutionPath, StringComparison.OrdinalIgnoreCase) || !string.Equals(Model.LoadedProcedureName, Model.ProcedureName, StringComparison.Ordinal))) { Model.Solution = null; Model.Procedure = null; } if (Model.Solution == null && !string.IsNullOrWhiteSpace(Model.SolutionPath)) { Model.Solution = VmRuntime.LoadSolution(Model.SolutionPath); Model.LoadedSolutionPath = Model.SolutionPath; Model.Procedure = null; } if (Model.Procedure == null) { Model.Procedure = VmRuntime.GetProcedure(Model.Solution, Model.ProcedureName); Model.LoadedProcedureName = Model.ProcedureName; } // 1. 输入映射 var inputs = new Dictionary(); foreach (var mapping in Model.InputMappings ?? new List()) { if (string.IsNullOrWhiteSpace(mapping.InputName)) continue; object value = !string.IsNullOrWhiteSpace(mapping.Source?.Formula) ? RegistryOrDebug.ResolveFormula(GetModel.FlowId, mapping.Source.Formula) : mapping.Source?.Value; inputs[mapping.InputName] = value; Log(4, $"输入终端[{mapping.InputName}] ← {(value?.GetType().Name ?? "null")}"); } VmRuntime.SetInputs(Model.Procedure, inputs); // 2. 运行 bool accept = VmRuntime.Run(Model.Procedure); Log(3, $"VM 流程运行结束,Accept={accept}"); // 3. 输出终端 var outputs = VmRuntime.GetOutputs(Model.Procedure) ?? new Dictionary(); foreach (var kv in outputs) { results[kv.Key] = kv.Value; Log(4, $"输出终端[{kv.Key}] = {kv.Value}"); } // 4. 输出图层,并学习图层数量供下次 DeclareOutputs 预声明 var layerList = VmRuntime.GetLayers(Model.Procedure) ?? new List(); for (int i = 0; i < layerList.Count; i++) results[$"输出图层{i + 1}"] = layerList[i]; if (layerList.Count != Model.LastLayerCount) Model.LastLayerCount = layerList.Count; Log(3, $"收集输出图层 {layerList.Count} 个"); // 4.5 图层发布到视觉显示总线:VM流程编辑器的视觉显示/图层筛选可直接查看 try { var args = new TeamAAS.Vision.LayerPublishArgs { FlowId = GetModel.FlowId, NodeName = GetModel.NodeName, RunStamp = "0", }; for (int i = 0; i < layerList.Count; i++) { if (layerList[i] == null) continue; var name = layerList.Count == 1 ? "图像" : $"图层{i + 1}"; args.Layers.Add(new TeamAAS.Vision.LayerItem( name, i == 0 ? TeamAAS.Vision.LayerKind.Image : TeamAAS.Vision.LayerKind.Other, layerList[i], owned: false)); } if (args.Layers.Count > 0) TeamAAS.Vision.VisionLayerStore.Instance.Publish(args); } catch { /* 显示发布失败不影响流程 */ } // 5. 结果 if (!accept) { results["VM异常"] = "VM 流程未通过"; results["结果"] = false; Log(1, "VM 流程未通过", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } results["结果"] = true; Log(2, $"VM 流程执行成功,图层 {layerList.Count} 个"); return NodeRunStatus.Success; } catch (Exception ex) { results["VM异常"] = ex.Message; results["结果"] = false; Log(1, $"VM 流程执行异常: {ex.Message}", TeamAAS.LogLevel.Error); return NodeRunStatus.Failed; } } } }