实现通过cdc进行升级。

This commit is contained in:
luocai 2024-08-05 17:42:27 +08:00
parent 5009528f3a
commit c6554704ac
14 changed files with 193 additions and 7 deletions

View File

@ -2,6 +2,7 @@
#include "AsyncEvent.h" #include "AsyncEvent.h"
#include "BoostLog.h" #include "BoostLog.h"
#include "CategoryLogSinkBackend.h" #include "CategoryLogSinkBackend.h"
#include "CdcUpdater.h"
#include "Configuration.h" #include "Configuration.h"
#include "Database.h" #include "Database.h"
#include "DateTime.h" #include "DateTime.h"
@ -300,6 +301,9 @@ void Application::onNewImageInfo(ModuleCommunication::MessageId messageId, uint3
m_communication->requestEnrolledImage(0, ImageSliceSize); m_communication->requestEnrolledImage(0, ImageSliceSize);
m_palmYImageBuffer.clear(); m_palmYImageBuffer.clear();
m_startUploadTime = system_clock::now(); m_startUploadTime = system_clock::now();
if (messageId == ModuleCommunication::Note) {
emit newStatusTip(Error, "活体未通过照片");
}
} }
void Application::onNewImageSliceData(const std::vector<uint8_t> &data) { void Application::onNewImageSliceData(const std::vector<uint8_t> &data) {
@ -312,6 +316,9 @@ void Application::onNewImageSliceData(const std::vector<uint8_t> &data) {
} else { } else {
auto username = m_palmUsername.toStdString(); auto username = m_palmUsername.toStdString();
auto way = (m_palmImageId == ModuleCommunication::VerifyExtended) ? "verify" : "enroll"; auto way = (m_palmImageId == ModuleCommunication::VerifyExtended) ? "verify" : "enroll";
if (m_palmImageId == ModuleCommunication::Note) {
way = "no_alive";
}
LOG(info) << "request finished, username: " << username LOG(info) << "request finished, username: " << username
<< ", elapsed: " << duration_cast<milliseconds>(system_clock::now() - m_startUploadTime); << ", elapsed: " << duration_cast<milliseconds>(system_clock::now() - m_startUploadTime);
std::ostringstream oss; std::ostringstream oss;
@ -382,3 +389,20 @@ void Application::onVerifyTimeout() {
m_communication->verify(120); m_communication->verify(120);
} }
} }
void Application::startOta(const QString &path) {
LOG(info) << "start ota, ota path: " << path.toStdString();
m_updater = std::make_shared<CdcUpdater>();
connect(m_updater.get(), &CdcUpdater::deviceDiscovered, this, &Application::onCdcDeviceDiscovered);
connect(m_updater.get(), &CdcUpdater::updateFinished, this, &Application::updateFinished);
connect(m_updater.get(), &CdcUpdater::progressChanged, this, &Application::otaProgressChanged);
connect(m_updater.get(), &CdcUpdater::message, this, &Application::otaMessage);
m_communication->startOta();
m_updater->start(path);
}
void Application::onCdcDeviceDiscovered(const QSerialPortInfo &info) {
auto status = m_updater->open(info);
LOG(info) << "open cdc port: " << info.portName().toStdString() << ", status: " << status;
}

View File

