diff --git a/app/src/infrastructure/plc_communication_service.cpp b/app/src/infrastructure/plc_communication_service.cpp index 386ad0c..8009b99 100644 --- a/app/src/infrastructure/plc_communication_service.cpp +++ b/app/src/infrastructure/plc_communication_service.cpp @@ -28,6 +28,32 @@ QModbusDataUnit::RegisterType registerType(RegisterArea area) ? QModbusDataUnit::Coils : QModbusDataUnit::HoldingRegisters; } +QString modbusErrorText(QModbusDevice::Error error) +{ + switch (error) + { + case QModbusDevice::ReadError: + return QStringLiteral("读取 PLC 数据失败"); + case QModbusDevice::WriteError: + return QStringLiteral("写入 PLC 数据失败"); + case QModbusDevice::ConnectionError: + return QStringLiteral("PLC 串口连接失败"); + case QModbusDevice::ConfigurationError: + return QStringLiteral("PLC 串口参数配置错误"); + case QModbusDevice::TimeoutError: + return QStringLiteral("PLC 通信超时,请检查站号、串口参数和 RS-485 接线"); + case QModbusDevice::ProtocolError: + return QStringLiteral("PLC 返回了无效或异常的 Modbus 响应"); + case QModbusDevice::ReplyAbortedError: + return QStringLiteral("PLC 通信请求已取消"); + case QModbusDevice::UnknownError: + return QStringLiteral("PLC 通信发生未知错误"); + case QModbusDevice::NoError: + default: + return QStringLiteral("PLC 通信失败"); + } +} + } // namespace PlcCommunicationService::PlcCommunicationService( @@ -73,7 +99,7 @@ PlcCommunicationService::PlcCommunicationService( { if (error != QModbusDevice::NoError) { - setError(master_->errorString()); + setError(modbusErrorText(error)); } }); } @@ -86,13 +112,14 @@ PlcCommunicationResult PlcCommunicationService::connectDevice( if (QString::fromStdString(configuration.portName).trimmed().isEmpty() || configuration.serverAddress < 1 || configuration.serverAddress > 247) { - return {false, "serial port and Modbus server address are required"}; + return {false, "必须填写串口端口,并将 PLC 站号设置为 1~247"}; } if (master_->state() != QModbusDevice::UnconnectedState) { - return {false, "PLC connection is already active"}; + return {false, "PLC 连接已经启动,请先断开当前连接"}; } configuration_ = configuration; + last_error_.clear(); master_->setConnectionParameter( QModbusDevice::SerialPortNameParameter, QString::fromStdString(configuration.portName)); @@ -117,12 +144,12 @@ PlcCommunicationResult PlcCommunicationService::connectDevice( initial_read_changed_callback_(false); } rebuildPollBlocks(); + setState(PlcConnectionState::Connecting); if (!master_->connectDevice()) { - setError(master_->errorString()); + setError(modbusErrorText(master_->error())); return {false, last_error_}; } - setState(PlcConnectionState::Connecting); return {true, {}}; } @@ -240,7 +267,7 @@ void PlcCommunicationService::pollNextBlock() QModbusReply *reply = master_->sendReadRequest(request, configuration_.serverAddress); if (reply == nullptr) { - setError(master_->errorString()); + setError(modbusErrorText(master_->error())); return; } pending_reply_ = reply; @@ -284,7 +311,7 @@ void PlcCommunicationService::handleReadFinished(QModbusReply *reply, PollBlock } if (reply->error() != QModbusDevice::NoError) { - setError(reply->errorString()); + setError(modbusErrorText(reply->error())); return; } const QModbusDataUnit result = reply->result(); @@ -320,7 +347,7 @@ RegisterWriteResult PlcCommunicationService::sendBitWrite( QModbusReply *reply = master_->sendWriteRequest(unit, configuration_.serverAddress); if (reply == nullptr) { - setError(master_->errorString()); + setError(modbusErrorText(master_->error())); return {false, RegisterError::WriteRejected}; } connect(reply, &QModbusReply::finished, @@ -329,7 +356,7 @@ RegisterWriteResult PlcCommunicationService::sendBitWrite( { if (reply->error() != QModbusDevice::NoError) { - setError(reply->errorString()); + setError(modbusErrorText(reply->error())); } reply->deleteLater(); }); @@ -348,7 +375,7 @@ RegisterWriteResult PlcCommunicationService::sendWordWrite( QModbusReply *reply = master_->sendWriteRequest(unit, configuration_.serverAddress); if (reply == nullptr) { - setError(master_->errorString()); + setError(modbusErrorText(master_->error())); return {false, RegisterError::WriteRejected}; } connect(reply, &QModbusReply::finished, @@ -357,7 +384,7 @@ RegisterWriteResult PlcCommunicationService::sendWordWrite( { if (reply->error() != QModbusDevice::NoError) { - setError(reply->errorString()); + setError(modbusErrorText(reply->error())); } reply->deleteLater(); }); diff --git a/app/src/ui/main_window.cpp b/app/src/ui/main_window.cpp index a1397bb..73aac9a 100644 --- a/app/src/ui/main_window.cpp +++ b/app/src/ui/main_window.cpp @@ -100,6 +100,29 @@ QString fromUtf8(const std::string &value) return QString::fromUtf8(value.data(), static_cast(value.size())); } +QString plcStatusText(const RuntimeModeService &service) +{ + switch (service.plcConnectionState()) + { + case PlcConnectionState::Connecting: + return MainWindow::tr("PLC 正在连接"); + case PlcConnectionState::Connected: + return service.initialPlcReadCompleted() + ? MainWindow::tr("PLC 已连接,首次读取完成") + : MainWindow::tr("PLC 已连接,正在读取工程使用的 M/D 地址"); + case PlcConnectionState::Faulted: + { + const QString error = fromUtf8(service.plcError()); + return error.isEmpty() + ? MainWindow::tr("PLC 通信故障") + : MainWindow::tr("PLC 通信故障:%1").arg(error); + } + case PlcConnectionState::Disconnected: + default: + return MainWindow::tr("PLC 已断开"); + } +} + QString controlTypeText(HmiControlType type) { switch (type) @@ -157,7 +180,7 @@ MainWindow::MainWindow( { QMetaObject::invokeMethod( this, - [this] { updateModeUi(tr("PLC 通信状态已更新")); }, + [this] { updateModeUi(plcStatusText(runtime_mode_service_)); }, Qt::QueuedConnection); }); hmi_editor_service_.ensureDefaultPage(); @@ -1011,6 +1034,10 @@ void MainWindow::requestMode(ApplicationMode requested_mode) { restoreCurrentModeAction(); QString message = transitionErrorText(result.error); + if (result.error == ModeTransitionError::InitialPlcReadRequired) + { + message += tr(";当前状态:%1").arg(plcStatusText(runtime_mode_service_)); + } if (result.error == ModeTransitionError::SimulationStartFailed) { const LogicScanResult &error = runtime_mode_service_.simulationError(); @@ -1083,12 +1110,20 @@ void MainWindow::updateModeUi(const QString &message) ui_->configurePlcAction->setEnabled( policy.allowsProjectEditing && plc_state == PlcConnectionState::Disconnected); ui_->disconnectPlcAction->setEnabled(plc_state != PlcConnectionState::Disconnected); - if (plc_state == PlcConnectionState::Connected) + if (plc_state == PlcConnectionState::Connecting) + { + register_status_label_->setText(tr("PLC:正在连接")); + } + else if (plc_state == PlcConnectionState::Connected) { register_status_label_->setText( runtime_mode_service_.initialPlcReadCompleted() ? tr("PLC:已连接,首读完成") : tr("PLC:已连接,正在首读")); } + else if (plc_state == PlcConnectionState::Faulted) + { + register_status_label_->setText(tr("PLC:通信故障")); + } updateSimulationUi(false); statusBar()->showMessage(message, 4000); ui_->outputList->addItem(message);