|
- #include "runtime_panel_controller.h"
-
- #include "free_monitor_widget.h"
- #include "hmi_editor_widget.h"
- #include "logic_editor_widget.h"
- #include "runtime_monitor_widget.h"
- #include "runtime_monitor_window.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 <QListWidget>
- #include <QLabel>
- #include <QObject>
- #include <QTimer>
- #include <QWidget>
-
- #include <utility>
-
- namespace {
-
- QString fromUtf8(const std::string &value)
- {
- return QString::fromUtf8(value.data(), static_cast<int>(value.size()));
- }
-
- } // namespace
-
- RuntimePanelController::RuntimePanelController(
- QWidget &parent,
- RuntimeModeService &runtime_mode_service,
- ProjectService &project_service,
- HmiEditorService &hmi_editor_service,
- HmiRuntimeService &hmi_runtime_service,
- LogicEditorService &logic_editor_service,
- HmiNavigationService &hmi_navigation_service,
- AlarmService &alarm_service,
- RegisterMonitorService ®ister_monitor_service,
- HmiEditorWidget &hmi_editor_widget,
- LogicEditorWidget &logic_editor_widget,
- QLabel &executor_status_label,
- std::function<std::string()> current_logic_id,
- std::function<void(const std::string &)> select_logic,
- std::function<void(const std::string &)> show_logic_properties,
- StatusReporter status_reporter,
- OutputReporter output_reporter,
- RuntimeExitRequester runtime_exit_requester)
- : parent_(parent),
- runtime_mode_service_(runtime_mode_service),
- project_service_(project_service),
- hmi_editor_service_(hmi_editor_service),
- hmi_runtime_service_(hmi_runtime_service),
- logic_editor_service_(logic_editor_service),
- hmi_navigation_service_(hmi_navigation_service),
- alarm_service_(alarm_service),
- register_monitor_service_(register_monitor_service),
- hmi_editor_widget_(hmi_editor_widget),
- logic_editor_widget_(logic_editor_widget),
- executor_status_label_(executor_status_label),
- current_logic_id_(std::move(current_logic_id)),
- select_logic_(std::move(select_logic)),
- show_logic_properties_(std::move(show_logic_properties)),
- status_reporter_(std::move(status_reporter)),
- output_reporter_(std::move(output_reporter)),
- runtime_exit_requester_(std::move(runtime_exit_requester))
- {
- }
-
- RuntimePanelController::~RuntimePanelController() = default;
-
- void RuntimePanelController::configure()
- {
- runtime_monitor_window_ = std::make_unique<RuntimeMonitorWindow>(&parent_);
- runtime_monitor_window_->setObjectName(
- QStringLiteral("runtimeMonitorWindow"));
- runtime_monitor_widget_ = new RuntimeMonitorWidget(
- hmi_editor_service_,
- hmi_runtime_service_,
- logic_editor_service_,
- project_service_,
- hmi_navigation_service_,
- alarm_service_,
- register_monitor_service_,
- runtime_monitor_window_.get());
- runtime_monitor_widget_->setObjectName(QStringLiteral("runtimeMonitorWidget"));
- runtime_monitor_window_->setMonitorWidget(*runtime_monitor_widget_);
- QObject::connect(runtime_monitor_widget_, &RuntimeMonitorWidget::exitRequested,
- &parent_, [this]
- {
- if (runtime_exit_requester_)
- {
- runtime_exit_requester_();
- }
- });
- QObject::connect(runtime_monitor_widget_->freeMonitorWidget(),
- &FreeMonitorWidget::monitorAddressesChanged,
- &parent_, [this]
- {
- runtime_mode_service_.setMonitorAddresses(
- register_monitor_service_.addresses());
- runtime_monitor_widget_->refreshValues(
- runtime_mode_service_.mode(),
- runtime_mode_service_.plcConnectionState());
- });
- QObject::connect(runtime_monitor_widget_->freeMonitorWidget(),
- &FreeMonitorWidget::operationMessage,
- &parent_, [this](const QString &message)
- {
- status_reporter_(message, 4000);
- });
- QObject::connect(runtime_monitor_widget_, &RuntimeMonitorWidget::navigationFailed,
- &parent_, [this](const QString &message)
- {
- status_reporter_(message, 5000);
- output_reporter_(QObject::tr("页面导航失败:%1").arg(message));
- });
- runtime_refresh_timer_ = new QTimer(&parent_);
- runtime_refresh_timer_->setInterval(150);
- QObject::connect(runtime_refresh_timer_, &QTimer::timeout,
- &parent_, [this] { handleRuntimeTimer(); });
- runtime_refresh_timer_->start();
- QObject::connect(&runtime_mode_service_.offlineSimulationService(),
- &OfflineSimulationService::stateChanged,
- &parent_, [this] { handleSimulationStateChanged(); },
- Qt::QueuedConnection);
- QObject::connect(&runtime_mode_service_.offlineSimulationService(),
- &OfflineSimulationService::scanCompleted,
- &parent_, [this] { handleScanCompleted(); },
- Qt::QueuedConnection);
- QObject::connect(&runtime_mode_service_.onlineLogicMonitorService(),
- &OnlineLogicMonitorService::stateChanged,
- &parent_, [this] { handleSimulationStateChanged(); });
- QObject::connect(&runtime_mode_service_.onlineLogicMonitorService(),
- &OnlineLogicMonitorService::scanCompleted,
- &parent_, [this] { handleScanCompleted(); },
- Qt::QueuedConnection);
- }
-
- RuntimeMonitorWidget *RuntimePanelController::runtimeMonitorWidget() const
- {
- return runtime_monitor_widget_;
- }
-
- void RuntimePanelController::enterRuntime(
- const std::string &page_id,
- const std::string &logic_id,
- ApplicationMode mode,
- PlcConnectionState plc_state)
- {
- if (!runtime_session_active_)
- {
- runtime_monitor_widget_->setProjectObjects(page_id, logic_id);
- // 运行窗口只创建一次,后续进入运行态复用同一个监控投影
- runtime_session_active_ = true;
- }
- runtime_monitor_widget_->setMode(mode, plc_state);
- runtime_monitor_window_->showForRuntime();
- }
-
- void RuntimePanelController::leaveRuntime(
- ApplicationMode mode, PlcConnectionState plc_state)
- {
- runtime_session_active_ = false;
- runtime_monitor_widget_->setMode(mode, plc_state);
- runtime_monitor_window_->hideForEditing();
- }
-
- void RuntimePanelController::closeForApplicationExit()
- {
- if (runtime_monitor_window_ != nullptr)
- {
- runtime_monitor_window_->closeForApplicationExit();
- }
- }
-
- void RuntimePanelController::updateSimulationUi(bool report_fault)
- {
- const bool offline = runtime_mode_service_.mode()
- == ApplicationMode::OfflineRunning;
- const bool online = runtime_mode_service_.mode()
- == ApplicationMode::OnlineRunning;
- const bool plc_connected = runtime_mode_service_.plcConnectionState()
- == PlcConnectionState::Connected;
- const SimulationState state = runtime_mode_service_.simulationState();
- const bool write_enabled = (online && plc_connected)
- || (offline && state == SimulationState::Running);
- // 编辑画布始终只读,运行操作统一由运行监控中的 HMI 发出
- hmi_editor_widget_.setRuntimeWriteEnabled(false);
- if (runtime_monitor_widget_ != nullptr)
- {
- runtime_monitor_widget_->setHmiWriteEnabled(write_enabled);
- runtime_monitor_widget_->setFreeMonitorWriteEnabled(write_enabled);
- runtime_monitor_widget_->refreshValues(
- runtime_mode_service_.mode(),
- runtime_mode_service_.plcConnectionState());
- }
- if (online)
- {
- switch (runtime_mode_service_.onlineLogicMonitorService().state())
- {
- case OnlineLogicMonitorState::Running:
- {
- executor_status_label_.setText(
- QObject::tr("本地推算轨迹:运行(%1 次)")
- .arg(runtime_mode_service_.onlineLogicMonitorService()
- .successfulScanCount()));
- return;
- }
- case OnlineLogicMonitorState::Faulted:
- {
- executor_status_label_.setText(QObject::tr("本地推算轨迹:故障"));
- if (report_fault)
- {
- const LogicScanResult &error = runtime_mode_service_
- .onlineLogicMonitorService().lastError();
- const QString message = QObject::tr("真机本地轨迹异常:%1")
- .arg(fromUtf8(error.message));
- status_reporter_(message, 0);
- output_reporter_(message);
- }
- return;
- }
- case OnlineLogicMonitorState::Stopped:
- default:
- {
- executor_status_label_.setText(QObject::tr("本地推算轨迹:停止"));
- return;
- }
- }
- }
- switch (state)
- {
- case SimulationState::Running:
- {
- executor_status_label_.setText(
- QObject::tr("逻辑执行器:运行(%1 次)")
- .arg(runtime_mode_service_.successfulScanCount()));
- break;
- }
- case SimulationState::Faulted:
- {
- executor_status_label_.setText(QObject::tr("逻辑执行器:故障"));
- if (!report_fault)
- {
- break;
- }
- const LogicScanResult &error = runtime_mode_service_.simulationError();
- if (!error.logicId.empty()
- && logic_editor_service_.findLogic(error.logicId) != nullptr)
- {
- select_logic_(error.logicId);
- }
- const std::string logic_id = current_logic_id_();
- logic_editor_widget_.setLogicId(logic_id);
- if (runtime_monitor_widget_ != nullptr)
- {
- runtime_monitor_widget_->setProjectObjects(
- hmi_navigation_service_.currentPageId(), logic_id);
- }
- logic_editor_widget_.setRuntimeTrace(
- runtime_mode_service_.offlineSimulationService()
- .traceSnapshot().forLogic(logic_id),
- error.nodeId);
- if (runtime_monitor_widget_ != nullptr)
- {
- runtime_monitor_widget_->setLogicTrace(
- runtime_mode_service_.offlineSimulationService().traceSnapshot(),
- error.nodeId);
- }
- if (!error.nodeId.empty())
- {
- logic_editor_widget_.selectNode(error.nodeId);
- show_logic_properties_(error.nodeId);
- }
- QString message = QObject::tr("离线仿真异常:%1").arg(fromUtf8(error.message));
- if (!error.logicId.empty())
- {
- message += QObject::tr(",逻辑 %1").arg(fromUtf8(error.logicId));
- }
- if (!error.rungId.empty())
- {
- message += QObject::tr(",网络 %1").arg(fromUtf8(error.rungId));
- }
- if (!error.nodeId.empty())
- {
- message += QObject::tr(",节点 %1").arg(fromUtf8(error.nodeId));
- }
- status_reporter_(message, 0);
- output_reporter_(message);
- break;
- }
- case SimulationState::Stopped:
- default:
- {
- executor_status_label_.setText(QObject::tr("逻辑执行器:停止"));
- break;
- }
- }
- }
-
- void RuntimePanelController::handleRuntimeTimer()
- {
- // 定时器只刷新投影;离线按定时器扫描,真机在完整 PLC 轮询后推算
- if (runtime_mode_service_.mode() == ApplicationMode::Editing)
- {
- return;
- }
- alarm_service_.refresh();
- hmi_editor_widget_.refreshRuntimeValues();
- if (runtime_monitor_widget_ != nullptr)
- {
- runtime_monitor_widget_->refreshValues(
- runtime_mode_service_.mode(),
- runtime_mode_service_.plcConnectionState());
- }
- updateSimulationUi(false);
- }
-
- void RuntimePanelController::handleSimulationStateChanged()
- {
- updateSimulationUi(true);
- }
-
- void RuntimePanelController::handleScanCompleted()
- {
- const ApplicationMode mode = runtime_mode_service_.mode();
- const bool offline_running = mode == ApplicationMode::OfflineRunning
- && runtime_mode_service_.simulationState() == SimulationState::Running;
- const bool online_running = mode == ApplicationMode::OnlineRunning
- && runtime_mode_service_.onlineLogicMonitorService().state()
- == OnlineLogicMonitorState::Running;
- // 排队信号可能晚于退出操作到达,编辑态不得恢复旧运行轨迹
- if (!offline_running && !online_running)
- {
- return;
- }
- const std::string logic_id = current_logic_id_();
- const LogicTraceSnapshot &trace = offline_running
- ? runtime_mode_service_.offlineSimulationService().traceSnapshot()
- : runtime_mode_service_.onlineLogicMonitorService().traceSnapshot();
- logic_editor_widget_.setRuntimeTrace(trace.forLogic(logic_id));
- if (runtime_monitor_widget_ != nullptr)
- {
- runtime_monitor_widget_->setLogicTrace(trace);
- }
- }
|