|
- #include "online_logic_monitor_service.h"
-
- #include <algorithm>
- #include <utility>
-
- namespace {
-
- LogicScanResult success()
- {
- return {true, LogicScanError::None, {}, {}, {}, {}};
- }
-
- LogicScanResult snapshotFailure(const RegisterAddress &address)
- {
- return {
- false,
- LogicScanError::RegisterReadFailed,
- "读取 PLC 缓存失败:" + address.toString(),
- {},
- {},
- {}};
- }
-
- } // namespace
-
- OnlineLogicMonitorService::OnlineLogicMonitorService(
- RegisterRepository &plc_repository,
- QObject *parent)
- : QObject(parent),
- plc_repository_(plc_repository)
- {
- }
-
- OnlineLogicMonitorStartResult OnlineLogicMonitorService::start(
- const std::vector<ControlLogic> &logics)
- {
- if (state_ == OnlineLogicMonitorState::Running)
- {
- return {false, OnlineLogicMonitorStartError::AlreadyRunning, {}};
- }
-
- std::vector<ControlLogic> snapshot = logics;
- const LogicScanResult validation = executor_.validate(snapshot);
- if (!validation.succeeded)
- {
- last_error_ = validation;
- state_ = OnlineLogicMonitorState::Faulted;
- emit stateChanged();
- return {false, OnlineLogicMonitorStartError::InvalidLogic, validation};
- }
-
- std::vector<RegisterAddress> addresses;
- for (const ControlLogic &logic : snapshot)
- {
- if (!logic.enabled)
- {
- continue;
- }
- for (const LadderRung &rung : logic.rungs)
- {
- std::vector<const LogicNode *> nodes;
- if (rung.condition.has_value())
- {
- collectConditionNodes(*rung.condition, &nodes);
- }
- if (rung.output.has_value())
- {
- nodes.push_back(&*rung.output);
- }
- for (const LogicNode *node : nodes)
- {
- collectRegisterAddressesForLogicNode(node->config, &addresses);
- }
- }
- }
- std::sort(
- addresses.begin(), addresses.end(),
- [](const RegisterAddress &left, const RegisterAddress &right)
- {
- return left.area() == right.area()
- ? left.index() < right.index()
- : left.area() == RegisterArea::M;
- });
- addresses.erase(std::unique(addresses.begin(), addresses.end()), addresses.end());
-
- executor_.resetRuntime();
- working_repository_.clear();
- logic_snapshot_ = std::move(snapshot);
- referenced_addresses_ = std::move(addresses);
- successful_scan_count_ = 0;
- last_error_ = success();
- trace_snapshot_.clear();
- state_ = OnlineLogicMonitorState::Running;
- emit stateChanged();
-
- const LogicScanResult first_scan = executeOnce();
- if (!first_scan.succeeded)
- {
- return {
- false,
- OnlineLogicMonitorStartError::PlcSnapshotUnavailable,
- first_scan};
- }
- return {true, OnlineLogicMonitorStartError::None, success()};
- }
-
- void OnlineLogicMonitorService::stop()
- {
- executor_.resetRuntime();
- working_repository_.clear();
- logic_snapshot_.clear();
- referenced_addresses_.clear();
- trace_snapshot_.clear();
- successful_scan_count_ = 0;
- // 主动停止时保留最近一次故障,便于真机退出后继续查看诊断信息
- if (state_ == OnlineLogicMonitorState::Stopped)
- {
- return;
- }
- state_ = OnlineLogicMonitorState::Stopped;
- emit stateChanged();
- }
-
- LogicScanResult OnlineLogicMonitorService::executeOnce()
- {
- if (state_ != OnlineLogicMonitorState::Running)
- {
- return {
- false,
- LogicScanError::InvalidLogic,
- "真机本地轨迹尚未运行",
- {},
- {},
- {}};
- }
-
- const LogicScanResult copied = copyPlcSnapshot();
- if (!copied.succeeded)
- {
- enterFault(copied);
- return copied;
- }
- const LogicScanResult result = executor_.executeScan(
- logic_snapshot_, working_repository_, &trace_snapshot_);
- if (!result.succeeded)
- {
- enterFault(result);
- return result;
- }
- ++successful_scan_count_;
- emit scanCompleted();
- return result;
- }
-
- OnlineLogicMonitorState OnlineLogicMonitorService::state() const
- {
- return state_;
- }
-
- std::uint64_t OnlineLogicMonitorService::successfulScanCount() const
- {
- return successful_scan_count_;
- }
-
- const LogicScanResult &OnlineLogicMonitorService::lastError() const
- {
- return last_error_;
- }
-
- const LogicTraceSnapshot &OnlineLogicMonitorService::traceSnapshot() const
- {
- return trace_snapshot_;
- }
-
- LogicScanResult OnlineLogicMonitorService::copyPlcSnapshot()
- {
- // 每轮从真实读回缓存重新开始,本地输出不会跨轮污染 PLC 数据
- working_repository_.clear();
- for (const RegisterAddress &address : referenced_addresses_)
- {
- if (address.area() == RegisterArea::M)
- {
- const BitReadResult read = plc_repository_.readBit(address);
- if (!read.succeeded)
- {
- return snapshotFailure(address);
- }
- working_repository_.writeBit(address, read.value);
- }
- else
- {
- const WordReadResult read = plc_repository_.readWord(address);
- if (!read.succeeded)
- {
- return snapshotFailure(address);
- }
- working_repository_.writeWord(address, read.value);
- }
- }
- return success();
- }
-
- void OnlineLogicMonitorService::enterFault(const LogicScanResult &error)
- {
- executor_.resetRuntime();
- last_error_ = error;
- state_ = OnlineLogicMonitorState::Faulted;
- emit stateChanged();
- }
|