#include "online_logic_monitor_service.h" #include #include 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 &logics) { if (state_ == OnlineLogicMonitorState::Running) { return {false, OnlineLogicMonitorStartError::AlreadyRunning, {}}; } std::vector 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 addresses; for (const ControlLogic &logic : snapshot) { if (!logic.enabled) { continue; } for (const LadderRung &rung : logic.rungs) { std::vector 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(); }