diff --git a/Analyser/Application.cpp b/Analyser/Application.cpp index 634fe91..f635b01 100644 --- a/Analyser/Application.cpp +++ b/Analyser/Application.cpp @@ -12,6 +12,10 @@ #include #include #include +#include +#include + +constexpr uint32_t ImageSliceSize = 2048; Application::Application(int &argc, char **argv) : m_app(std::make_shared(argc, argv)) { QFont font; @@ -178,6 +182,31 @@ void Application::getEnrolledImage(const QString &username, uint8_t timeout) { m_communication->enrollEx(username.toStdString(), timeout); } +void Application::uploadImage() { + m_uploadImageSendedSize = 0; + std::ifstream ifs("palm.yuv", std::ofstream::binary); + m_uploadBuffer = std::vector((std::istreambuf_iterator(ifs)), std::istreambuf_iterator()); + + ModuleCommunication::UploadImageInformation request; + mbedtls_md5_context context; + mbedtls_md5_init(&context); + mbedtls_md5_starts(&context); + mbedtls_md5_update(&context, reinterpret_cast(m_uploadBuffer.data()), m_uploadBuffer.size()); + mbedtls_md5_finish(&context, request.md5); + mbedtls_md5_free(&context); + + request.operation = 0; + request.width = 600; + request.height = 800; + request.size = m_uploadBuffer.size(); + strncpy(request.username, "下发测试", sizeof(request.username)); + m_communication->uploadImageInfo(request); + LOG(info) << "upload image, md5: " + << ModuleCommunication::protocolDataFormatString(request.md5, sizeof(request.md5)); + + m_startUploadTime = std::chrono::system_clock::now(); +} + ModuleCommunication *Application::module() const { return m_communication.get(); } @@ -238,7 +267,7 @@ void Application::onErrorOccurred(const QString &error) { void Application::onNewEnrolledImageInfo(uint32_t size, const uint8_t *md5) { using namespace std::chrono; m_enrolledImageSize = size; - m_communication->requestEnrolledImage(0, 1024); + m_communication->requestEnrolledImage(0, ImageSliceSize); m_enrollYImageBuffer.clear(); m_startUploadTime = system_clock::now(); } @@ -249,13 +278,16 @@ void Application::onNewImageSliceData(const std::vector &data) { // << ", 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(), 1024); + m_communication->requestEnrolledImage(m_enrollYImageBuffer.size(), ImageSliceSize); } else { LOG(info) << "request finished, elapsed: " << duration_cast(system_clock::now() - m_startUploadTime); QImage image(reinterpret_cast(m_enrollYImageBuffer.data()), 600, 800, QImage::Format_Grayscale8); image.save("test.jpg"); + + std::ofstream ofs("palm.yuv", std::ofstream::binary); + ofs.write(m_enrollYImageBuffer.data(), m_enrollYImageBuffer.size()); } } @@ -269,7 +301,7 @@ void Application::onCommandStarted(ModuleCommunication::MessageId messageId) { void Application::onCommandFinished(ModuleCommunication::MessageId messageId, ModuleCommunication::MessageStatus status) { - LOG(info) << m_persistenceMode << " " << m_persistenceModeStarted << " " << m_persistenceVerifyInterval; + // LOG(info) << m_persistenceMode << " " << m_persistenceModeStarted << " " << m_persistenceVerifyInterval; using namespace std::chrono; if (messageId == ModuleCommunication::Verify) { m_verifyElapsed = duration_cast(system_clock::now() - m_verifyStartTime); @@ -279,6 +311,22 @@ void Application::onCommandFinished(ModuleCommunication::MessageId messageId, } } + if (messageId == ModuleCommunication::UploadImageInfo) { + m_communication->uploadImageData( + m_uploadImageSendedSize, (const uint8_t *)m_uploadBuffer.data() + m_uploadImageSendedSize, ImageSliceSize); + } else if (messageId == ModuleCommunication::UploadImageData) { + m_uploadImageSendedSize += ImageSliceSize; + if (m_uploadImageSendedSize < m_uploadBuffer.size()) { + auto remainSize = m_uploadBuffer.size() - m_uploadImageSendedSize; + m_communication->uploadImageData(m_uploadImageSendedSize, + (const uint8_t *)m_uploadBuffer.data() + m_uploadImageSendedSize, + remainSize < ImageSliceSize ? remainSize : ImageSliceSize); + } else { + LOG(info) << "upload finished, elapsed: " + << duration_cast(system_clock::now() - m_startUploadTime); + } + } + if (messageId == ModuleCommunication::Verify && m_persistenceMode) { // 持续识别逻辑 m_persistenceModeStarted = true; } else if (messageId == ModuleCommunication::Reset) { diff --git a/Analyser/Application.h b/Analyser/Application.h index c197148..4692391 100644 --- a/Analyser/Application.h +++ b/Analyser/Application.h @@ -47,6 +47,7 @@ public: Q_INVOKABLE void deleteUser(uint16_t userid); Q_INVOKABLE void deleteAll(); Q_INVOKABLE void getEnrolledImage(const QString &username, uint8_t timeout); + Q_INVOKABLE void uploadImage(); ModuleCommunication *module() const; bool connected() const; bool uvcOpened() const; @@ -94,6 +95,9 @@ private: QByteArray m_enrollYImageBuffer; std::chrono::system_clock::time_point m_startUploadTime; + uint32_t m_uploadImageSendedSize; + std::vector m_uploadBuffer; + std::shared_ptr m_videoPlayer; VideoFrameProvider *m_videoFrameProvider; }; diff --git a/Analyser/ModuleCommunication.cpp b/Analyser/ModuleCommunication.cpp index d78cd76..06939b7 100644 --- a/Analyser/ModuleCommunication.cpp +++ b/Analyser/ModuleCommunication.cpp @@ -106,8 +106,9 @@ void ModuleCommunication::requestEnrolledImage(uint32_t offset, uint32_t size) { auto [data, frameSize] = generateFrame(GetEnrolledImage, reinterpret_cast(&request), sizeof(request)); m_serialPort->write(reinterpret_cast(data), frameSize); - LOG_CAT(info, GUI) << "发送获取图片指令: " << protocolDataFormatString(data, frameSize); - LOG_CAT(info, GUI) << Separator; + // 打印太耗时 + // LOG_CAT(info, GUI) << "发送获取图片指令: " << protocolDataFormatString(data, frameSize); + // LOG_CAT(info, GUI) << Separator; } void ModuleCommunication::requestPalmFeature(uint16_t userid) { @@ -146,6 +147,31 @@ void ModuleCommunication::enrollPalmFeature(uint16_t userid, const PalmFeature & if (buffer != nullptr) delete[] buffer; } +void ModuleCommunication::uploadImageInfo(const UploadImageInformation &info) { + UploadImageInformation request; + request.operation = info.operation; + request.width = htons(info.width); + request.height = htons(info.height); + request.size = htonl(info.size); + memcpy(request.username, info.username, sizeof(request.username)); + memcpy(request.md5, info.md5, sizeof(request.md5)); + auto [data, frameSize] = + generateFrame(UploadImageInfo, reinterpret_cast(&request), sizeof(request)); + m_serialPort->write(reinterpret_cast(data), frameSize); +} + +void ModuleCommunication::uploadImageData(uint32_t offset, const uint8_t *data, uint32_t size) { + uint32_t dataSize = sizeof(UploadImageDataSlice) + size; + auto buffer = new uint8_t[dataSize]; + auto request = reinterpret_cast(buffer); + request->size = htonl(size); + request->offset = htonl(offset); + memcpy(request->data, data, size); + auto [frameData, frameSize] = generateFrame(UploadImageData, buffer, dataSize); + m_serialPort->write(reinterpret_cast(frameData), frameSize); + delete[] buffer; +} + ModuleCommunication::MessageId ModuleCommunication::currentMessageId() const { return m_currentMessageId; } @@ -216,7 +242,8 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { // LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size); if (result == Success) { auto info = reinterpret_cast(data + 7); - emit newImageSliceData(std::vector(info->data, info->data + ntohl(info->size))); + uint32_t sliceSize = ntohl(info->size); + emit newImageSliceData(std::vector(info->data, info->data + sliceSize)); } // LOG_CAT(info, GUI) << Separator; break; @@ -264,6 +291,12 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) { LOG_CAT(info, GUI) << Separator; break; } + case UploadImageInfo: { + break; + } + case UploadImageData: { + break; + } default: LOG(warning) << "unknown reply command: 0x" << (static_cast(replyId) & 0xff) << ", data: " << protocolDataFormatString(data, size); @@ -353,7 +386,7 @@ void ModuleCommunication::onErrorOccurred(QSerialPort::SerialPortError error) { std::pair ModuleCommunication::generateFrame(MessageId command, const uint8_t *data, uint16_t size) { - static uint8_t sendBuffer[1024] = {0}; + static uint8_t sendBuffer[4096] = {0}; memset(sendBuffer, 0, sizeof(sendBuffer)); sendBuffer[0] = 0xef; sendBuffer[1] = 0xaa; diff --git a/Analyser/ModuleCommunication.h b/Analyser/ModuleCommunication.h index 048fa04..e42de85 100644 --- a/Analyser/ModuleCommunication.h +++ b/Analyser/ModuleCommunication.h @@ -23,6 +23,8 @@ public: GetEnrolledImage = 0x1F, DeleteUser = 0x20, DeleteAll = 0x21, + UploadImageInfo = 0xF6, + UploadImageData = 0xF7, RegisterPalmFeature = 0xF9, RequestPalmFeature = 0xFA, Idle = 0xFF, @@ -114,6 +116,23 @@ public: uint8_t feature[0]; }; + struct UploadImageInformation { + uint8_t operation; // 0:图片录入掌静脉 + uint8_t format; // 0: 灰度图(纯Y分量) + uint16_t width; + uint16_t height; + uint32_t size; + uint8_t md5[16]; // 图片内容 md5 值 + char username[32]; + }; + + struct UploadImageDataSlice { + uint32_t offset; + uint32_t size; + uint8_t reserved[4]; // 预留 + uint8_t data[0]; + }; + #pragma pack() explicit ModuleCommunication(QObject *parent = nullptr); bool open(const QString &portName, int baudRate); @@ -129,8 +148,11 @@ public: void requestPalmFeature(uint16_t userid); void enrollPalmFeature(uint16_t userid, const PalmFeature &feature); - MessageId currentMessageId() const; + void uploadImageInfo(const UploadImageInformation &info); + void uploadImageData(uint32_t offset, const uint8_t *data, uint32_t size); + MessageId currentMessageId() const; + static std::string protocolDataFormatString(const uint8_t *data, int size); signals: void newVerifyResult(uint16_t userid, const QString &username); void newPalmFeature(const PalmFeature &feature); @@ -145,7 +167,7 @@ protected: void onReadyRead(); void onErrorOccurred(QSerialPort::SerialPortError error); std::pair generateFrame(MessageId command, const uint8_t *data = nullptr, uint16_t size = 0); - std::string protocolDataFormatString(const uint8_t *data, int size); + private: std::shared_ptr m_serialPort; QByteArray m_receivedBuffer; diff --git a/Analyser/qml/OperationItem.qml b/Analyser/qml/OperationItem.qml index 04b7533..7504c12 100644 --- a/Analyser/qml/OperationItem.qml +++ b/Analyser/qml/OperationItem.qml @@ -111,6 +111,7 @@ ColumnLayout { } Button { text: "图片下发注册" + onClicked: App.uploadImage() } } }