#include "firingwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "../utils/backendapimanager.h" #include "../utils/global.h" #include "../utils/logger.h" #include "ui_firingwidget.h" #define ANSI_COLOR_GREEN "\x1B[32m" #define ANSI_COLOR_RESET "\x1B[0m" #define MSG_DATA_TYPE_BLASTING 1 #define MSG_DATA_TYPE_RECORD 2 firingWidget::firingWidget(const int &row, const bool &select, const QString &uuid, QWidget *parent) : QWidget(parent), ui(new Ui::firingWidget), m_curProjUuid(uuid), m_row(row), m_select(select), daoProj(DatabaseManager::getInstance().getDatabase()), daoDet(DatabaseManager::getInstance().getDatabase()), daoReg(DatabaseManager::getInstance().getDatabase()) { ui->setupUi(this); ui->pushButton_2->setText("立即测试"); ui->textEdit->setStyleSheet("border: none;background: transparent;"); ui->frame_2->setStyleSheet("border: none;background: transparent;"); QFrame *frame = ui->frame_2; // 使用你为 QFrame 设置的对象名称 navProgress = new NavProgress(frame); ui->verticalLayout->setContentsMargins(0, 30, 0, 0); ui->scrollArea->setStyleSheet("background: rgba(0, 0, 0, 22); border-radius: 20px;"); ui->verticalLayout->addWidget(navProgress); m_topic = "hxgc/" + uuid + "/B"; QStringList topics = {m_topic}; m_connectionCheckTimer = new QTimer(this); m_subscription = mainMqttClient->subscribeToTopic(m_topic); connect(m_subscription, &QMqttSubscription::messageReceived, this, &firingWidget::handleProjectFiringMqttMessage); connect(this, &firingWidget::lastStageChanged, this, &firingWidget::handleFiringStageChanged); } firingWidget::~firingWidget() { m_subscription->unsubscribe(); delete ui; } void firingWidget::sendMqttMessage(const QString &topic, const QByteArray &message) { qDebug() << ANSI_COLOR_GREEN << "XXX Sending MQTT message to topic:" << topic << "with message:" << message << ANSI_COLOR_RESET; if (mainMqttClient->isConnected()) { mainMqttClient->sendMessage(topic, message, quint8(2), false); } else { QMessageBox::warning(nullptr, "MQTT未连接", "MQTT未连接, 无法发送消息: " + topic + ", " + message); Logger::getInstance().error("MQTT未连接, 无法发送消息" + topic + ", " + message); } } void firingWidget::startBlasting() { // 等待3s mqtt连接后再发送mqtt消息 m_lastStage = FiringStages::Starting; qDebug() << ANSI_COLOR_GREEN << "Firing widget started with topic: 1" << m_topic << ANSI_COLOR_RESET; emit lastStageChanged(FiringStages::Starting); qDebug() << ANSI_COLOR_GREEN << "Firing widget started with topic: 2" << m_topic << ANSI_COLOR_RESET; checkBlasterConnection(); } // 定间隔检查有没有收到爆破器返回信息 void firingWidget::checkBlasterConnection() { m_lastMsgTime = QDateTime::currentDateTime(); connect(m_subscription, &QMqttSubscription::messageReceived, this, [&]() { m_lastMsgTime = QDateTime::currentDateTime(); }); connect(m_connectionCheckTimer, &QTimer::timeout, this, [this]() { if (m_lastStage == FiringStages::CancelConfirmed || m_lastStage == FiringStages::BlastFinished || m_lastStage == FiringStages::ForceCanceled) { m_connectionCheckTimer->stop(); return; } if (m_lastMsgTime.secsTo(QDateTime::currentDateTime()) > 3) { m_connectionCheckTimer->stop(); QMessageBox msgBox; msgBox.setWindowTitle("起爆检测测试错误"); msgBox.setText("超时未收到爆破器消息,是否继续等待"); QPushButton *yesButton = msgBox.addButton("继续等待", QMessageBox::YesRole); QPushButton *noButton = msgBox.addButton("强制取消", QMessageBox::NoRole); yesButton->setStyleSheet( "QPushButton { background-color:rgb(5, 58, 156); color: white; padding: 5px 15px; " "border-radius: 4px; }"); noButton->setStyleSheet( "QPushButton { background-color: #f44336; color: white; padding: 5px 15px; " "border-radius: 4px; }"); msgBox.exec(); if (msgBox.clickedButton() == noButton) { emit lastStageChanged(FiringStages::ForceCanceled); return; } m_connectionCheckTimer->start(5000); } }); m_connectionCheckTimer->start(1000); } void firingWidget::handleProjectFiringMqttMessage(const QMqttMessage &message) { QString msgText = QString("Topic: %1, Message: %2").arg(message.topic().name(), QString(message.payload())); QTextEdit *textEdit = ui->scrollAreaWidgetContents->findChild("textEdit"); if (textEdit) { textEdit->append(msgText); } int stage = 0; QJsonDocument jsonDoc = QJsonDocument::fromJson(message.payload()); if (!jsonDoc.isNull() && jsonDoc.isObject()) { QJsonObject jsonObj = jsonDoc.object(); if (jsonObj.contains("type") && jsonObj["type"].toInt() == MSG_DATA_TYPE_BLASTING) { if (jsonObj.contains("data") && jsonObj["data"].isObject()) { QJsonObject relayInfo = jsonObj["data"].toObject(); int status = relayInfo["status"].toInt(); if (ErrorBlastStatus::isErrorStatus(status)) { Logger::getInstance().error(QString("爆破器返回异常. 工程uuid: %1; 错误code: %2") .arg(m_curProjUuid, ErrorBlastStatus::getErrorMessage(status))); QMessageBox::critical(nullptr, "爆破器报错", QString("错误错误信息: %1").arg(ErrorBlastStatus::getErrorMessage(status))); sendCancelFiringMsg(); return; } stage = relayInfo["stage"].toInt(); if (stage != m_lastStage) { m_lastStage = stage; switch (stage) { case FiringStages::Starting: navProgress->setState(FiringStages::Starting); ui->pushButton_2->setText("立即测试"); ui->pushButton_2->setEnabled(false); break; case FiringStages::QuickTesting: navProgress->setState(FiringStages::QuickTesting); emit updatefiringStage(FiringStages::QuickTesting, m_row); ui->pushButton_2->setText("立即测试"); ui->pushButton_2->setEnabled(false); break; case FiringStages::QuickTestFinished: // 起爆检测测试检查报错雷管数量,如果有错误,提示用户确认是否继续 if (relayInfo["errorCount"].toInt() > 0) { m_connectionCheckTimer->stop(); QMessageBox msgBox; msgBox.setWindowTitle("起爆检测测试错误"); msgBox.setText(QString("起爆检测测试发现 %1 个报错雷管,是否继续起爆?") .arg(relayInfo["errorCount"].toInt())); QPushButton *yesButton = msgBox.addButton("确定继续", QMessageBox::YesRole); QPushButton *noButton = msgBox.addButton("取消", QMessageBox::NoRole); yesButton->setStyleSheet( "QPushButton { background-color:rgb(5, 58, 156); color: white; padding: 5px 15px; " "border-radius: 4px; }"); noButton->setStyleSheet( "QPushButton { background-color: #f44336; color: white; padding: 5px 15px; " "border-radius: 4px; }"); msgBox.exec(); if (msgBox.clickedButton() == noButton) { sendCancelFiringMsg(); return; } m_connectionCheckTimer->start(); } ui->pushButton_2->setEnabled(true); ui->pushButton_2->setText("充电"); navProgress->setState(FiringStages::QuickTestFinished); emit progressChanged(FiringStages::QuickTestFinished, m_row); emit updatefiringStage(FiringStages::QuickTestFinished, m_row); break; case FiringStages::NetCharging: ui->pushButton_2->setEnabled(false); emit progressChanged(FiringStages::NetCharging, m_row); emit updatefiringStage(FiringStages::NetCharging, m_row); ui->pushButton_2->setText("充电"); navProgress->setState(FiringStages::NetCharging); break; case FiringStages::NetChargingFinished: ui->pushButton_2->setEnabled(true); ui->pushButton_2->setText("起爆"); navProgress->setState(FiringStages::NetChargingFinished); emit progressChanged(FiringStages::NetChargingFinished, m_row); emit updatefiringStage(FiringStages::NetChargingFinished, m_row); break; case FiringStages::Blasting: ui->pushButton_2->setEnabled(false); emit progressChanged(FiringStages::Blasting, m_row); emit updatefiringStage(FiringStages::Blasting, m_row); ui->pushButton_2->setText("起爆"); navProgress->setState(FiringStages::Blasting); break; case FiringStages::BlastFinished: ui->pushButton_2->setEnabled(false); emit progressChanged(FiringStages::BlastFinished, m_row); emit updatefiringStage(FiringStages::BlastFinished, m_row); emit updateProjectStatus(m_curProjUuid, BlastStatus::Blasted); ui->pushButton_2->setText("已完成起爆"); navProgress->setState(FiringStages::BlastFinished); emit closeFiring(m_curProjUuid, m_row); break; case FiringStages::CancelConfirmed: navProgress->setState(FiringStages::BlastFinished); ui->pushButton_2->setEnabled(false); ui->pushButton_2->setText("已确认取消"); emit progressChanged(FiringStages::Starting, m_row); emit updatefiringStage(FiringStages::CancelConfirmed, m_row); emit updateProjectStatus(m_curProjUuid, BlastStatus::Created); emit closeFiring(m_curProjUuid, m_row); break; default: break; } emit lastStageChanged(m_lastStage); } } } } } void firingWidget::onCountdownFinished(const QString &topic, const QString &message) { qDebug() << "Countdown finished for topic:" << topic << ", message:" << message; sendMqttMessage(topic, message.toUtf8()); } void firingWidget::onMqttDisconnected() { Logger::getInstance().info(QString("Project(%1) firing MQTT disconncted.").arg(m_curProjUuid)); } void firingWidget::onMqttConnected() { Logger::getInstance().info(QString("Project(%1) firing MQTT connected.").arg(m_curProjUuid)); } void firingWidget::onButtonPressedReceived(const QString &topic, const QString &message) { QByteArray data = "\r\nDISABLE_BUTTON\r\n"; // 调用发送数据的方法 bool success = serialTool->sendData(data); if (!success) { Logger::getInstance().error(QString("onButtonPressedReceived: Failed to send data: %1").arg(data)); return; } emit countdown(m_curProjUuid, topic, message); qDebug() << "Data sent successfully"; } void firingWidget::onSafeChecked(const QString projectUuid) { if (projectUuid == m_curProjUuid) { m_lastStage = 3; // 设置为待安全确认状态 emit projSafeCheckSuccess(m_curProjUuid); emit lastStageChanged(m_lastStage); qDebug() << ANSI_COLOR_GREEN << "安全确认成功,进入待起爆状态" << ANSI_COLOR_RESET; } else { qDebug() << "Project UUID mismatch, expected: " << m_curProjUuid << ", got: " << projectUuid; } } // 状态改变 void firingWidget::handleFiringStageChanged(int newStage) { qDebug() << ANSI_COLOR_GREEN << "handleFiringStageChanged: " << newStage << ANSI_COLOR_RESET; QString topic = "hxgc/" + m_curProjUuid + "/P"; QString message; QString buttonText; switch (newStage) { case FiringStages::Starting: message = "起爆测试"; buttonText = "立即测试"; sendMqttMessage(topic, message.toUtf8()); emit updatefiringStage(FiringStages::Starting, m_row); break; case FiringStages::QuickTestFinished: message = "开始充电"; buttonText = "充电"; sendMqttMessage(topic, message.toUtf8()); break; case FiringStages::NetChargingFinished: message = "起爆"; buttonText = "起爆"; break; case FiringStages::Blasting: if (!m_select) { if (connection) { disconnect(connection); qDebug() << "Connection disconnected."; } if (connectionPress) { disconnect(connectionPress); qDebug() << "connectionPress disconnected."; } serialTool->releaseInstance(); } qDebug() << ANSI_COLOR_GREEN << "释放按键 5" << ANSI_COLOR_RESET; break; case FiringStages::ForceCanceled: // 强制取消 sendCancelFiringMsg(); emit updateProjectStatus(m_curProjUuid, BlastStatus::Created); emit updatefiringStage(FiringStages::ForceCanceled, m_row); emit closeFiring(m_curProjUuid, m_row); break; default: return; } qDebug() << ANSI_COLOR_GREEN << "Stage 值变为: i2" << newStage << ANSI_COLOR_RESET; if (!message.isEmpty()) { if (m_lastStage == FiringStages::NetChargingFinished && !m_select) { bool success2; serialTool = SerialTool::getInstance(nullptr, &success2); if (serialTool) { QByteArray data = "\r\nENABLE_BUTTON\r\n"; bool success = serialTool->sendData(data); if (success) { qDebug() << "Data sent successfully"; } else { qDebug() << "Failed to send data"; } connection = connect(serialTool, &SerialTool::enableButtonReceived, [this]() { emit updatefiringStage(10, m_row); }); connectionPress = connect(serialTool, &SerialTool::buttonPressedReceived, [this, topic, message]() { this->onButtonPressedReceived(topic, message); }); } else { qDebug() << "serialTool Not found."; // 在准备起爆状态下 但是没有获取串口 m_lastStage = FiringStages::PendingTriggerButtonClick; } } else if (m_lastStage == FiringStages::NetChargingFinished && m_select) { qDebug() << "多台起爆:待起爆状态"; emit batchFiringSignal(m_curProjUuid); } else { qDebug() << "Stage 值变为: " << newStage << "发送消息" << message.toUtf8(); } } } void firingWidget::sendCancelFiringMsg() { QString message = "取消流程"; QString topic = "hxgc/" + m_curProjUuid + "/P"; sendMqttMessage(topic, message.toUtf8()); }