VmRuntime.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. using System;
  2. using System.Collections.Generic;
  3. using VM.Core;
  4. namespace Plugins.Vm
  5. {
  6. /// <summary>
  7. /// 海康 VisionMaster SDK 适配层(唯一允许出现 VM SDK 调用的地方)。
  8. /// 插件/模型/视图只依赖本类的 SDK 无关签名(object / Dictionary),更换/升级 VM 版本时只改这里。
  9. ///
  10. /// 已接入 VM 4.4 的基础能力:加载方案、按名取流程、运行流程、关闭方案。
  11. /// 仍为 TODO 的部分:VM 的输入/输出是“模块级”(各模块 ModuResult / 模块参数),
  12. /// 不像 Cognex ToolBlock 有统一的输入/输出终端,需按方案里实际用到的模块逐个对接。
  13. /// </summary>
  14. public static class VmRuntime
  15. {
  16. /// <summary>VM SDK 是否可用(已引用 VM.Core)。</summary>
  17. public static bool IsSdkAvailable => true;
  18. /// <summary>当前已加载方案的路径。VmSolution 是进程级单例,用它做“同方案不重载”的守护。</summary>
  19. private static string _loadedSolutionPath;
  20. /// <summary>
  21. /// 加载 VM 方案(.sol)。返回 <see cref="VmSolution"/> 单例(用 object 承载,避免上层依赖 SDK 类型)。
  22. /// 加载后关闭各模块结果回调以提升运行效率(与 VM 官方示例一致)。
  23. /// </summary>
  24. public static object LoadSolution(string solutionPath)
  25. {
  26. if (string.IsNullOrWhiteSpace(solutionPath))
  27. throw new ArgumentException("VM 方案路径为空", nameof(solutionPath));
  28. // 单例守护:同一 .sol 已加载则直接复用,避免多个 VM 节点/多次运行反复重载(VmSolution 为进程级单例)
  29. if (_loadedSolutionPath == solutionPath && VmSolution.Instance != null)
  30. return VmSolution.Instance;
  31. VmSolution.Load(solutionPath, "");
  32. _loadedSolutionPath = solutionPath;
  33. var inst = VmSolution.Instance;
  34. try { inst?.DisableModulesCallback(); } catch { /* 某些方案无回调可关,忽略 */ }
  35. return inst;
  36. }
  37. /// <summary>从已加载方案中按名取流程(<see cref="VmProcedure"/>);不存在返回 null。</summary>
  38. public static object GetProcedure(object solution, string procedureName)
  39. {
  40. if (string.IsNullOrWhiteSpace(procedureName)) return null;
  41. var inst = VmSolution.Instance;
  42. if (inst == null) return null;
  43. return inst[procedureName] as VmProcedure;
  44. }
  45. /// <summary>
  46. /// 设置流程输入。TODO:VM 输入为模块级——需按方案中具体模块(如图像源 ImageSource)
  47. /// 通过 <c>VmSolution.Instance["流程名.模块名"] as XxxModuleTool</c> 设参数/图像;
  48. /// 待明确各节点要喂的模块后补全(当前签名保留,先不抛异常以便流程能跑通)。
  49. /// </summary>
  50. public static void SetInputs(object procedure, Dictionary<string, object> inputs)
  51. {
  52. // TODO: 按模块写入 VM 输入
  53. }
  54. /// <summary>运行流程。返回是否成功执行(未抛异常即视为已运行)。</summary>
  55. public static bool Run(object procedure)
  56. {
  57. var p = procedure as VmProcedure;
  58. if (p == null) return false;
  59. p.Run();
  60. // TODO:VM 的“通过/不通过”按模块结果或 OK/NG 判定,非单一 RunStatus;接入后按方案约定返回。
  61. return true;
  62. }
  63. /// <summary>
  64. /// 收集流程输出。TODO:VM 输出为模块级结果(如 <c>pro.ModuResult.GetOutputImageV2("ImageData")</c>、
  65. /// 各模块 <c>ModuResult</c> 的字段)。需按方案里配置的“输出模块/结果名”逐个读取,接入后补全。
  66. /// </summary>
  67. public static Dictionary<string, object> GetOutputs(object procedure)
  68. {
  69. return new Dictionary<string, object>();
  70. }
  71. /// <summary>
  72. /// 收集运行图层/渲染源(配合 VmRenderControl.ModuleSource 显示)。TODO:接入后返回 VM 模块/图像数据集。
  73. /// </summary>
  74. public static List<object> GetLayers(object procedure)
  75. {
  76. return new List<object>();
  77. }
  78. /// <summary>关闭并释放当前方案。</summary>
  79. public static void Close()
  80. {
  81. try { VmSolution.Instance?.CloseSolution(); } catch { }
  82. _loadedSolutionPath = null;
  83. }
  84. // ─────────────────────────────────────────────────────────────────
  85. // 模块级结果读取(供"VM模块"算子节点使用;全部反射容错,缺能力时返回 null)
  86. // ─────────────────────────────────────────────────────────────────
  87. /// <summary>
  88. /// 读取流程运行后的模块结果:优先 GetOutputImageV2(图像类结果键),其次 GetOutputValue/GetResultValue。
  89. /// key 为模块结果终端名(如 "ImageData"、"Score")。不可用时返回 null。
  90. /// </summary>
  91. public static object GetModuleOutput(object procedure, string key)
  92. {
  93. if (procedure == null || string.IsNullOrWhiteSpace(key)) return null;
  94. try
  95. {
  96. var moduResult = procedure.GetType().GetProperty("ModuResult")?.GetValue(procedure)
  97. ?? procedure.GetType().GetField("ModuResult")?.GetValue(procedure);
  98. if (moduResult == null) return null;
  99. var type = moduResult.GetType();
  100. foreach (var method in new[] { "GetOutputImageV2", "GetOutputValue", "GetResultValue" })
  101. {
  102. var m = type.GetMethod(method, new[] { typeof(string) });
  103. if (m == null) continue;
  104. try
  105. {
  106. var v = m.Invoke(moduResult, new[] { key });
  107. if (v != null) return v;
  108. }
  109. catch { }
  110. }
  111. }
  112. catch { }
  113. return null;
  114. }
  115. }
  116. }