SmartLockerTools/OtaUpdate/Widget.cpp
2024-10-02 03:01:37 +08:00

158 lines
5.0 KiB
C++

#include "Widget.h"
#include "BoostLog.h"
#include "CdcUpdater.h"
#include "DeviceDiscovery.h"
#include "StringUtility.h"
#include <QDropEvent>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QMimeData>
#include <QProgressBar>
#include <QPushButton>
#include <QSerialPortInfo>
#include <QTimer>
#include <QVBoxLayout>
#include <filesystem>
Widget::Widget(QWidget *parent) : QWidget(parent) {
m_fileEditor = new QLineEdit();
m_fileEditor->setPlaceholderText("请选择升级文件或将文件拖入工具中");
m_selectButton = new QPushButton("选择");
connect(m_selectButton, &QPushButton::clicked, this, &Widget::onSelectButtonClicked);
auto fileLayout = new QHBoxLayout();
fileLayout->addWidget(m_fileEditor);
fileLayout->addWidget(m_selectButton);
m_startButton = new QPushButton(this);
m_startButton->setText("开始");
connect(m_startButton, &QPushButton::clicked, this, &Widget::start);
m_progressBar = new QProgressBar();
m_progressBar->setRange(0, 100);
m_progressBar->setValue(0);
m_messageLabel = new QLabel();
m_messageLabel->setText("选择升级文件,点击开始按钮升级模组");
auto statusLayout = new QVBoxLayout();
statusLayout->addWidget(m_progressBar);
statusLayout->addWidget(m_messageLabel);
auto controlLayout = new QHBoxLayout();
controlLayout->addLayout(statusLayout);
controlLayout->addWidget(m_startButton);
auto layout = new QVBoxLayout(this);
layout->addLayout(fileLayout);
layout->addLayout(controlLayout);
setAcceptDrops(true);
}
Widget::~Widget() {
}
void Widget::start() {
m_progressBar->setValue(0);
auto filePath = m_fileEditor->text();
#ifdef Q_OS_WIN
auto path = Amass::StringUtility::UTF8ToGBK(filePath.toStdString());
#else
auto path = filePath.toStdString();
#endif
if (!std::filesystem::exists(path)) {
QMessageBox::warning(this, "升级", "升级文件不存在!");
return;
}
auto device = CdcUpdater::searchDevice();
if (device) {
LOG(info) << "device already in ota mode.";
} else {
auto discovery = std::make_shared<DeviceDiscovery>();
std::error_code error;
setMessage("尝试发现设备......");
auto device = discovery->find(DeviceDiscovery::DeviceName, error);
if (!device) {
QMessageBox::warning(this, "升级", "未检测到模组,请尝试重新插入模组!");
return;
}
setMessage("发现设备成功,进入BOOT模式......");
discovery->enterOtaMode(device, error);
}
m_updater = std::make_shared<CdcUpdater>();
connect(m_updater.get(), &CdcUpdater::deviceDiscovered, this, &Widget::onCdcDeviceDiscovered);
connect(m_updater.get(), &CdcUpdater::updateFinished, this, &Widget::onUpdateFinished);
connect(m_updater.get(), &CdcUpdater::progressChanged, this, &Widget::setProgress);
connect(m_updater.get(), &CdcUpdater::message, this, &Widget::setMessage);
m_updater->start(filePath, device ? *device : QSerialPortInfo());
setControlsEnabled(false);
}
void Widget::onCdcDeviceDiscovered(const QSerialPortInfo &info) {
auto status = m_updater->open(info);
LOG(info) << "open cdc port: " << info.portName().toStdString() << ", status: " << status;
if (!status) {
QTimer::singleShot(0, this, [this]() { m_updater->startSearchDevice(); });
}
}
void Widget::onSelectButtonClicked() {
auto fileName = QFileDialog::getOpenFileName(this, "升级文件", "", tr("OTA文件 (*.Pkg)"));
m_fileEditor->setText(fileName);
}
void Widget::onUpdateFinished() {
QMessageBox::information(this, "升级", "升级成功!");
setControlsEnabled(true);
}
static QString dragFilePath(const QMimeData *mimeData) {
QString ret;
if (mimeData->hasUrls()) {
auto urls = mimeData->urls();
for (auto &url : urls) {
auto path = url.toLocalFile();
if (path.isEmpty()) continue;
ret = path;
break;
}
}
return ret;
}
void Widget::dragEnterEvent(QDragEnterEvent *event) {
auto path = dragFilePath(event->mimeData());
if (path.endsWith(".Pkg", Qt::CaseInsensitive)) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
void Widget::dropEvent(QDropEvent *event) {
auto path = dragFilePath(event->mimeData());
if (path.endsWith(".Pkg", Qt::CaseInsensitive)) {
m_fileEditor->setText(path);
}
}
void Widget::setControlsEnabled(bool enabled) {
m_startButton->setEnabled(enabled);
m_selectButton->setEnabled(enabled);
m_fileEditor->setEnabled(enabled);
}
void Widget::setProgress(int32_t progress) {
m_progressBar->setValue(progress);
}
void Widget::setMessage(const QString &message) {
m_messageLabel->setText(message);
}