| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150 |
- 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
- {
- /// <summary>
- /// VM(海康 VisionMaster)流程/工具块节点。镜像 VppToolBlockPlugin 的行为:
- /// 配置输入映射 → 运行 VM 流程 → 收集输出终端与图层。所有 VM SDK 调用经 <see cref="VmRuntime"/> 适配层。
- /// </summary>
- [Serializable]
- [Plugin("VM工具块", PluginCategory.Vm模块, typeof(VmToolBlockModel), typeof(VmToolBlockEditView),
- "CogOutline",
- NodeShape = NodeCategory.Normal, Description = "海康 VisionMaster 流程节点 - 双击用 VM 自带界面配置流程,运行时执行 VM 方案")]
- public class VmToolBlockPlugin : BasePlugin<VmToolBlockModel>
- {
- /// <summary>
- /// 动态输出声明(跑之前就能被绑定树索引):
- /// 1) 用户声明的输出终端名(<see cref="VmToolBlockModel.OutputNames"/>);
- /// 2) 输出图层N——数量取决于 VM 流程内部,运行后学习到的快照 <see cref="VmToolBlockModel.LastLayerCount"/>;
- /// 3) 固定状态输出 结果。
- /// </summary>
- public override List<OutputField> DeclareOutputs()
- {
- var list = new List<OutputField>();
- 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<string, object> results)
- {
- results = new Dictionary<string, object>();
- 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<string, object>();
- foreach (var mapping in Model.InputMappings ?? new List<VmInputMapping>())
- {
- 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<string, object>();
- 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<object>();
- 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;
- }
- }
- }
- }
|