using System; using System.Collections.Generic; using VM.Core; namespace Plugins.Vm { /// /// 海康 VisionMaster SDK 适配层(唯一允许出现 VM SDK 调用的地方)。 /// 插件/模型/视图只依赖本类的 SDK 无关签名(object / Dictionary),更换/升级 VM 版本时只改这里。 /// /// 已接入 VM 4.4 的基础能力:加载方案、按名取流程、运行流程、关闭方案。 /// 仍为 TODO 的部分:VM 的输入/输出是“模块级”(各模块 ModuResult / 模块参数), /// 不像 Cognex ToolBlock 有统一的输入/输出终端,需按方案里实际用到的模块逐个对接。 /// public static class VmRuntime { /// VM SDK 是否可用(已引用 VM.Core)。 public static bool IsSdkAvailable => true; /// 当前已加载方案的路径。VmSolution 是进程级单例,用它做“同方案不重载”的守护。 private static string _loadedSolutionPath; /// /// 加载 VM 方案(.sol)。返回 单例(用 object 承载,避免上层依赖 SDK 类型)。 /// 加载后关闭各模块结果回调以提升运行效率(与 VM 官方示例一致)。 /// public static object LoadSolution(string solutionPath) { if (string.IsNullOrWhiteSpace(solutionPath)) throw new ArgumentException("VM 方案路径为空", nameof(solutionPath)); // 单例守护:同一 .sol 已加载则直接复用,避免多个 VM 节点/多次运行反复重载(VmSolution 为进程级单例) if (_loadedSolutionPath == solutionPath && VmSolution.Instance != null) return VmSolution.Instance; VmSolution.Load(solutionPath, ""); _loadedSolutionPath = solutionPath; var inst = VmSolution.Instance; try { inst?.DisableModulesCallback(); } catch { /* 某些方案无回调可关,忽略 */ } return inst; } /// 从已加载方案中按名取流程();不存在返回 null。 public static object GetProcedure(object solution, string procedureName) { if (string.IsNullOrWhiteSpace(procedureName)) return null; var inst = VmSolution.Instance; if (inst == null) return null; return inst[procedureName] as VmProcedure; } /// /// 设置流程输入。TODO:VM 输入为模块级——需按方案中具体模块(如图像源 ImageSource) /// 通过 VmSolution.Instance["流程名.模块名"] as XxxModuleTool 设参数/图像; /// 待明确各节点要喂的模块后补全(当前签名保留,先不抛异常以便流程能跑通)。 /// public static void SetInputs(object procedure, Dictionary inputs) { // TODO: 按模块写入 VM 输入 } /// 运行流程。返回是否成功执行(未抛异常即视为已运行)。 public static bool Run(object procedure) { var p = procedure as VmProcedure; if (p == null) return false; p.Run(); // TODO:VM 的“通过/不通过”按模块结果或 OK/NG 判定,非单一 RunStatus;接入后按方案约定返回。 return true; } /// /// 收集流程输出。TODO:VM 输出为模块级结果(如 pro.ModuResult.GetOutputImageV2("ImageData")、 /// 各模块 ModuResult 的字段)。需按方案里配置的“输出模块/结果名”逐个读取,接入后补全。 /// public static Dictionary GetOutputs(object procedure) { return new Dictionary(); } /// /// 收集运行图层/渲染源(配合 VmRenderControl.ModuleSource 显示)。TODO:接入后返回 VM 模块/图像数据集。 /// public static List GetLayers(object procedure) { return new List(); } /// 关闭并释放当前方案。 public static void Close() { try { VmSolution.Instance?.CloseSolution(); } catch { } _loadedSolutionPath = null; } // ───────────────────────────────────────────────────────────────── // 模块级结果读取(供"VM模块"算子节点使用;全部反射容错,缺能力时返回 null) // ───────────────────────────────────────────────────────────────── /// /// 读取流程运行后的模块结果:优先 GetOutputImageV2(图像类结果键),其次 GetOutputValue/GetResultValue。 /// key 为模块结果终端名(如 "ImageData"、"Score")。不可用时返回 null。 /// public static object GetModuleOutput(object procedure, string key) { if (procedure == null || string.IsNullOrWhiteSpace(key)) return null; try { var moduResult = procedure.GetType().GetProperty("ModuResult")?.GetValue(procedure) ?? procedure.GetType().GetField("ModuResult")?.GetValue(procedure); if (moduResult == null) return null; var type = moduResult.GetType(); foreach (var method in new[] { "GetOutputImageV2", "GetOutputValue", "GetResultValue" }) { var m = type.GetMethod(method, new[] { typeof(string) }); if (m == null) continue; try { var v = m.Invoke(moduResult, new[] { key }); if (v != null) return v; } catch { } } } catch { } return null; } } }