综合平台编程器项目的远程存储
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

210 строки
5.5 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. if (rung.condition.has_value())
  54. {
  55. collectConditionNodes(*rung.condition, &nodes);
  56. }
  57. if (rung.output.has_value())
  58. {
  59. nodes.push_back(&*rung.output);
  60. }
  61. for (const LogicNode *node : nodes)
  62. {
  63. collectRegisterAddressesForLogicNode(node->config, &addresses);
  64. }
  65. }
  66. }
  67. std::sort(
  68. addresses.begin(), addresses.end(),
  69. [](const RegisterAddress &left, const RegisterAddress &right)
  70. {
  71. return left.area() == right.area()
  72. ? left.index() < right.index()
  73. : left.area() == RegisterArea::M;
  74. });
  75. addresses.erase(std::unique(addresses.begin(), addresses.end()), addresses.end());
  76. executor_.resetRuntime();
  77. working_repository_.clear();
  78. logic_snapshot_ = std::move(snapshot);
  79. referenced_addresses_ = std::move(addresses);
  80. successful_scan_count_ = 0;
  81. last_error_ = success();
  82. trace_snapshot_.clear();
  83. state_ = OnlineLogicMonitorState::Running;
  84. emit stateChanged();
  85. const LogicScanResult first_scan = executeOnce();
  86. if (!first_scan.succeeded)
  87. {
  88. return {
  89. false,
  90. OnlineLogicMonitorStartError::PlcSnapshotUnavailable,
  91. first_scan};
  92. }
  93. return {true, OnlineLogicMonitorStartError::None, success()};
  94. }
  95. void OnlineLogicMonitorService::stop()
  96. {
  97. executor_.resetRuntime();
  98. working_repository_.clear();
  99. logic_snapshot_.clear();
  100. referenced_addresses_.clear();
  101. trace_snapshot_.clear();
  102. successful_scan_count_ = 0;
  103. // 主动停止时保留最近一次故障,便于真机退出后继续查看诊断信息
  104. if (state_ == OnlineLogicMonitorState::Stopped)
  105. {
  106. return;
  107. }
  108. state_ = OnlineLogicMonitorState::Stopped;
  109. emit stateChanged();
  110. }
  111. LogicScanResult OnlineLogicMonitorService::executeOnce()
  112. {
  113. if (state_ != OnlineLogicMonitorState::Running)
  114. {
  115. return {
  116. false,
  117. LogicScanError::InvalidLogic,
  118. "真机本地轨迹尚未运行",
  119. {},
  120. {},
  121. {}};
  122. }
  123. const LogicScanResult copied = copyPlcSnapshot();
  124. if (!copied.succeeded)
  125. {
  126. enterFault(copied);
  127. return copied;
  128. }
  129. const LogicScanResult result = executor_.executeScan(
  130. logic_snapshot_, working_repository_, &trace_snapshot_);
  131. if (!result.succeeded)
  132. {
  133. enterFault(result);
  134. return result;
  135. }
  136. ++successful_scan_count_;
  137. emit scanCompleted();
  138. return result;
  139. }
  140. OnlineLogicMonitorState OnlineLogicMonitorService::state() const
  141. {
  142. return state_;
  143. }
  144. std::uint64_t OnlineLogicMonitorService::successfulScanCount() const
  145. {
  146. return successful_scan_count_;
  147. }
  148. const LogicScanResult &OnlineLogicMonitorService::lastError() const
  149. {
  150. return last_error_;
  151. }
  152. const LogicTraceSnapshot &OnlineLogicMonitorService::traceSnapshot() const
  153. {
  154. return trace_snapshot_;
  155. }
  156. LogicScanResult OnlineLogicMonitorService::copyPlcSnapshot()
  157. {
  158. // 每轮从真实读回缓存重新开始,本地输出不会跨轮污染 PLC 数据
  159. working_repository_.clear();
  160. for (const RegisterAddress &address : referenced_addresses_)
  161. {
  162. if (address.area() == RegisterArea::M)
  163. {
  164. const BitReadResult read = plc_repository_.readBit(address);
  165. if (!read.succeeded)
  166. {
  167. return snapshotFailure(address);
  168. }
  169. working_repository_.writeBit(address, read.value);
  170. }
  171. else
  172. {
  173. const WordReadResult read = plc_repository_.readWord(address);
  174. if (!read.succeeded)
  175. {
  176. return snapshotFailure(address);
  177. }
  178. working_repository_.writeWord(address, read.value);
  179. }
  180. }
  181. return success();
  182. }
  183. void OnlineLogicMonitorService::enterFault(const LogicScanResult &error)
  184. {
  185. executor_.resetRuntime();
  186. last_error_ = error;
  187. state_ = OnlineLogicMonitorState::Faulted;
  188. emit stateChanged();
  189. }