综合平台编程器项目的远程存储
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.
 
 
 
 

142 lines
3.8 KiB

  1. #include "offline_simulation_service.h"
  2. #include <utility>
  3. OfflineSimulationService::OfflineSimulationService(
  4. VirtualRegisterRepository &repository,
  5. VirtualRegisterRepository *initial_repository,
  6. QObject *parent)
  7. : QObject(parent),
  8. repository_(repository),
  9. initial_repository_(initial_repository)
  10. {
  11. timer_.setInterval(kDefaultScanIntervalMs);
  12. timer_.setTimerType(Qt::PreciseTimer);
  13. connect(&timer_, &QTimer::timeout,
  14. this, &OfflineSimulationService::handleTimeout);
  15. }
  16. SimulationStartResult OfflineSimulationService::start(
  17. const std::vector<ControlLogic> &logics)
  18. {
  19. if (state_ == SimulationState::Running)
  20. {
  21. return {false, SimulationStartError::AlreadyRunning, {}};
  22. }
  23. // 仿真期间使用启动时快照,编辑器后续修改不会改变正在扫描的逻辑
  24. std::vector<ControlLogic> snapshot = logics;
  25. const LogicScanResult validation = executor_.validate(snapshot);
  26. if (!validation.succeeded)
  27. {
  28. last_error_ = validation;
  29. return {false, SimulationStartError::InvalidLogic, validation};
  30. }
  31. // 重启会话时清空沿触发状态和运行值,再装载编辑态确认的初始值
  32. timer_.stop();
  33. executor_.resetRuntime();
  34. repository_.clear();
  35. if (initial_repository_ != nullptr)
  36. {
  37. repository_.copyFrom(*initial_repository_);
  38. }
  39. logic_snapshot_ = std::move(snapshot);
  40. successful_scan_count_ = 0;
  41. last_error_ = {true, LogicScanError::None, {}, {}, {}, {}};
  42. trace_snapshot_.clear();
  43. state_ = SimulationState::Running;
  44. timer_.start();
  45. emit stateChanged();
  46. return {true, SimulationStartError::None, {true, LogicScanError::None, {}, {}, {}, {}}};
  47. }
  48. void OfflineSimulationService::restoreInitialValues()
  49. {
  50. repository_.clear();
  51. if (initial_repository_ != nullptr)
  52. {
  53. repository_.copyFrom(*initial_repository_);
  54. }
  55. }
  56. void OfflineSimulationService::stop()
  57. {
  58. timer_.stop();
  59. executor_.resetRuntime();
  60. logic_snapshot_.clear();
  61. if (state_ == SimulationState::Stopped)
  62. {
  63. return;
  64. }
  65. // 运行结束后丢弃本轮输出,编辑态继续看到下一轮要使用的初始值
  66. restoreInitialValues();
  67. state_ = SimulationState::Stopped;
  68. last_error_ = {true, LogicScanError::None, {}, {}, {}, {}};
  69. emit stateChanged();
  70. }
  71. LogicScanResult OfflineSimulationService::executeOnce()
  72. {
  73. if (state_ != SimulationState::Running)
  74. {
  75. return {false,
  76. LogicScanError::InvalidLogic,
  77. "离线仿真尚未运行",
  78. {},
  79. {},
  80. {}};
  81. }
  82. // 执行器负责一轮完整扫描;任何读写错误都会让服务进入 Faulted
  83. const LogicScanResult result = executor_.executeScan(
  84. logic_snapshot_, repository_, &trace_snapshot_);
  85. if (!result.succeeded)
  86. {
  87. enterFault(result);
  88. return result;
  89. }
  90. ++successful_scan_count_;
  91. emit scanCompleted();
  92. return result;
  93. }
  94. SimulationState OfflineSimulationService::state() const
  95. {
  96. return state_;
  97. }
  98. int OfflineSimulationService::scanIntervalMs() const
  99. {
  100. return timer_.interval();
  101. }
  102. std::uint64_t OfflineSimulationService::successfulScanCount() const
  103. {
  104. return successful_scan_count_;
  105. }
  106. const LogicScanResult &OfflineSimulationService::lastError() const
  107. {
  108. return last_error_;
  109. }
  110. const LogicTraceSnapshot &OfflineSimulationService::traceSnapshot() const
  111. {
  112. return trace_snapshot_;
  113. }
  114. void OfflineSimulationService::handleTimeout()
  115. {
  116. executeOnce();
  117. }
  118. void OfflineSimulationService::enterFault(const LogicScanResult &error)
  119. {
  120. // 故障后停止定时器和运行时状态,保留错误及最后轨迹供 UI 诊断
  121. timer_.stop();
  122. executor_.resetRuntime();
  123. last_error_ = error;
  124. state_ = SimulationState::Faulted;
  125. emit stateChanged();
  126. }