Browse Source

fix: 清理退出仿真后的旧轨迹

main
suyu 3 weeks ago
parent
commit
1ba67589f5
7 changed files with 207 additions and 0 deletions
  1. +5
    -0
      app/src/ui/logic_editor_widget.cpp
  2. +2
    -0
      app/src/ui/logic_editor_widget.h
  3. +6
    -0
      app/src/ui/runtime_panel_controller.cpp
  4. +143
    -0
      app/tests/runtime_panel_controller_tests.cpp
  5. +48
    -0
      app/tests/runtime_panel_controller_tests.pro
  6. +2
    -0
      app/tests/tests.pro
  7. +1
    -0
      scripts/run_qt_tests.ps1

+ 5
- 0
app/src/ui/logic_editor_widget.cpp View File

@@ -1045,6 +1045,11 @@ void LogicEditorWidget::clearRuntimeTrace()
reloadLogic();
}

bool LogicEditorWidget::runtimeTraceEnabled() const
{
return runtime_trace_enabled_;
}

void LogicEditorWidget::reloadLogic()
{
// 逻辑或选择变化后重新计算网格布局和可点击插入目标


+ 2
- 0
app/src/ui/logic_editor_widget.h View File

@@ -51,6 +51,8 @@ public:
const std::string &fault_node_id = {});
/** 清除当前运行轨迹和故障节点标记 */
void clearRuntimeTrace();
/** 返回当前是否正在显示运行轨迹 */
bool runtimeTraceEnabled() const;
/** 根据当前逻辑模型重建梯形图场景 */
void reloadLogic();
/** 选中指定节点并滚动到可见区域 */


+ 6
- 0
app/src/ui/runtime_panel_controller.cpp View File

@@ -288,6 +288,12 @@ void RuntimePanelController::handleSimulationStateChanged()

