Przeglądaj źródła

爆破异常处理

Yao 1 miesiąc temu
rodzic
commit
2a2094d151
7 zmienionych plików z 105 dodań i 27 usunięć
  1. 7 0
      backendapimanager.cpp
  2. 2 18
      blastopepage.cpp
  3. 52 4
      fireWidget/firingwidget.cpp
  4. 32 0
      fireWidget/firingwidget.h
  5. 2 2
      global.cpp
  6. 8 1
      global.h
  7. 2 2
      mainwindow.cpp

+ 7 - 0
backendapimanager.cpp

@@ -2,6 +2,8 @@
 
 #include <QEventLoop>
 
+#include "logger.h"
+
 backendAPIManager *backendAPIManager::s_instance = nullptr;
 
 void backendAPIManager::initialize(const QString &backendUrl) {
@@ -66,6 +68,7 @@ QNetworkReply *backendAPIManager::sendRequest(const QString &endpoint, const QJs
     return reply;
 }
 
+// 上传爆破记录完整记录. 包含设备和雷管记录
 bool backendAPIManager::uploadBlastProjectFull(const QJsonObject &projectData) {
     if (!s_instance) return false;
 
@@ -81,6 +84,10 @@ bool backendAPIManager::uploadBlastProjectFull(const QJsonObject &projectData) {
         QJsonDocument response = QJsonDocument::fromJson(reply->readAll());
         s_instance->handleUploadFinished(response, reply->url());
     } else {
+        Logger::getInstance().error(
+            QString("UploadBlastProjectFull request failed. uuid: %1 error message: %2")
+                .arg(projectData.value("uuid").toString())
+                .arg(reply->errorString()));
         s_instance->handleUploadError(reply->errorString());
     }
 

+ 2 - 18
blastopepage.cpp

@@ -76,7 +76,7 @@ void BlastOpePage::InitFace() {
         return;
     }
     if (response.contains("data") && response["data"].isObject()) {
-        LoadingWidget::showLoading(this, "正在打开人脸识别界面...");
+        LoadingWidget::showLoading(this, "人脸识别请求已创建...");
         QJsonObject dataObject = response["data"].toObject();
         if (dataObject.contains("ResultObject") && dataObject["ResultObject"].isObject()) {
             QJsonObject resultObject = dataObject["ResultObject"].toObject();
@@ -99,9 +99,8 @@ void BlastOpePage::InitFace() {
     } else {
         QMessageBox::information(nullptr, "提示", "人脸识别请求失败");
         Logger::getInstance().error("FaceVerificationInit: Failed to get certifyUrl");
+        LoadingWidget::hideLoading();
     }
-    Logger::getInstance().info("FaceVerificationInit: successfully");
-    LoadingWidget::hideLoading();
 }
 
 void BlastOpePage::closeWebViewAndRestoreUI() {
@@ -408,24 +407,9 @@ void BlastOpePage::loadDataFromSource(int currentPage, int pageSize) {
         QModelIndex statusIndex = model->index(row, propMap.key("blastStatus"));
         if (statusIndex.isValid()) {
             QString blastStatus = model->data(statusIndex).toString();
-            /*if (blastStatus == "起 爆 完 成") {
-                // 为按钮添加图标,这里假设图标文件名为 icon.png,你需要根据实际情况修改
-                QIcon icon(":/icons/icons/svg/blast.svg");
-                button->setIcon(icon);
-                button->setIconSize(QSize(32, 32));  // 设置图标大小
-                button->setStyleSheet(
-                    "QPushButton {"
-                    "    padding: 0px;"
-                    "    border: none;"
-                    "    background-color: transparent;"
-                    "}");
-            } else*/
             if (blastStatus == "待起爆") {
                 button->setText(startBlastButtonTxt);
                 button->setEnabled(true);
-            } else {
-                button->setText("待安全员确认");
-                button->setDisabled(true);
             }
         }
         QHBoxLayout *layout = new QHBoxLayout(widget);

+ 52 - 4
fireWidget/firingwidget.cpp

@@ -90,7 +90,38 @@ void firingWidget::startBlasting() {
     });
     connectionCheckTimer->start(2000);
 }
+void firingWidget::cancelBlasting();
+void firingWidget::on_sendTest_4_clicked();
+
+void firingWidget::startHeartbeatMonitor() {
+    m_isHeartBeating = true;
+    QThread *heartbeatThread = new QThread();
+    QTimer *heartbeatTimer = new QTimer(nullptr);
+    heartbeatTimer->setInterval(3000);  // 3 seconds interval
+    heartbeatTimer->moveToThread(heartbeatThread);
+
+    connect(heartbeatThread, &QThread::started, heartbeatTimer,
+            static_cast<void (QTimer::*)()>(&QTimer::start));
+    connect(heartbeatThread, &QThread::finished, heartbeatTimer, &QTimer::stop);
+    connect(heartbeatThread, &QThread::finished, heartbeatTimer, &QTimer::deleteLater);
+    connect(heartbeatThread, &QThread::finished, heartbeatThread, &QThread::deleteLater);
+
+    connect(heartbeatTimer, &QTimer::timeout, this, [this]() {
+        if (!m_isHeartBeating) {
+            Logger::getInstance().error("爆破器心跳检测失败,连接可能已断开");
+            QMetaObject::invokeMethod(
+                this,
+                [this]() {
+                    QMessageBox::critical(this, "连接错误", "爆破器心跳检测失败,连接可能已断开");
+                    cancelBlasting();
+                },
+                Qt::QueuedConnection);
+        }
+        m_isHeartBeating = false;  // Reset flag for next interval
+    });
 
+    heartbeatThread->start();
+}
 void firingWidget::on_pushButton_2_clicked() { emit countdown(m_uuid, topic, "message"); }
 
 // NOTE: aborted, changed to upload in the smartmine server side.
@@ -168,20 +199,35 @@ void firingWidget::handleProjectFiringMqttMessage(const QByteArray &message,
     if (textEdit) {
         textEdit->append(msgText);
     }
-
     qDebug() << ANSI_COLOR_GREEN << "Received message on topic:" << topic.name()
              << ", Message:" << QString(message) << ANSI_COLOR_RESET;
-
     int stage = 0;
     QJsonDocument jsonDoc = QJsonDocument::fromJson(message);
     if (!jsonDoc.isNull() && jsonDoc.isObject()) {
         QJsonObject jsonObj = jsonDoc.object();
+
         if (jsonObj.contains("type") && jsonObj["type"].toInt() == 1) {
             if (jsonObj.contains("data") && jsonObj["data"].isObject()) {
                 QJsonObject dataObject = jsonObj["data"].toObject();
+                if (!dataObject.contains("status")) {
+                    qDebug() << "Received JSON does not contain 'status' field.";
+                }
+                int status = dataObject["status"].toInt();
+                if (ErrorBlastStatusList::isErrorStatus(status)) {
+                    Logger::getInstance().error(
+                        QString("爆破器返回异常. 工程uuid: %1; 错误code: %2")
+                            .arg(m_uuid, ErrorBlastStatusList::getErrorMessage(status)));
+                    QMessageBox::critical(nullptr, "爆破器报错",
+                                          QString("错误错误信息: %1")
+                                              .arg(ErrorBlastStatusList::getErrorMessage(status)));
+
+                    emit updateBlastStatus(status, m_row);
+                    ui->pushButton_2->setEnabled(false);
+                    return;
+                }
+
                 stage = dataObject["stage"].toInt();
                 if (stage != lastStage) {
-                    // TODO: check available stage
                     lastStage = stage;
                     switch (stage) {
                         case 0:
@@ -236,7 +282,6 @@ void firingWidget::handleProjectFiringMqttMessage(const QByteArray &message,
                             navProgress->setState(6);
                             break;
                         case 7:
-                            qDebug() << "status:" << stage;
                             ui->pushButton_2->setEnabled(false);
                             emit progressChanged(0, m_row);    // 发送进度值
                             emit updateBlastStatus(0, m_row);  // 正在测试
@@ -391,6 +436,7 @@ void firingWidget::saveAndUploadRecord(const QJsonObject &jsonObj) {
         return;
     }
 
+    qDebug() << "Starting transaction for blast record with uuid:" << jsonObj;
     HBlastRecord *blastRecord = recordBlastProject(jsonObj);
     if (blastRecord == nullptr) {
         Logger::getInstance("error_blast_records.log")
@@ -427,6 +473,8 @@ void firingWidget::saveAndUploadRecord(const QJsonObject &jsonObj) {
         return;
     }
 
+    qDebug() << "Transaction committed successfully for blast record with uuid:"
+             << blastRecord->getUuid();
     uploadBlastRecordToServer(blastRecord);
 }
 

+ 32 - 0
fireWidget/firingwidget.h

@@ -21,6 +21,38 @@ namespace Ui {
 class firingWidget;
 }
 
+// Error status codes for device and bus issues
+class ErrorBlastStatusList {
+   public:
+    // Error code constants
+    static const int DEV_ERROR = 0xA0;        // Device exception
+    static const int BUS_SHORT = 0xA1;        // Bus short circuit
+    static const int BUS_VOLTAGE_ERR = 0xA2;  // Bus voltage abnormal
+    static const int DET_OFFLINE_ERR = 0xA3;  // Detonator offline
+
+    // Check if a status code exists in the error list
+    static bool isErrorStatus(int code) { return getErrorMap().find(code) != getErrorMap().end(); }
+
+    // Get error message for a status code
+    static QString getErrorMessage(int code) {
+        const auto &map = getErrorMap();
+        auto it = map.find(code);
+        return (it != map.end()) ? it->second : "Unknown error";
+    }
+
+   private:
+    // Internal function to get the error map (lazy initialization)
+    static const std::map<int, QString> &getErrorMap() {
+        static const std::map<int, QString> errorMap = {{DEV_ERROR, "Device exception"},
+                                                        {BUS_SHORT, "Bus short circuit"},
+                                                        {BUS_VOLTAGE_ERR, "Bus voltage abnormal"},
+                                                        {DET_OFFLINE_ERR, "Detonator offline"}};
+        return errorMap;
+    }
+};
+
+// The map will be initialized in the cpp file
+
 class firingWidget : public QWidget {
     Q_OBJECT
 

+ 2 - 2
global.cpp

@@ -1,10 +1,10 @@
 #include "global.h"
 
-QUrl apiBackendUrl("http://localhost:8000/api/v1/");  // 定义并初始化全局变量
+QUrl apiBackendUrl("http://192.168.0.241:8000/api/v1/");  // 定义并初始化全局变量
 QString labLat("未知");
 QString labLon("未知");
 QString globalAuthority;
-QString firewidgetPort("COM4");  // 4 for dev; 1: 爆破装
+QString firewidgetPort("COM1");  // 4 for dev; 1: 爆破装
 QString gpsPort("COM3");
 QString databaseHost("192.168.0.241");
 QString mqttClientId("mqttclient_OnDevPC");

+ 8 - 1
global.h

@@ -18,7 +18,7 @@ extern QString mqttClientId;                 // mqtt客户端ID
 extern QString MQTT_TOPIC_CAMPANY_PROJECTS;  // 每个部署点(公司)唯一地址
 extern bool isShowTriggeringWidget;          // 是否显示点火装置触发中调试组件
 
-/* BlastStatus (1未注册2注册成功3充电4起爆)*/
+/* BlastStatus*/
 namespace BlastStatus {
 const QString Created = "1";
 const QString Registered = "2";
@@ -26,4 +26,11 @@ const QString Blasted = "3";
 const QString SafeChecked = "5";
 }  // namespace BlastStatus
 
+namespace BlastStatusNames {
+const QString Created = "未注册";
+const QString Registered = "已注册";
+const QString Blasted = "爆破完成";
+const QString SafeChecked = "已安全检查";
+}  // namespace BlastStatusNames
+
 #endif  // GLOBAL_H

+ 2 - 2
mainwindow.cpp

@@ -23,8 +23,8 @@
 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
     try {
         this->setWindowFlags(Qt::FramelessWindowHint);
-        // this->setWindowState(Qt::WindowMaximized);  // Maximizes the window
-        this->setFixedSize(1360, 864);
+        this->setWindowState(Qt::WindowMaximized);  // Maximizes the window
+        // this->setFixedSize(1360, 864);
         ui->setupUi(this);
         LoadingWidget::init(ui->stackedWidget);