综合平台编程器项目的远程存储
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

207 lines
5.4 KiB

  1. #include "online_logic_monitor_service.h"
  2. #include <algorithm>
  3. #include <utility>
  4. namespace {
  5. LogicScanResult success()
  6. {
  7. return {true, LogicScanError::None, {}, {}, {}, {}};
  8. }
  9. LogicScanResult snapshotFailure(const RegisterAddress &address)
  10. {
  11. return {
  12. false,
  13. LogicScanError::RegisterReadFailed,
  14. "读取 PLC 缓存失败:" + address.toString(),
  15. {},
  16. {},
  17. {}};
  18. }
  19. } // namespace
  20. OnlineLogicMonitorService::OnlineLogicMonitorService(
  21. RegisterRepository &plc_repository,
  22. QObject *parent)
  23. : QObject(parent),
  24. plc_repository_(plc_repository)
  25. {
  26. }
  27. OnlineLogicMonitorStartResult OnlineLogicMonitorService::start(
  28. const std::vector<ControlLogic> &logics)
  29. {
  30. if (state_ == OnlineLogicMonitorState::Running)
  31. {
  32. return {false, OnlineLogicMonitorStartError::AlreadyRunning, {}};
  33. }
  34. std::vector<ControlLogic> snapshot = logics;
  35. const LogicScanResult validation = executor_.validate(snapshot);
  36. if (!validation.succeeded)
  37. {
  38. last_error_ = validation;
  39. state_ = OnlineLogicMonitorState::Faulted;
  40. emit stateChanged();
  41. return {false, OnlineLogicMonitorStartError::InvalidLogic, validation};
  42. }
  43. std::vector<RegisterAddress> addresses;
  44. for (const ControlLogic &logic : snapshot)
  45. {
  46. if (!logic.enabled)
  47. {
  48. continue;
  49. }
  50. for (const LadderRung &rung : logic.rungs)
  51. {
  52. std::vector<const LogicNode *> nodes;
  53. collectConditionNodes(rung, &nodes);
  54. if (rung.output.has_value())
  55. {
  56. nodes.push_back(&*rung.output);
  57. }
  58. for (const LogicNode *node : nodes)
  59. {
  60. collectRegisterAddressesForLogicNode(node->config, &addresses);
  61. }
  62. }
  63. }
  64. std::sort(
  65. addresses.begin(), addresses.end(),
  66. [](const RegisterAddress &left, const RegisterAddress &right)
  67. {
  68. return left.area() == right.area()
  69. ? left.index() < right.index()
  70. : left.area() == RegisterArea::M;
  71. });
  72. addresses.erase(std::unique(addresses.begin(), addresses.end()), addresses.end());
  73. executor_.resetRuntime();
  74. working_repository_.clear();
  75. logic_snapshot_ = std::move(snapshot);
  76. referenced_addresses_ = std::move(addresses);
  77. successful_scan_count_ = 0;
  78. last_error_ = success();
  79. trace_snapshot_.clear();
  80. state_ = OnlineLogicMonitorState::Running;
  81. emit stateChanged();
  82. const LogicScanResult first_scan = executeOnce();
  83. if (!first_scan.succeeded)
  84. {
  85. return {
  86. false,
  87. OnlineLogicMonitorStartError::PlcSnapshotUnavailable,
  88. first_scan};
  89. }
  90. return {true, OnlineLogicMonitorStartError::None, success()};
  91. }
  92. void OnlineLogicMonitorService::stop()
  93. {
  94. executor_.resetRuntime();
  95. working_repository_.clear();
  96. logic_snapshot_.clear();
  97. referenced_addresses_.clear();
  98. trace_snapshot_.clear();
  99. successful_scan_count_ = 0;
  100. // 主动停止时保留最近一次故障,便于真机退出后继续查看诊断信息
  101. if (state_ == OnlineLogicMonitorState::Stopped)
  102. {
  103. return;
  104. }
  105. state_ = OnlineLogicMonitorState::Stopped;
  106. emit stateChanged();
  107. }
  108. LogicScanResult OnlineLogicMonitorService::executeOnce()
  109. {
  110. if (state_ != OnlineLogicMonitorState::Running)
  111. {
  112. return {
  113. false,
  114. LogicScanError::InvalidLogic,
  115. "真机本地轨迹尚未运行",
  116. {},
  117. {},
  118. {}};
  119. }
  120. const LogicScanResult copied = copyPlcSnapshot();
  121. if (!copied.succeeded)
  122. {
  123. enterFault(copied);
  124. return copied;
  125. }
  126. const LogicScanResult result = executor_.executeScan(
  127. logic_snapshot_, working_repository_, &trace_snapshot_);
  128. if (!result.succeeded)
  129. {
  130. enterFault(result);
  131. return result;
  132. }
  133. ++successful_scan_count_;
  134. emit scanCompleted();
  135. return result;
  136. }
  137. OnlineLogicMonitorState OnlineLogicMonitorService::state() const
  138. {
  139. return state_;
  140. }
  141. std::uint64_t OnlineLogicMonitorService::successfulScanCount() const
  142. {
  143. return successful_scan_count_;
  144. }
  145. const LogicScanResult &OnlineLogicMonitorService::lastError() const
  146. {
  147. return last_error_;
  148. }
  149. const LogicTraceSnapshot &OnlineLogicMonitorService::traceSnapshot() const
  150. {
  151. return trace_snapshot_;
  152. }
  153. LogicScanResult OnlineLogicMonitorService::copyPlcSnapshot()
  154. {
  155. // 每轮从真实读回缓存重新开始,本地输出不会跨轮污染 PLC 数据
  156. working_repository_.clear();
  157. for (const RegisterAddress &address : referenced_addresses_)
  158. {
  159. if (address.area() == RegisterArea::M)
  160. {
  161. const BitReadResult read = plc_repository_.readBit(address);
  162. if (!read.succeeded)
  163. {
  164. return snapshotFailure(address);
  165. }
  166. working_repository_.writeBit(address, read.value);
  167. }
  168. else
  169. {
  170. const WordReadResult read = plc_repository_.readWord(address);
  171. if (!read.succeeded)
  172. {
  173. return snapshotFailure(address);
  174. }
  175. working_repository_.writeWord(address, read.value);
  176. }
  177. }
  178. return success();
  179. }
  180. void OnlineLogicMonitorService::enterFault(const LogicScanResult &error)
  181. {
  182. executor_.resetRuntime();
  183. last_error_ = error;
  184. state_ = OnlineLogicMonitorState::Faulted;
  185. emit stateChanged();
  186. }