From 7cc7b12f332976197c18dc2fbc60370785ba3ebc Mon Sep 17 00:00:00 2001 From: luocai Date: Tue, 27 Aug 2024 11:14:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=94=B9OTA=E5=8D=87=E7=BA=A7?= =?UTF-8?q?=E6=AD=A5=E9=AA=A4=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application.cpp | 3 +- CMakeLists.txt | 2 +- DeviceConnection.cpp | 124 ++++++++++++++++++++++++------------ DeviceConnection.h | 4 +- qml/DeviceView.qml | 7 +- qml/IpTextField.qml | 2 +- qml/Main.qml | 28 +++++++- qml/NetworkSettingPopup.qml | 2 +- qml/OtaPopup.qml | 27 ++------ 9 files changed, 127 insertions(+), 72 deletions(-) diff --git a/Application.cpp b/Application.cpp index c1e092e..f16e045 100644 --- a/Application.cpp +++ b/Application.cpp @@ -15,9 +15,10 @@ Application::Application(int &argc, char **argv) m_collector(new DataCollection(this)) { QFont font; font.setPointSize(16); + font.setFamily("微软雅黑"); m_app->setFont(font); m_app->setApplicationName(APPLICATION_NAME); - m_app->setApplicationVersion(QString("v%1").arg(APP_VERSION)); + m_app->setApplicationVersion(QString("V%1").arg(APP_VERSION)); m_player->open(); } diff --git a/CMakeLists.txt b/CMakeLists.txt index 25e549a..ae96fcf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.16) project(AntiClipSettings VERSION 1.1 LANGUAGES C CXX) -set(APPLICATION_NAME "T009上位机工具") +set(APPLICATION_NAME "视觉防夹设备上位机工具") set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/DeviceConnection.cpp b/DeviceConnection.cpp index 9c3e3b5..a7fc53c 100644 --- a/DeviceConnection.cpp +++ b/DeviceConnection.cpp @@ -14,6 +14,32 @@ DeviceConnection::DeviceConnection(QObject *parent) : QObject{parent} { } +DeviceConnection::~DeviceConnection() { + close(); +} + +void DeviceConnection::close() { + if (m_otaTimer != nullptr) { + m_otaTimer->deleteLater(); + m_otaTimer = nullptr; + } + if (m_timerId > 0) { + killTimer(m_timerId); + m_timerId = -1; + } + if (m_commandSocket != nullptr) { + m_commandSocket->deleteLater(); + m_commandSocket = nullptr; + } + if (m_h264Socket != nullptr) { + m_h264Socket->deleteLater(); + m_h264Socket = nullptr; + } + while (!m_requests.empty()) { + m_requests.pop(); + } +} + DeviceConnection::Infomation DeviceConnection::infomation() const { return m_infomation; } @@ -28,15 +54,7 @@ bool DeviceConnection::isConnected() const { } void DeviceConnection::connect(const Infomation &infomation) { - while (!m_requests.empty()) { - m_requests.pop(); - } - if (m_commandSocket != nullptr) { - m_commandSocket->deleteLater(); - } - if (m_h264Socket != nullptr) { - m_h264Socket->deleteLater(); - } + close(); m_infomation = infomation; m_commandSocket = new QTcpSocket(this); QObject::connect(m_commandSocket, &QTcpSocket::disconnected, this, &DeviceConnection::onDisconnected); @@ -317,6 +335,9 @@ void DeviceConnection::requestOta(const QString &firmware, const QString &file) killTimer(m_timerId); m_timerId = -1; } + if (!m_requests.empty()) { + m_requests.pop(); + } Task task; task.command = "a22devicefirmware_setdata"; task.task = [this, file, firmware]() { @@ -379,22 +400,42 @@ void DeviceConnection::transferBinContent() { m_otaProgress < 98 ? "向设备发送升级固件......" : "升级固件发送完成,等待设备校验升级固件......"); - if (m_sendedSize < m_uploadBuffer.size()) { + if ((m_sendedSize < m_uploadBuffer.size()) && isConnected()) { QTimer::singleShot(0, this, &DeviceConnection::transferBinContent); } else if (m_sendedSize >= m_uploadBuffer.size()) { LOG(info) << "transfer ota file finished, wait " << WaitMd5CheckTime << " ms for send check, total sended size: " << m_sendedSize; - QTimer::singleShot(WaitMd5CheckTime, this, [this]() { - boost::json::object request; - request["func"] = "a22devicefirmware_setdata"; - request["deviceid"] = "0"; - boost::json::object data; - data["target_linux04_firmware"] = "RD_T009_V21R003B001"; - request["data"] = std::move(data); - auto text = boost::json::serialize(request); - m_commandSocket->write(text.data(), text.size()); - LOG(info) << "request md5 check result: " << text; - }); + // QTimer::singleShot(WaitMd5CheckTime, this, [this]() { + // boost::json::object request; + // request["func"] = "a22devicefirmware_setdata"; + // request["deviceid"] = "0"; + // boost::json::object data; + // data["target_linux04_firmware"] = "RD_T009_V21R003B001"; + // request["data"] = std::move(data); + // auto text = boost::json::serialize(request); + // m_commandSocket->write(text.data(), text.size()); + // LOG(info) << "request md5 check result: " << text; + // }); + + if (m_otaTimer == nullptr) { + m_otaTimer = new QTimer(this); + m_otaTimer->setSingleShot(true); + } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + Qt::ConnectionType type = Qt::SingleShotConnection; +#else + Qt::ConnectionType type = Qt::UniqueConnection; +#endif + m_otaTimer->callOnTimeout( + this, + [this]() { + emit otaProgressChanged(false, m_otaProgress, "升级超时,请检查设备并重新尝试..."); + m_otaProgress = -1; + m_commandSocket->close(); + m_h264Socket->close(); + }, + type); + m_otaTimer->start(60 * 1000); } } @@ -515,29 +556,32 @@ QString DeviceConnection::handleCommand(const std::string_view &replyText, const } else if (value == "2") { LOG(info) << "md5 check finished"; m_otaProgress = 99; + if (m_otaTimer != nullptr) { + m_otaTimer->stop(); + } emit otaProgressChanged(true, m_otaProgress, "设备正在升级中,请稍后......"); QTimer::singleShot(0, this, [this]() { m_commandSocket->close(); // 等待设备重新上线后,发起广播。由搜索服务触发重连 m_h264Socket->close(); - if (m_otaTimer == nullptr) { - m_otaTimer = new QTimer(this); - m_otaTimer->setSingleShot(true); - } -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - Qt::ConnectionType type = Qt::SingleShotConnection; -#else - Qt::ConnectionType type = Qt::UniqueConnection; -#endif - m_otaTimer->callOnTimeout( - this, - [this]() { - emit otaProgressChanged(false, m_otaProgress, "升级超时,请检查设备并重新尝试..."); - m_otaProgress = -1; - m_commandSocket->close(); - m_h264Socket->close(); - }, - type); - m_otaTimer->start(60 * 1000); + // if (m_otaTimer == nullptr) { + // m_otaTimer = new QTimer(this); + // m_otaTimer->setSingleShot(true); + // } + // #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + // Qt::ConnectionType type = Qt::SingleShotConnection; + // #else + // Qt::ConnectionType type = Qt::UniqueConnection; + // #endif + // m_otaTimer->callOnTimeout( + // this, + // [this]() { + // emit otaProgressChanged(false, m_otaProgress, + // "升级超时,请检查设备并重新尝试..."); m_otaProgress = -1; + // m_commandSocket->close(); + // m_h264Socket->close(); + // }, + // type); + // m_otaTimer->start(60 * 1000); }); } else { const char *message = nullptr; diff --git a/DeviceConnection.h b/DeviceConnection.h index 046f114..aebab30 100644 --- a/DeviceConnection.h +++ b/DeviceConnection.h @@ -50,7 +50,8 @@ public: }; using H264FrameCallback = std::function; - explicit DeviceConnection(QObject *parent = nullptr); + DeviceConnection(QObject *parent = nullptr); + ~DeviceConnection(); Infomation infomation() const; bool isConnected() const; void setH264FrameCallback(H264FrameCallback &&callback); @@ -102,6 +103,7 @@ protected: std::shared_ptr timeoutTimer = nullptr; std::shared_ptr> future; }; + void close(); void onConnected(); void onDisconnected(); void onH264ReadyRead(); diff --git a/qml/DeviceView.qml b/qml/DeviceView.qml index 0341566..e4c9ed7 100644 --- a/qml/DeviceView.qml +++ b/qml/DeviceView.qml @@ -246,8 +246,7 @@ Item { columns: 2 spacing: 10 verticalItemAlignment: Qt.AlignVCenter - Text { - + Label { text: qsTr("开门区域: ") } Row { @@ -276,7 +275,7 @@ Item { } - Text {text: qsTr("防夹区域: ")} + Label {text: qsTr("防夹区域: ")} Row { enabled: root.enabled RadioButton { @@ -297,7 +296,7 @@ Item { } - Text {text: qsTr("屏蔽区域: ")} + Label {text: qsTr("屏蔽区域: ")} Row { id: shieldedRow RadioButton { diff --git a/qml/IpTextField.qml b/qml/IpTextField.qml index 8a58838..14dec8d 100644 --- a/qml/IpTextField.qml +++ b/qml/IpTextField.qml @@ -9,7 +9,7 @@ Column { property bool canEmpty: false property var regularExpression : /^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/ TextField { - height: 40 + height: 44 width: 350 id: input selectByMouse: true diff --git a/qml/Main.qml b/qml/Main.qml index fc96c8d..653c63a 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -15,6 +15,7 @@ ApplicationWindow { RowLayout { anchors.fill: parent Button { + Layout.leftMargin: 5 Material.background: Material.Blue text: "搜索设备" onClicked: { @@ -127,8 +128,8 @@ ApplicationWindow { footer: RowLayout { width: parent.width - Item {} Button { + Layout.leftMargin: 5 text: App.collector.enabled ? "停止采集" : "数据采集" onClicked: { if (App.collector.enabled) { @@ -184,6 +185,31 @@ ApplicationWindow { } } + function showFileDialog(nameFilters,onSelected){ + let dialog = null + if (isQt5) { + dialog = Qt.createQmlObject("import QtQuick.Dialogs 1.3; FileDialog {}", window, "myDynamicSnippet") + } else { + dialog = Qt.createQmlObject("import QtQuick.Dialogs; FileDialog {}", window, "myDynamicSnippet") + } + if (dialog) { + dialog.nameFilters = nameFilters; + dialog.visible = true + dialog.accepted.connect(function () { + let fileUrl = isQt5 ? dialog.fileUrl.toString() : dialog.selectedFile.toString() + let localFilePath = fileUrl.startsWith( + "file:///") ? fileUrl.substring(8) : fileUrl + onSelected(localFilePath) + dialog.destroy() + }) + dialog.rejected.connect(function () { + dialog.destroy() + }) + } else { + console.error("Failed to create FolderDialog object") + } + } + function showFolderDialog(onSelected) { let dialog = null if (isQt5) { diff --git a/qml/NetworkSettingPopup.qml b/qml/NetworkSettingPopup.qml index 97df378..df4121b 100644 --- a/qml/NetworkSettingPopup.qml +++ b/qml/NetworkSettingPopup.qml @@ -9,7 +9,7 @@ Popup { anchors.centerIn: Overlay.overlay modal: true closePolicy: Popup.CloseOnEscap | Popup.NoAutoClose - property int inputHeight: 50 + property int inputHeight: 56 background: Rectangle { radius: 8 } diff --git a/qml/OtaPopup.qml b/qml/OtaPopup.qml index bdf1495..2e1e106 100644 --- a/qml/OtaPopup.qml +++ b/qml/OtaPopup.qml @@ -1,7 +1,6 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 -import QtQuick.Dialogs 1.3 import AntiClipSettings 1.0 Popup { @@ -46,7 +45,9 @@ Popup { Button { enabled: otaFinished text: "选择" - onClicked: fileDialog.open() + onClicked: showFileDialog(["OTA文件 (*.bin)"],(path)=>{ + otaFile.text = path + }) } } @@ -59,7 +60,7 @@ Popup { to: 100 value: 0.0 } - Text { + Label { id: progressText text: "0%" verticalAlignment: Text.AlignVCenter @@ -67,7 +68,7 @@ Popup { } RowLayout { - Text { + Label { id: otaMessage text: "请选择升级文件,点击开始按钮升级模组" wrapMode: Text.Wrap @@ -92,24 +93,6 @@ Popup { onClose() } - FileDialog { - id: fileDialog - nameFilters: ["OTA文件 (*.bin)"] - - onAccepted: { - let fileUrl = isQt5 ? fileDialog.fileUrl.toString() : fileDialog.selectedFile.toString() - var localFilePath = fileUrl.startsWith( - "file:///") ? fileUrl.substring(8) : fileUrl - otaFile.text = localFilePath - } - onVisibleChanged: { - if (!isQt5) { - currentFolder = StandardPaths.standardLocations( - StandardPaths.DesktopLocation)[0] - } - } - } - Connections { target: App function onCurrentDeviceOtaProgressChanged(status, progress, message) {