@ -13,6 +13,7 @@ class Database;
class VideoPlayer; class VideoPlayer;
class VideoFrameProvider; class VideoFrameProvider;
class QTimer; class QTimer;
class CdcUpdater;
class Application : public QObject { class Application : public QObject {
Q_OBJECT Q_OBJECT
@ -44,6 +45,7 @@ public:
Q_INVOKABLE bool openUVC(const QString &deviceName); Q_INVOKABLE bool openUVC(const QString &deviceName);
Q_INVOKABLE void close(); Q_INVOKABLE void close();
Q_INVOKABLE void closeUVC(); Q_INVOKABLE void closeUVC();
Q_INVOKABLE void startOta(const QString &path);
Q_INVOKABLE void verify(bool captureImage, uint8_t timeout); Q_INVOKABLE void verify(bool captureImage, uint8_t timeout);
Q_INVOKABLE void enroll(const QString &username, bool persistence, uint8_t timeout); Q_INVOKABLE void enroll(const QString &username, bool persistence, uint8_t timeout);
Q_INVOKABLE void enrollExtended(const QString &username, bool persistence, uint8_t timeout); Q_INVOKABLE void enrollExtended(const QString &username, bool persistence, uint8_t timeout);
@ -69,6 +71,9 @@ signals:
void newVideoFrame(); void newVideoFrame();
void newLog(const QString &log); void newLog(const QString &log);
void newStatusTip(TipType type, const QString &tip); void newStatusTip(TipType type, const QString &tip);
void updateFinished();
void otaMessage(const QString &text);
void otaProgressChanged(int32_t progress);
protected: protected:
Application(int &argc, char **argv); Application(int &argc, char **argv);
@ -80,10 +85,13 @@ protected:
void onCommandStarted(ModuleCommunication::MessageId messageId); void onCommandStarted(ModuleCommunication::MessageId messageId);
void onCommandFinished(ModuleCommunication::MessageId messageId, ModuleCommunication::MessageStatus status); void onCommandFinished(ModuleCommunication::MessageId messageId, ModuleCommunication::MessageStatus status);
void onVerifyTimeout(); void onVerifyTimeout();
void onCdcDeviceDiscovered(const QSerialPortInfo &info);
void onUpdateFinished();
private: private:
std::shared_ptr<QGuiApplication> m_app; std::shared_ptr<QGuiApplication> m_app;
std::shared_ptr<ModuleCommunication> m_communication; std::shared_ptr<ModuleCommunication> m_communication;
std::shared_ptr<CdcUpdater> m_updater;
std::shared_ptr<Database> m_database; std::shared_ptr<Database> m_database;
bool m_persistenceMode = true; // 模组持续识别 bool m_persistenceMode = true; // 模组持续识别

View File

@ -29,6 +29,7 @@ qt_add_qml_module(Analyser
qml/ConnectionItem.qml qml/ConnectionItem.qml
qml/OperationItem.qml qml/OperationItem.qml
qml/StatusTip.qml qml/StatusTip.qml
qml/OtaPage.qml
RESOURCES RESOURCES
resources/successfull.svg resources/successfull.svg
resources/warning.svg resources/warning.svg

View File

@ -159,6 +159,11 @@ void ModuleCommunication::setDebugEnabled(bool enabled) {
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize); m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
} }
void ModuleCommunication::startOta() {
auto [frameData, frameSize] = generateFrame(StartOta);
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
}
void ModuleCommunication::requestUniqueId() { void ModuleCommunication::requestUniqueId() {
auto [frameData, frameSize] = generateFrame(GetUniqueID); auto [frameData, frameSize] = generateFrame(GetUniqueID);
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize); m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
@ -346,6 +351,11 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
LOG_CAT(info, GUI) << "模组日志: " << message; LOG_CAT(info, GUI) << "模组日志: " << message;
break; break;
} }
case NoAliveImage: {
LOG(info) << "no alive image";
emit newImageInfo(Note, 600 * 800, nullptr);
break;
}
default: default:
LOG(warning) << "unknown note command: 0x" << (static_cast<int>(noteId) & 0xff) LOG(warning) << "unknown note command: 0x" << (static_cast<int>(noteId) & 0xff)
<< ", data: " << protocolDataFormatString(data, size); << ", data: " << protocolDataFormatString(data, size);

View File

