diff --git a/Application.cpp b/Application.cpp index dfa776f..7226bbf 100644 --- a/Application.cpp +++ b/Application.cpp @@ -159,6 +159,12 @@ void Application::connectToDevice(const QString &address) { }); } +void Application::upgradeDevice(const QString &file) { + if (m_device != nullptr) { + m_device->requestOta(file); + } +} + void Application::onDeviceOpenDoorArea(DeviceConnection::AreaWay way, const QList &points) { setCurrentOpenDoorAreaWay(way); setCurrentOpenDoorAreaPoints(points); diff --git a/Application.h b/Application.h index 0069ab6..e642a93 100644 --- a/Application.h +++ b/Application.h @@ -64,6 +64,7 @@ public: Q_INVOKABLE void updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway); Q_INVOKABLE void connectToDevice(const QString &address); + Q_INVOKABLE void upgradeDevice(const QString &file); int exec(); static Application *create(QQmlEngine *qmlEngine, QJSEngine *jsEngine); diff --git a/CMakeLists.txt b/CMakeLists.txt index 83eb819..a53cf6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.16) -project(AntiClipSettings VERSION 0.1 LANGUAGES CXX) +project(AntiClipSettings VERSION 0.1 LANGUAGES C CXX) set(APPLICATION_NAME "T009上位机") set(CMAKE_CXX_STANDARD 17) @@ -49,6 +49,7 @@ qt_add_qml_module(AntiClipSettings Main.qml DeviceView.qml NetworkSettingPopup.qml + OtaPopup.qml ) # Qt for iOS sets MACOSX_BUNDLE_GUI_IDENTIFIER automatically since Qt 6.1. @@ -63,6 +64,7 @@ set_target_properties(AntiClipSettings PROPERTIES ) add_subdirectory(${Projects_ROOT}/Kylin/Universal Universal) +add_subdirectory(${Projects_ROOT}/Kylin/Encrypt Encrypt) target_include_directories(AntiClipSettings PRIVATE ${FFmpeg_INCLUDE_DIR} @@ -84,6 +86,7 @@ target_link_libraries(AntiClipSettings PRIVATE avdevice PRIVATE avformat PRIVATE Universal + PRIVATE Encrypt ) include(GNUInstallDirs) diff --git a/DeviceConnection.cpp b/DeviceConnection.cpp index ab3ef44..4853a54 100644 --- a/DeviceConnection.cpp +++ b/DeviceConnection.cpp @@ -1,10 +1,14 @@ #include "DeviceConnection.h" #include "BoostLog.h" +#include "StringUtility.h" #include #include #include #include #include +#include +#include +#include DeviceConnection::DeviceConnection(QObject *parent) : QObject{parent} { } @@ -231,6 +235,44 @@ void DeviceConnection::updateNetworkInfomation(bool dhcp, const QString &ip, con m_requests.push(task); } +void DeviceConnection::requestOta(const QString &file) { + LOG(info) << file.toStdString(); + + auto task = [this, file]() { + std::ifstream ifs(Amass::StringUtility::UTF8ToGBK(file.toStdString()), std::ifstream::binary); + m_uploadBuffer = std::vector((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + unsigned char md5[16]; + mbedtls_md5_context context; + mbedtls_md5_init(&context); + mbedtls_md5_starts(&context); + mbedtls_md5_update(&context, m_uploadBuffer.data(), m_uploadBuffer.size()); + mbedtls_md5_finish(&context, md5); + mbedtls_md5_free(&context); + std::stringstream oss; + oss << std::hex << std::setfill('0'); + for (int i = 0; i < 16; i++) { + oss << std::setw(2) << static_cast(md5[i]); + } + + boost::json::object request; + request["func"] = "a22devicefirmware_setdata"; + request["deviceid"] = "0"; + boost::json::object data; + data["target_linux04_firmware"] = "RD_T009_V21R003B001"; + data["datasize"] = std::filesystem::file_size(file.toStdString()); + data["md5"] = oss.str(); + request["data"] = std::move(data); + auto text = boost::json::serialize(request); + m_commandSocket->write(text.data(), text.size()); + LOG(info) << "requestOta: " << text; + }; + if (m_requests.empty()) { + task(); + } + m_requests.push(task); +} + void DeviceConnection::handleCommand(const std::string_view &replyText) { boost::system::error_code error; auto replyValue = boost::json::parse(replyText, error); diff --git a/DeviceConnection.h b/DeviceConnection.h index c985953..1cb89ee 100644 --- a/DeviceConnection.h +++ b/DeviceConnection.h @@ -41,6 +41,8 @@ public: void requestNetworkInfomation(); void updateNetworkInfomation(bool dhcp, const QString &ip, const QString &netmask, const QString &gateway); + void requestOta(const QString &file); + signals: void currentOpenDoorAreaChanged(AreaWay way, const QList &points); void currentShieldedAreaChanged(bool enabled, const QList &points); @@ -62,6 +64,7 @@ private: QByteArray m_commandBuffer; QByteArray m_h264Buffer; + std::vector m_uploadBuffer; H264FrameCallback m_frameCallback; std::queue> m_requests; }; diff --git a/Main.qml b/Main.qml index f6ff258..c102ee9 100644 --- a/Main.qml +++ b/Main.qml @@ -103,6 +103,10 @@ ApplicationWindow { height: 240 } + OtaPopup { + id: otaPopup + } + footer: RowLayout { width: parent.width Item {} @@ -112,6 +116,7 @@ ApplicationWindow { Item {} Button { text: "升级" + onClicked: otaPopup.open() } Item {} spacing: (parent.width - (2 * 100)) / 3 diff --git a/OtaPopup.qml b/OtaPopup.qml new file mode 100644 index 0000000..37486e3 --- /dev/null +++ b/OtaPopup.qml @@ -0,0 +1,113 @@ +import QtCore +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts +import QtQuick.Dialogs +import AntiClipSettings + +Popup { + id: root + parent: Overlay.overlay + anchors.centerIn: Overlay.overlay + width: 500 + height: 200 + modal: true + focus: true + closePolicy: Popup.CloseOnEscape + property var onClose + + ColumnLayout { + anchors.fill: parent + anchors.margins: 10 + spacing: 10 + + RowLayout { + Layout.alignment: Qt.AlignRight + Button { + text: "关闭" + onClicked: root.close() + } + } + + RowLayout { + spacing: 10 + TextField { + id: otaFile + Layout.fillWidth: true + placeholderText: "请选择升级文件或将文件拖入工具中" + } + Button { + text: "选择" + onClicked: fileDialog.open() + } + } + + RowLayout { + spacing: 10 + ProgressBar { + id: progressBar + Layout.fillWidth: true + from: 0 + to: 100 + value: 0.0 + } + Text { + id: progressText + text: "0%" + verticalAlignment: Text.AlignVCenter + } + } + + RowLayout { + Text { + id: otaMessage + text: "请选择升级文件,点击开始按钮升级模组" + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + Layout.fillWidth: true + } + Button { + text: "开始" + Layout.alignment: Qt.AlignRight + onClicked: { + otaMessage.color = "black" + App.upgradeDevice(otaFile.text) + } + } + } + } + + onClosed: { + if (onClose) + onClose() + } + + FileDialog { + id: fileDialog + nameFilters: ["OTA文件 (*.bin)"] + currentFolder: StandardPaths.standardLocations( + StandardPaths.DesktopLocation)[0] + onAccepted: { + var fileUrl = fileDialog.selectedFile.toString() + var localFilePath = fileUrl.startsWith( + "file:///") ? fileUrl.substring(8) : fileUrl + otaFile.text = localFilePath + } + } + + // Connections { + // target: App + // function onUpdateFinished() { + // otaMessage.text = "OTA升级完成" + // otaMessage.color = "green" + // } + // function onOtaMessage(message) { + // otaMessage.text = message + // } + // function onOtaProgressChanged(progress) { + // progressBar.value = progress + // progressText.text = `${progress}%` + // } + // } +}