void RuntimePanelController::handleScanCompleted()
{
// 排队的扫描信号可能晚于退出操作到达,编辑态不得恢复旧运行轨迹
if (runtime_mode_service_.mode() != ApplicationMode::OfflineRunning
|| runtime_mode_service_.simulationState() != SimulationState::Running)
{
return;
}
const std::string logic_id = current_logic_id_();
logic_editor_widget_.setRuntimeTrace(
runtime_mode_service_.offlineSimulationService()


+ 143
- 0
app/tests/runtime_panel_controller_tests.cpp View File

@@ -0,0 +1,143 @@
#include "domain/virtual_register_repository.h"
#include "services/alarm_service.h"
#include "services/hmi_editor_service.h"
#include "services/hmi_navigation_service.h"
#include "services/hmi_runtime_service.h"
#include "services/logic_editor_service.h"
#include "services/offline_simulation_service.h"
#include "services/project_service.h"
#include "services/register_monitor_service.h"
#include "services/runtime_mode_service.h"
#include "support/test_support.h"
#include "ui/hmi_editor_widget.h"
#include "ui/logic_editor_widget.h"
#include "ui/runtime_panel_controller.h"

#include <QApplication>
#include <QCoreApplication>
#include <QEventLoop>
#include <QLabel>
#include <QWidget>

#include <iostream>
#include <stdexcept>
#include <string>

namespace {

using TestProjectStorage = TestSupport::InMemoryProjectStorage;
using TestSupport::require;

ControlLogic makeAlwaysOnLogic()
{
ControlLogic logic;
logic.id = "queued-trace-logic";
logic.name = "Queued trace logic";

LadderRung rung;
rung.id = "always-on-rung";
rung.name = "Always on";
rung.condition = ConditionExpression::fromWire("always-on-wire", 10);

LogicNode output;
output.id = "always-on-output";
output.config = CoilNodeConfig{
RegisterAddress{RegisterArea::M, 1}, CoilMode::Normal};
rung.output = output;
logic.rungs.push_back(rung);
return logic;
}

void testQueuedOfflineTraceIsIgnoredAfterReturningToEditing()
{
TestProjectStorage storage;
ProjectService project_service(storage);
VirtualRegisterRepository virtual_repository;
OfflineSimulationService simulation_service(virtual_repository);
RuntimeModeService runtime_mode_service(project_service, simulation_service);
HmiEditorService hmi_editor_service(project_service);
HmiRuntimeService hmi_runtime_service(virtual_repository);
LogicEditorService logic_editor_service(project_service);
HmiNavigationService hmi_navigation_service(project_service);
AlarmService alarm_service(project_service, virtual_repository);
RegisterMonitorService register_monitor_service(virtual_repository);

const ControlLogic logic = makeAlwaysOnLogic();
project_service.editProject().controlLogics.push_back(logic);

QWidget parent;
HmiEditorWidget hmi_editor_widget(
hmi_editor_service, hmi_runtime_service, alarm_service, &parent);
LogicEditorWidget logic_editor_widget(logic_editor_service, &parent);
QLabel executor_status_label(&parent);
std::string current_logic_id = logic.id;
logic_editor_widget.setLogicId(current_logic_id);

RuntimePanelController controller(
parent,
runtime_mode_service,
project_service,
hmi_editor_service,
hmi_runtime_service,
logic_editor_service,
hmi_navigation_service,
alarm_service,
register_monitor_service,
hmi_editor_widget,
logic_editor_widget,
executor_status_label,
[&current_logic_id] { return current_logic_id; },
[&current_logic_id](const std::string &logic_id)
{
current_logic_id = logic_id;
},
[](const std::string &) {},
[](const QString &, int) {},
[](const QString &) {},
[] {});
controller.configure();

require(runtime_mode_service.enterOfflineRunning().succeeded,
"offline simulation must start for queued trace regression");
controller.enterRuntime(
{}, logic.id, runtime_mode_service.mode(),
runtime_mode_service.plcConnectionState());
require(simulation_service.executeOnce().succeeded,
"offline simulation must produce a trace before editing");
require(simulation_service.traceSnapshot()
.forLogic(logic.id).rungValues.at("always-on-rung"),
"the queued trace must contain an energized rung");

require(runtime_mode_service.enterEditing().succeeded,
"offline simulation must return to editing before queued delivery");
controller.leaveRuntime(
runtime_mode_service.mode(), runtime_mode_service.plcConnectionState());
logic_editor_widget.clearRuntimeTrace();
require(!logic_editor_widget.runtimeTraceEnabled(),
"editing transition must initially clear the runtime trace");

QCoreApplication::processEvents(QEventLoop::AllEvents);
require(!logic_editor_widget.runtimeTraceEnabled(),
"a queued offline scan must not restore the trace after returning to editing");
}

} // namespace

int main(int argc, char *argv[])
{
qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("offscreen"));
QApplication application(argc, argv);
try
{
testQueuedOfflineTraceIsIgnoredAfterReturningToEditing();
}
catch (const std::exception &error)
{
std::cerr << "runtime panel controller tests failed: "
<< error.what() << '\n';
return 1;
}

std::cout << "runtime panel controller tests passed\n";
return 0;
}

+ 48
- 0
app/tests/runtime_panel_controller_tests.pro View File

@@ -0,0 +1,48 @@
include(pri/test_defaults.pri)
include(pri/test_layers.pri)

TARGET = runtime_panel_controller_tests
QT += core gui widgets
CONFIG += testcase

SOURCES += \
runtime_panel_controller_tests.cpp \
$$DOMAIN_ALL_SOURCES \
$$SERVICE_PROJECT_SOURCES \
$$SERVICE_ALARM_SOURCES \
$$SERVICE_HMI_SOURCES \
$$SERVICE_LOGIC_SOURCES \
$$SERVICE_OFFLINE_SOURCES \
$$SERVICE_RUNTIME_SOURCES \
$$SERVICE_MONITOR_SOURCES \
../src/ui/hmi_editor_widget.cpp \
../src/ui/logic_editor_widget.cpp \
../src/ui/free_monitor_widget.cpp \
../src/ui/runtime_monitor_window.cpp \
../src/ui/runtime_monitor_widget.cpp \
../src/ui/toolbar_icon_factory.cpp \
../src/ui/runtime_panel_controller.cpp

HEADERS += \
$$DOMAIN_ALL_HEADERS \
$$SERVICE_PROJECT_HEADERS \
$$SERVICE_ALARM_HEADERS \
$$SERVICE_HMI_HEADERS \
$$SERVICE_LOGIC_HEADERS \
$$SERVICE_OFFLINE_HEADERS \
$$SERVICE_RUNTIME_HEADERS \
$$SERVICE_MONITOR_HEADERS \
../src/services/plc_communication_gateway.h \
../src/ui/hmi_editor_widget.h \
../src/ui/logic_editor_widget.h \
../src/ui/free_monitor_widget.h \
../src/ui/runtime_monitor_window.h \
../src/ui/runtime_monitor_widget.h \
../src/ui/toolbar_icon_factory.h \
../src/ui/runtime_panel_controller.h \
$$TEST_SUPPORT_HEADERS

FORMS += \
../src/ui/free_monitor_widget.ui \
../src/ui/runtime_monitor_window.ui \
../src/ui/runtime_monitor_widget.ui

+ 2
- 0
app/tests/tests.pro View File

@@ -11,6 +11,7 @@ SUBDIRS += \
project_management \
register_monitor \
runtime_mode \
runtime_panel_controller \
plc_runtime

domain.file = domain_tests.pro
@@ -21,4 +22,5 @@ offline_simulation.file = offline_simulation_service_tests.pro
project_management.file = project_management_tests.pro
register_monitor.file = register_monitor_service_tests.pro
runtime_mode.file = runtime_mode_service_tests.pro
runtime_panel_controller.file = runtime_panel_controller_tests.pro
plc_runtime.file = plc_runtime_tests.pro

+ 1
- 0
scripts/run_qt_tests.ps1 View File

@@ -33,6 +33,7 @@ $functionalTargets = @(
'project_management_tests',
'register_monitor_service_tests',
'runtime_mode_service_tests',
'runtime_panel_controller_tests',
'plc_runtime_tests'
)
$performanceTargets = @('performance_tests')


Loading…
Cancel
Save