From 5009528f3a61e955cf7ddcacf6f79df9881f2780 Mon Sep 17 00:00:00 2001 From: luocai Date: Wed, 31 Jul 2024 16:08:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E8=AF=86=E5=88=AB=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Analyser/Application.cpp | 65 +++++++++++++++++++------------- Analyser/Application.h | 12 +++--- Analyser/ModuleCommunication.cpp | 61 ++++++++++++++++++++++++------ Analyser/ModuleCommunication.h | 26 +++++++++---- Analyser/qml/OperationItem.qml | 18 ++++++++- 5 files changed, 132 insertions(+), 50 deletions(-) diff --git a/Analyser/Application.cpp b/Analyser/Application.cpp index cbc1127..59f9a11 100644 --- a/Analyser/Application.cpp +++ b/Analyser/Application.cpp @@ -52,6 +52,7 @@ Application::Application(int &argc, char **argv) : m_app(std::make_sharedcurrentMessageId() != ModuleCommunication::Idle) { m_communication->reset(); } - m_communication->verify(timeout); + if (captureImage) { + m_communication->verifyExtended(captureImage, timeout); + } else { + m_communication->verify(timeout); + } + m_verifyExtendedMode = captureImage; } void Application::enroll(const QString &username, bool persistence, uint8_t timeout) { @@ -172,7 +177,7 @@ void Application::enroll(const QString &username, bool persistence, uint8_t time m_communication->reset(); } m_communication->enroll(username.toStdString(), persistence, timeout); - m_enrollUsername = username; + m_palmUsername = username; } void Application::deleteUser(uint16_t userid) { @@ -194,7 +199,7 @@ void Application::enrollExtended(const QString &username, bool persistence, uint m_communication->reset(); } m_communication->enrollExtended(username.toStdString(), persistence, timeout); - m_enrollUsername = username; + m_palmUsername = username; } void Application::uploadImage() { @@ -269,7 +274,8 @@ bool Application::isVerifying() const { return false; } return (m_persistenceMode && m_persistenceModeStarted) || - (m_communication->currentMessageId() == ModuleCommunication::Verify); + (m_communication->currentMessageId() == ModuleCommunication::Verify) || + (m_communication->currentMessageId() == ModuleCommunication::VerifyExtended); } void Application::onNewPalmFeature(const PalmFeature &feature) { @@ -287,36 +293,37 @@ void Application::onErrorOccurred(const QString &error) { QTimer::singleShot(0, this, [this]() { close(); }); } -void Application::onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5) { +void Application::onNewImageInfo(ModuleCommunication::MessageId messageId, uint32_t size, const uint8_t *md5) { using namespace std::chrono; - m_enrolledImageSize = size; + m_palmImageId = messageId; + m_palmImageSize = size; m_communication->requestEnrolledImage(0, ImageSliceSize); - m_enrollYImageBuffer.clear(); + m_palmYImageBuffer.clear(); m_startUploadTime = system_clock::now(); } void Application::onNewImageSliceData(const std::vector &data) { using namespace std::chrono; - // LOG(info) << "onNewImageSliceData:" << data.size() << ", already received: " << m_enrollYImageBuffer.size() - // << ", total size: " << m_enrolledImageSize; - m_enrollYImageBuffer.append(reinterpret_cast(data.data()), data.size()); - if (m_enrollYImageBuffer.size() < m_enrolledImageSize) { - m_communication->requestEnrolledImage(m_enrollYImageBuffer.size(), ImageSliceSize); + // LOG(info) << "onNewImageSliceData:" << data.size() << ", already received: " << m_palmYImageBuffer.size() + // << ", total size: " << m_palmImageSize; + m_palmYImageBuffer.append(reinterpret_cast(data.data()), data.size()); + if (m_palmYImageBuffer.size() < m_palmImageSize) { + m_communication->requestEnrolledImage(m_palmYImageBuffer.size(), ImageSliceSize); } else { - auto username = m_enrollUsername.toStdString(); + auto username = m_palmUsername.toStdString(); + auto way = (m_palmImageId == ModuleCommunication::VerifyExtended) ? "verify" : "enroll"; LOG(info) << "request finished, username: " << username << ", elapsed: " << duration_cast(system_clock::now() - m_startUploadTime); std::ostringstream oss; - oss << YuvPath << "/" << username << "_" << DateTime::toString(std::chrono::system_clock::now(), "%Y%m%d%H%M%S") - << ".yuv"; + oss << YuvPath << "/" << username << "_" << way << "_" + << DateTime::toString(std::chrono::system_clock::now(), "%Y%m%d%H%M%S") << ".yuv"; std::ofstream ofs(Amass::StringUtility::UTF8ToGBK(oss.str()), std::ofstream::binary); - ofs.write(m_enrollYImageBuffer.data(), m_enrollYImageBuffer.size()); + ofs.write(m_palmYImageBuffer.data(), m_palmYImageBuffer.size()); - QImage image(reinterpret_cast(m_enrollYImageBuffer.data()), 600, 800, - QImage::Format_Grayscale8); + QImage image(reinterpret_cast(m_palmYImageBuffer.data()), 600, 800, QImage::Format_Grayscale8); oss.str(""); - oss << JpgPath << "/" << username << "_" << DateTime::toString(std::chrono::system_clock::now(), "%Y%m%d%H%M%S") - << ".jpg"; + oss << JpgPath << "/" << username << "_" << way << "_" + << DateTime::toString(std::chrono::system_clock::now(), "%Y%m%d%H%M%S") << ".jpg"; image.save(QString::fromStdString(oss.str()), "jpg", 100); } } @@ -346,14 +353,16 @@ void Application::onCommandFinished(ModuleCommunication::MessageId messageId, } } - if (messageId == ModuleCommunication::Verify && m_persistenceMode) { // 持续识别逻辑 + if (((messageId == ModuleCommunication::Verify) || (messageId == ModuleCommunication::VerifyExtended)) && + m_persistenceMode) { // 持续识别逻辑 m_persistenceModeStarted = true; } else if (messageId == ModuleCommunication::Reset) { m_persistenceModeStarted = false; m_verifyTimer->stop(); } - if (m_persistenceMode && m_persistenceModeStarted && messageId == ModuleCommunication::Verify && + if (m_persistenceMode && m_persistenceModeStarted && + ((messageId == ModuleCommunication::Verify) || (messageId == ModuleCommunication::VerifyExtended)) && ((status == ModuleCommunication::Success) || (status == ModuleCommunication::Failed4UnknownUser) || (status == ModuleCommunication::Failed4Timeout) || (status == ModuleCommunication::Failed4UnknownReason))) { m_verifyTimer->start(m_persistenceVerifyInterval * 1000); @@ -367,5 +376,9 @@ void Application::onCommandFinished(ModuleCommunication::MessageId messageId, } void Application::onVerifyTimeout() { - m_communication->verify(120); + if (m_verifyExtendedMode) { + m_communication->verifyExtended(m_verifyExtendedMode, 120); + } else { + m_communication->verify(120); + } } diff --git a/Analyser/Application.h b/Analyser/Application.h index 156e737..f99d9a1 100644 --- a/Analyser/Application.h +++ b/Analyser/Application.h @@ -44,7 +44,7 @@ public: Q_INVOKABLE bool openUVC(const QString &deviceName); Q_INVOKABLE void close(); Q_INVOKABLE void closeUVC(); - Q_INVOKABLE void verify(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 enrollExtended(const QString &username, bool persistence, uint8_t timeout); Q_INVOKABLE void deleteUser(uint16_t userid); @@ -75,7 +75,7 @@ protected: void onNewVerifyResult(uint16_t userid, const QString &username, uint16_t elapsed); void onNewPalmFeature(const PalmFeature &feature); void onErrorOccurred(const QString &error); - void onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5); + void onNewImageInfo(ModuleCommunication::MessageId messageId, uint32_t size, const uint8_t *md5); void onNewImageSliceData(const std::vector &data); void onCommandStarted(ModuleCommunication::MessageId messageId); void onCommandFinished(ModuleCommunication::MessageId messageId, ModuleCommunication::MessageStatus status); @@ -87,13 +87,15 @@ private: std::shared_ptr m_database; bool m_persistenceMode = true; // 模组持续识别 + bool m_verifyExtendedMode = false; bool m_persistenceModeStarted = false; int m_persistenceVerifyInterval = 1; QTimer *m_verifyTimer = nullptr; - uint32_t m_enrolledImageSize = 0; - QString m_enrollUsername; - QByteArray m_enrollYImageBuffer; + ModuleCommunication::MessageId m_palmImageId; // 通过哪个指令获取的图片 + uint32_t m_palmImageSize = 0; + QString m_palmUsername; + QByteArray m_palmYImageBuffer; std::chrono::system_clock::time_point m_startUploadTime; uint32_t m_uploadImageSendedSize; diff --git a/Analyser/ModuleCommunication.cpp b/Analyser/ModuleCommunication.cpp index 98ad125..6f22ed0 100644 --- a/Analyser/ModuleCommunication.cpp +++ b/Analyser/ModuleCommunication.cpp @@ -34,7 +34,7 @@ bool ModuleCommunication::open(const QString &portName, int baudRate) { } void ModuleCommunication::verify(uint8_t timeout) { - VerifyInfo data = {0}; + VerifyRequest data = {0}; data.timeout = timeout; auto [frameData, frameSize] = generateFrame(Verify, reinterpret_cast(&data), sizeof(data)); @@ -45,6 +45,18 @@ void ModuleCommunication::verify(uint8_t timeout) { LOG_CAT(info, GUI) << Separator; } +void ModuleCommunication::verifyExtended(bool captureImage, uint8_t timeout) { + VerifyRequest data = {0}; + data.timeout = timeout; + data.save_image = captureImage ? 0x01 : 0x00; + auto [frameData, frameSize] = generateFrame(VerifyExtended, reinterpret_cast(&data), sizeof(data)); + m_serialPort->write(reinterpret_cast(frameData), frameSize); + setCurrentMessageIdStatus(VerifyExtended); + + LOG_CAT(info, GUI) << "发送扩展识别指令: " << protocolDataFormatString(frameData, frameSize); + LOG_CAT(info, GUI) << Separator; +} + void ModuleCommunication::reset() { auto [frameData, frameSize] = generateFrame(Reset); m_serialPort->write(reinterpret_cast(frameData), frameSize); @@ -102,8 +114,7 @@ void ModuleCommunication::requestEnrolledImage(uint32_t offset, uint32_t size) { ImageSliceRequest request; request.offset = htonl(offset); request.size = htonl(size); - auto [data, frameSize] = - generateFrame(GetEnrolledImage, reinterpret_cast(&request), sizeof(request)); + auto [data, frameSize] = generateFrame(GetImage, reinterpret_cast(&request), sizeof(request)); m_serialPort->write(reinterpret_cast(data), frameSize); // 打印太耗时 // LOG_CAT(info, GUI) << "发送获取图片指令: " << protocolDataFormatString(data, frameSize); @@ -142,6 +153,12 @@ void ModuleCommunication::requestCurrentStatus() { LOG_CAT(info, GUI) << Separator; } +void ModuleCommunication::setDebugEnabled(bool enabled) { + uint8_t data = enabled ? 0x01 : 0x00; + auto [frameData, frameSize] = generateFrame(EnableDebug, &data, sizeof(data)); + m_serialPort->write(reinterpret_cast(frameData), frameSize); +} + void ModuleCommunication::requestUniqueId() { auto [frameData, frameSize] = generateFrame(GetUniqueID); m_serialPort->write(reinterpret_cast(frameData), frameSize); @@ -168,10 +185,11 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { LOG_CAT(info, GUI) << Separator; break; } - case Verify: { + case Verify: + case VerifyExtended: { LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size); if (result == Success) { - auto info = reinterpret_cast(data + 7); + auto info = reinterpret_cast(data + 7); uint16_t userid = ntohs(info->userid); uint16_t elapsed = ntohs(info->elapsed); LOG_CAT(info, GUI) << "用户ID: " << userid @@ -183,18 +201,26 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { } else if (result == Rejected) { LOG_CAT(info, GUI) << "模组拒绝该命令。"; } else if (result == Failed4UnknownUser) { - auto info = reinterpret_cast(data + 7); + auto info = reinterpret_cast(data + 7); uint16_t elapsed = ntohs(info->elapsed); emit newVerifyResult(InvalidUserId, "", elapsed); LOG_CAT(info, GUI) << "未录入用户, 耗时: " << elapsed << "ms"; } else if (result == Failed4UnknownReason) { - auto info = reinterpret_cast(data + 7); + auto info = reinterpret_cast(data + 7); uint16_t elapsed = ntohs(info->elapsed); emit newVerifyResult(InvalidUserId, "", elapsed); LOG_CAT(info, GUI) << "未知错误, 耗时: " << elapsed << "ms"; } else { LOG_CAT(info, GUI) << "未知错误(" << static_cast(result) << ")。"; } + if (replyId == VerifyExtended) { + auto info = reinterpret_cast(data + 7); + uint16_t width = ntohs(info->image_width); + uint16_t height = ntohs(info->image_height); + if ((width > 0) && (height > 0)) { + emit newImageInfo(static_cast(replyId), width * height, info->md5); + } + } LOG_CAT(info, GUI) << Separator; break; } @@ -205,6 +231,8 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { LOG_CAT(info, GUI) << "注册成功,用户ID: " << ntohs(info->userid); } else if (result == Failed4Timeout) { LOG_CAT(info, GUI) << "识别超时。"; + } else { + LOG_CAT(info, GUI) << "未知错误(" << static_cast(result) << ")。"; } LOG_CAT(info, GUI) << Separator; break; @@ -217,19 +245,21 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { uint16_t height = ntohs(info->image_height); LOG_CAT(info, GUI) << "注册成功,用户ID: " << ntohs(info->userid) << ", 图片大小: " << width << "x" << height; - emit newEnrolledImageInfo(width * height, info->md5); + emit newImageInfo(static_cast(replyId), width * height, info->md5); + } else { + LOG_CAT(info, GUI) << "未知错误(" << static_cast(result) << ")。"; } LOG_CAT(info, GUI) << Separator; break; } - case GetEnrolledImage: { - // LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size); + case GetImage: { if (result == Success) { auto info = reinterpret_cast(data + 7); uint32_t sliceSize = ntohl(info->size); emit newImageSliceData(std::vector(info->data, info->data + sliceSize)); + } else { + LOG(info) << "GetImage failed, status: " << static_cast(result); } - // LOG_CAT(info, GUI) << Separator; break; } case DeleteUser: { @@ -279,6 +309,10 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { LOG_CAT(info, GUI) << Separator; break; } + case EnableDebug: { + LOG(info) << "set moudle debug mode: " << (result == Success); + break; + } default: LOG(warning) << "unknown reply command: 0x" << (static_cast(replyId) & 0xff) << ", data: " << protocolDataFormatString(data, size); @@ -307,6 +341,11 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { LOG_CAT(info, GUI) << Separator; break; } + case DebugInfo: { + auto message = reinterpret_cast(data + 6); + LOG_CAT(info, GUI) << "模组日志: " << message; + break; + } default: LOG(warning) << "unknown note command: 0x" << (static_cast(noteId) & 0xff) << ", data: " << protocolDataFormatString(data, size); diff --git a/Analyser/ModuleCommunication.h b/Analyser/ModuleCommunication.h index dc90e08..c1db403 100644 --- a/Analyser/ModuleCommunication.h +++ b/Analyser/ModuleCommunication.h @@ -22,11 +22,13 @@ public: Reset = 0x10, GetCurrentStatus = 0x11, Verify = 0x12, + VerifyExtended = 0x16, EnrollSingle = 0x1D, EnrollExtended = 0x1E, - GetEnrolledImage = 0x1F, + GetImage = 0x1F, // 获取图片数据,通过VerifyExtended或EnrollExtended保存的 DeleteUser = 0x20, DeleteAll = 0x21, + EnableDebug = 0x82, GetUniqueID = 0xAC, UploadImageInfo = 0xF6, UploadImageData = 0xF7, @@ -38,6 +40,7 @@ public: Ready = 0x00, PalmState = 0x01, UnknownError = 0x02, + DebugInfo = 0x55, }; enum MessageStatus : uint8_t { Success = 0, @@ -60,9 +63,9 @@ public: }; #pragma pack(1) - struct VerifyInfo { - uint8_t powerDownRightAway; // power down right away after verifying - uint8_t timeout; // timeout, unit second, default 10s + struct VerifyRequest { + uint8_t save_image; + uint8_t timeout; // timeout, unit second, default 10s }; struct VerifyNoteInfo { int16_t state; // corresponding to PALM_STATE_* @@ -106,12 +109,19 @@ public: uint8_t data[0]; }; - struct VerifyDataReply { + struct VerifyReply { uint16_t userid; uint8_t username[UsernameSize]; // 32Bytes uint16_t elapsed; // 此时识别耗时时间 }; + struct VerifyExtendReply : public VerifyReply { + uint16_t image_width; + uint16_t image_height; + uint8_t image_format; // 0: 只有Y分量,灰度图 + uint8_t md5[16]; + }; + struct UploadImageInformation { uint8_t operation; // 0:图片录入掌静脉 uint8_t format; // 0: 灰度图(纯Y分量) @@ -136,7 +146,8 @@ public: #pragma pack() explicit ModuleCommunication(QObject *parent = nullptr); bool open(const QString &portName, int baudRate); - Q_INVOKABLE void verify(uint8_t timeout); + void verify(uint8_t timeout); + void verifyExtended(bool captureImage, uint8_t timeout); Q_INVOKABLE void reset(); void enroll(const std::string &username, bool persistence, uint8_t timeout); @@ -149,6 +160,7 @@ public: void uploadImageInfo(const UploadImageInformation &info); void uploadImageData(uint32_t offset, const uint8_t *data, uint32_t size); Q_INVOKABLE void requestCurrentStatus(); + Q_INVOKABLE void setDebugEnabled(bool enabled); MessageId currentMessageId() const; static std::string protocolDataFormatString(const uint8_t *data, int size); @@ -161,7 +173,7 @@ signals: */ void newVerifyResult(uint16_t userid, const QString &username, uint16_t elapsed); void newPalmFeature(const PalmFeature &feature); - void newEnrolledImageInfo(uint32_t size, const uint8_t *md5); + void newImageInfo(MessageId id, uint32_t size, const uint8_t *md5); void newImageSliceData(const std::vector &data); void errorOccurred(const QString &error); void commandStarted(ModuleCommunication::MessageId messageId); diff --git a/Analyser/qml/OperationItem.qml b/Analyser/qml/OperationItem.qml index 8fed3dd..d173517 100644 --- a/Analyser/qml/OperationItem.qml +++ b/Analyser/qml/OperationItem.qml @@ -87,6 +87,12 @@ ColumnLayout { checked: App.persistenceMode onToggled: App.persistenceMode = !App.persistenceMode } + Text { + text: qsTr("保存图片") + } + Switch { + id: extendedVerifyMode + } Text { text: qsTr("识别间隔(s)") } @@ -104,7 +110,8 @@ ColumnLayout { } else { App.persistenceVerifyInterval = parseInt( verifyIntetval.text) - App.verify(parseInt(verifyTimeout.text)) + App.verify(extendedVerifyMode.checked, + parseInt(verifyTimeout.text)) } } } @@ -153,6 +160,15 @@ ColumnLayout { text: "ID查询" onClicked: App.module.requestUniqueId() } + Row { + Text { + text: qsTr("日志") + } + Switch { + id: debugMode + onToggled: App.module.setDebugEnabled(debugMode.checked) + } + } } } }