@ -28,6 +28,7 @@ public:
GetImage = 0x1F, // 获取图片数据通过VerifyExtended或EnrollExtended保存的 GetImage = 0x1F, // 获取图片数据通过VerifyExtended或EnrollExtended保存的
DeleteUser = 0x20, DeleteUser = 0x20,
DeleteAll = 0x21, DeleteAll = 0x21,
StartOta = 0x40, // 模组进入boot模式进行ota升级
EnableDebug = 0x82, EnableDebug = 0x82,
GetUniqueID = 0xAC, GetUniqueID = 0xAC,
UploadImageInfo = 0xF6, UploadImageInfo = 0xF6,
@ -41,6 +42,7 @@ public:
PalmState = 0x01, PalmState = 0x01,
UnknownError = 0x02, UnknownError = 0x02,
DebugInfo = 0x55, DebugInfo = 0x55,
NoAliveImage = 0x56,
}; };
enum MessageStatus : uint8_t { enum MessageStatus : uint8_t {
Success = 0, Success = 0,
@ -161,6 +163,7 @@ public:
void uploadImageData(uint32_t offset, const uint8_t *data, uint32_t size); void uploadImageData(uint32_t offset, const uint8_t *data, uint32_t size);
Q_INVOKABLE void requestCurrentStatus(); Q_INVOKABLE void requestCurrentStatus();
Q_INVOKABLE void setDebugEnabled(bool enabled); Q_INVOKABLE void setDebugEnabled(bool enabled);
void startOta();
MessageId currentMessageId() const; MessageId currentMessageId() const;
static std::string protocolDataFormatString(const uint8_t *data, int size); static std::string protocolDataFormatString(const uint8_t *data, int size);

View File

@ -70,7 +70,6 @@ void VideoPlayer::run() {
if (status == 0) { if (status == 0) {
QImage image; QImage image;
image.loadFromData(packet->data, packet->size); image.loadFromData(packet->data, packet->size);
image.mirror(false, true);
if (!image.isNull() && m_callback) m_callback(image); if (!image.isNull() && m_callback) m_callback(image);
} else { } else {
char message[256] = {0}; char message[256] = {0};

View File

@ -160,6 +160,10 @@ ColumnLayout {
text: "ID查询" text: "ID查询"
onClicked: App.module.requestUniqueId() onClicked: App.module.requestUniqueId()
} }
Button {
text: "OTA升级"
onClicked: loader.active = true
}
Row { Row {
Text { Text {
text: qsTr("日志") text: qsTr("日志")
@ -171,4 +175,18 @@ ColumnLayout {
} }
} }
} }
Loader {
id: loader
source: "OtaPage.qml"
active: false
onLoaded: {
if (loader.item && loader.item.open) {
loader.item.open();
loader.item.onClose = ()=>{
loader.active= false
}
}
}
}
} }

115
Analyser/qml/OtaPage.qml Normal file
View File

@ -0,0 +1,115 @@
import QtCore
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Dialogs
import Analyser
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.startOta(otaFile.text)
enabled = false
}
}
}
}
onClosed: {
if (onClose)
onClose()
}
FileDialog {
id: fileDialog
nameFilters: ["OTA文件 (*.Pkg)"]
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}%`
}
}
}

View File

@ -5,7 +5,7 @@ import Analyser
Window { Window {
width: 1120 width: 1120
height: 640 height: 680
visible: true visible: true
title: qsTr(Qt.application.name + " " + Qt.application.version) title: qsTr(Qt.application.name + " " + Qt.application.version)

View File

@ -6,7 +6,6 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets SerialPort)
set(PROJECT_SOURCES OtaUpdate.rc set(PROJECT_SOURCES OtaUpdate.rc
main.cpp main.cpp
CdcUpdater.h CdcUpdater.cpp
Widget.cpp Widget.cpp
Widget.h Widget.h
) )
@ -18,7 +17,6 @@ qt_add_executable(SmartLockerUpdater
target_link_libraries(SmartLockerUpdater target_link_libraries(SmartLockerUpdater
PRIVATE Peripheral PRIVATE Peripheral
PRIVATE Encrypt
PRIVATE Qt${QT_VERSION_MAJOR}::Widgets PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
PRIVATE Qt${QT_VERSION_MAJOR}::SerialPort PRIVATE Qt${QT_VERSION_MAJOR}::SerialPort
) )

View File

@ -1,5 +1,11 @@
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS SerialPort)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS SerialPort)
set(CMAKE_AUTOMOC ON)
add_library(Peripheral add_library(Peripheral
DeviceDiscovery.h DeviceDiscovery.cpp DeviceDiscovery.h DeviceDiscovery.cpp
CdcUpdater.h CdcUpdater.cpp
) )
target_include_directories(Peripheral target_include_directories(Peripheral
@ -8,8 +14,10 @@ target_include_directories(Peripheral
target_link_libraries(Peripheral target_link_libraries(Peripheral
PUBLIC Universal PUBLIC Universal
PRIVATE Encrypt
PRIVATE Mfreadwrite PRIVATE Mfreadwrite
PRIVATE Mf PRIVATE Mf
PRIVATE mfplat PRIVATE mfplat
PRIVATE mfuuid PRIVATE mfuuid
PRIVATE Qt${QT_VERSION_MAJOR}::SerialPort
) )

View File

@ -106,7 +106,8 @@ void CdcUpdater::transferBin() {
auto readSize = m_ifs->gcount(); auto readSize = m_ifs->gcount();
if (readSize > 0) { if (readSize > 0) {
m_progress += (99 - m_progressBeforeTranster) * static_cast<float>(m_packetIndex) / m_totalPackageSize; m_progress = m_progressBeforeTranster +
(99 - m_progressBeforeTranster) * static_cast<float>(m_packetIndex) / m_totalPackageSize;
if (m_progress > 99) m_progress = 99; if (m_progress > 99) m_progress = 99;
emit progressChanged(m_progress); emit progressChanged(m_progress);
@ -138,7 +139,7 @@ void CdcUpdater::onReadyRead() {
if (command == EnterUpgradeReply) { if (command == EnterUpgradeReply) {
write(GetVersion); write(GetVersion);
emit progressChanged(++m_progress); emit progressChanged(++m_progress);
message("获取模组OTA版本......"); emit message("获取模组OTA版本......");
} else if (command == GetVersionReply) { } else if (command == GetVersionReply) {
LOG(info) << "device ota version: 0x" << std::hex << (static_cast<int>(data[4]) & 0xff); LOG(info) << "device ota version: 0x" << std::hex << (static_cast<int>(data[4]) & 0xff);
int fileSize = std::filesystem::file_size(m_path); int fileSize = std::filesystem::file_size(m_path);
@ -150,7 +151,7 @@ void CdcUpdater::onReadyRead() {
content[2] = 0x14; content[2] = 0x14;
write(StartUpgrade, content.data(), content.size()); write(StartUpgrade, content.data(), content.size());
emit progressChanged(++m_progress); emit progressChanged(++m_progress);
message("模组进入升级状态......"); emit message("模组进入升级状态......");
} else if (command == StartUpgradeReply) { } else if (command == StartUpgradeReply) {
std::ifstream ifs(m_path, std::ifstream::binary); std::ifstream ifs(m_path, std::ifstream::binary);
char buffer[4096] = {0}; char buffer[4096] = {0};

View File

@ -56,6 +56,7 @@ HOST_TOOLS := /opt/Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1/bin
上述步骤执行完毕之后,即可编译打包: 上述步骤执行完毕之后,即可编译打包:
```shell ```shell
./boot-rebuild.sh # 编译boot
./rebuild-app.sh y L015 V200 R002 # 编译烧录固件 ./rebuild-app.sh y L015 V200 R002 # 编译烧录固件
./rebuild-app-ota.sh y L015 V200 R002 14 # 编译OTA固件11为OTA版本号 ./rebuild-app-ota.sh y L015 V200 R002 14 # 编译OTA固件11为OTA版本号
600X800 600X800