HalconDisplayPlugin.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using System.Windows;
  5. using Plugins.Halcon.Models;
  6. using Plugins.Halcon.Views;
  7. using TeamAAS.FlowEditor.Execution;
  8. using TeamAAS.FlowEditor.Models;
  9. using TeamAAS.FlowEditor.Plugins;
  10. namespace Plugins.Halcon
  11. {
  12. /// <summary>
  13. /// HALCON 图像显示节点(主流程节点,与 VP图像显示/VM图像显示 对等):把 HALCON 流程容器输出的
  14. /// 图像/区域显示到主页画面框(视觉窗体 UCDispHalcon),每项可独立链接叠加区域与 OK/NG 结果驱动状态圆点。
  15. /// 放在主流程调用:图像来源绑定上游「Halcon流程」容器的输出(或任意前序节点的图像/GenImage)。
  16. /// 画面框是主页单例、独立于编辑器——正常运行只往里推图,不由编辑器控制。
  17. /// </summary>
  18. [Serializable]
  19. [Plugin("Halcon图像显示", PluginCategory.Halocn模块, typeof(HalconDisplayModel), "Monitor",
  20. NodeShape = NodeCategory.Normal,
  21. Description = "主流程节点:把 HALCON 图像/区域显示到主页画面框;每项可独立链接叠加区域与 OK/NG 结果驱动状态圆点")]
  22. public class HalconDisplayPlugin : BasePlugin<HalconDisplayModel>
  23. {
  24. public override List<OutputField> DeclareOutputs()
  25. {
  26. var list = new List<OutputField>
  27. {
  28. new OutputField("显示画面数", typeof(int)),
  29. new OutputField("结果", typeof(bool)),
  30. };
  31. foreach (var kv in BuildItemKeys(Model))
  32. list.Add(new OutputField(kv.Key, typeof(object)));
  33. return list;
  34. }
  35. /// <summary>
  36. /// 依据显示项列表生成稳定的「输出键 → 显示项」映射:键优先取目标画面名,重名/空名追加序号去重。
  37. /// <see cref="DeclareOutputs"/> 与 <see cref="PluginRun"/> 共用,保证键一致。
  38. /// </summary>
  39. private static List<KeyValuePair<string, HalconDisplayItem>> BuildItemKeys(HalconDisplayModel model)
  40. {
  41. var map = new List<KeyValuePair<string, HalconDisplayItem>>();
  42. if (model?.DisplayItems == null) return map;
  43. var used = new HashSet<string>();
  44. for (int i = 0; i < model.DisplayItems.Count; i++)
  45. {
  46. var item = model.DisplayItems[i];
  47. if (item == null) continue;
  48. string key = item.FrameName;
  49. if (string.IsNullOrWhiteSpace(key)) key = $"画面{item.FrameNo}";
  50. string unique = key;
  51. int dup = 2;
  52. while (!used.Add(unique)) unique = $"{key}({dup++})";
  53. map.Add(new KeyValuePair<string, HalconDisplayItem>(unique, item));
  54. }
  55. return map;
  56. }
  57. public override NodeRunStatus PluginRun(CancellationToken token, out Dictionary<string, object> results)
  58. {
  59. var res = new Dictionary<string, object>();
  60. results = res;
  61. try
  62. {
  63. var windows = UCDispHalcon.Instance.halconWindow;
  64. int displayed = 0;
  65. Log(3, $"开始显示,显示项 {Model.DisplayItems?.Count ?? 0} 个,主页画面框 {windows?.Count ?? 0} 个");
  66. foreach (var kv in BuildItemKeys(Model))
  67. {
  68. var item = kv.Value;
  69. res[kv.Key] = null;
  70. object image = GetResolve(item.Source);
  71. object overlay = string.IsNullOrWhiteSpace(item.OverlaySource?.Formula) ? null : GetResolve(item.OverlaySource);
  72. res[kv.Key] = image;
  73. if (image == null)
  74. {
  75. Log(2, $"显示项[{kv.Key}] 未解析到图像,已跳过", TeamAAS.LogLevel.Warning);
  76. continue;
  77. }
  78. if (item.FrameNo < 1 || windows == null || windows.Count < item.FrameNo)
  79. {
  80. Log(2, $"显示项[{kv.Key}] 目标画面序号 {item.FrameNo} 无效或主页画面框不足,已跳过", TeamAAS.LogLevel.Warning);
  81. continue;
  82. }
  83. var win = windows[item.FrameNo - 1];
  84. if (win == null) continue;
  85. bool hasOk = !string.IsNullOrWhiteSpace(item.OkNgBinding?.Formula);
  86. bool ok = hasOk && GetValue<bool>(item.OkNgBinding);
  87. Application.Current?.Dispatcher.Invoke(() =>
  88. {
  89. win.RefreshImage(image, overlay);
  90. if (hasOk) win.SetLable(ok ? HalconResultType.OK : HalconResultType.NG);
  91. });
  92. displayed++;
  93. Log(4, $"显示项[{kv.Key}] → 画面{item.FrameNo},图像类型 {(image?.GetType().Name ?? "null")},叠加 {(overlay != null ? "有" : "无")}{(hasOk ? $",OK/NG={(ok ? "OK" : "NG")}" : "")}");
  94. }
  95. res["显示画面数"] = displayed;
  96. res["结果"] = true;
  97. Log(2, $"显示完成,共刷新 {displayed} 个画面");
  98. return NodeRunStatus.Success;
  99. }
  100. catch (Exception ex)
  101. {
  102. res["Error"] = ex.Message;
  103. res["结果"] = false;
  104. Log(1, $"HALCON 图像显示异常: {ex.Message}", TeamAAS.LogLevel.Error);
  105. return NodeRunStatus.Failed;
  106. }
  107. }
  108. }
  109. }