实现图片上传下载。
This commit is contained in:
parent
174e22ea79
commit
6e11d190c0
@ -12,6 +12,10 @@
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QTimer>
|
||||
#include <fstream>
|
||||
#include <mbedtls/md5.h>
|
||||
|
||||
constexpr uint32_t ImageSliceSize = 2048;
|
||||
|
||||
Application::Application(int &argc, char **argv) : m_app(std::make_shared<QApplication>(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<char>((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
|
||||
|
||||
ModuleCommunication::UploadImageInformation request;
|
||||
mbedtls_md5_context context;
|
||||
mbedtls_md5_init(&context);
|
||||
mbedtls_md5_starts(&context);
|
||||
mbedtls_md5_update(&context, reinterpret_cast<const uint8_t *>(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<uint8_t> &data) {
|
||||
// << ", total size: " << m_enrolledImageSize;
|
||||
m_enrollYImageBuffer.append(reinterpret_cast<const char *>(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<milliseconds>(system_clock::now() - m_startUploadTime);
|
||||
QImage image(reinterpret_cast<const uint8_t *>(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<milliseconds>(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<milliseconds>(system_clock::now() - m_startUploadTime);
|
||||
}
|
||||
}
|
||||
|
||||
if (messageId == ModuleCommunication::Verify && m_persistenceMode) { // 持续识别逻辑
|
||||
m_persistenceModeStarted = true;
|
||||
} else if (messageId == ModuleCommunication::Reset) {
|
||||
|
@ -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<char> m_uploadBuffer;
|
||||
|
||||
std::shared_ptr<VideoPlayer> m_videoPlayer;
|
||||
VideoFrameProvider *m_videoFrameProvider;
|
||||
};
|
||||
|
@ -106,8 +106,9 @@ void ModuleCommunication::requestEnrolledImage(uint32_t offset, uint32_t size) {
|
||||
auto [data, frameSize] =
|
||||
generateFrame(GetEnrolledImage, reinterpret_cast<const uint8_t *>(&request), sizeof(request));
|
||||
m_serialPort->write(reinterpret_cast<const char *>(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<const uint8_t *>(&request), sizeof(request));
|
||||
m_serialPort->write(reinterpret_cast<const char *>(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<UploadImageDataSlice *>(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<const char *>(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<const ImageSliceReply *>(data + 7);
|
||||
emit newImageSliceData(std::vector<uint8_t>(info->data, info->data + ntohl(info->size)));
|
||||
uint32_t sliceSize = ntohl(info->size);
|
||||
emit newImageSliceData(std::vector<uint8_t>(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<int>(replyId) & 0xff)
|
||||
<< ", data: " << protocolDataFormatString(data, size);
|
||||
@ -353,7 +386,7 @@ void ModuleCommunication::onErrorOccurred(QSerialPort::SerialPortError error) {
|
||||
|
||||
std::pair<uint8_t *, uint32_t> 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;
|
||||
|
@ -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<uint8_t *, uint32_t> 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<QSerialPort> m_serialPort;
|
||||
QByteArray m_receivedBuffer;
|
||||
|
@ -111,6 +111,7 @@ ColumnLayout {
|
||||
}
|
||||
Button {
|
||||
text: "图片下发注册"
|
||||
onClicked: App.uploadImage()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user