适配模组的strict模式。
This commit is contained in:
parent
36a5877a0c
commit
2c06e4d1e0
@ -10,9 +10,9 @@
|
||||
#include "StringUtility.h"
|
||||
#include "VideoFrameProvider.h"
|
||||
#include "VideoPlayer.h"
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
#include <QFont>
|
||||
#include <QGuiApplication>
|
||||
#include <QImage>
|
||||
#include <QQmlApplicationEngine>
|
||||
#include <QSerialPortInfo>
|
||||
@ -26,11 +26,11 @@
|
||||
|
||||
constexpr uint32_t ImageSliceSize = (4000 - 32);
|
||||
|
||||
Application::Application(int &argc, char **argv) : m_app(std::make_shared<QApplication>(argc, argv)) {
|
||||
Application::Application(int &argc, char **argv) : m_app(std::make_shared<QGuiApplication>(argc, argv)) {
|
||||
m_app->setApplicationName(APPLICATION_NAME);
|
||||
m_app->setApplicationVersion(QString("v%1_%2 build: %3 %4").arg(APP_VERSION, GIT_COMMIT_ID, __DATE__, __TIME__));
|
||||
QFont font;
|
||||
font.setPointSize(16);
|
||||
font.setPointSize(12);
|
||||
m_app->setFont(font);
|
||||
|
||||
m_verifyTimer = new QTimer(this);
|
||||
@ -56,7 +56,7 @@ Application::Application(int &argc, char **argv) : m_app(std::make_shared<QAppli
|
||||
void Application::onNewEnrollResult(uint16_t userid) {
|
||||
m_palmId = userid;
|
||||
QTimer::singleShot(0, this, [this, userid]() {
|
||||
emit newStatusTip(Info, QString("%1,录入成功,ID:%2").arg(m_palmUsername).arg(userid));
|
||||
emit newStatusTip(Info, "录入成功", QString("用户: %1, ID: %2").arg(m_palmUsername).arg(userid));
|
||||
});
|
||||
}
|
||||
|
||||
@ -106,6 +106,14 @@ Application *Application::create(QQmlEngine *qmlEngine, QJSEngine *jsEngine) {
|
||||
QStringList Application::availableSerialPorts() const {
|
||||
QStringList ret;
|
||||
auto ports = QSerialPortInfo::availablePorts();
|
||||
auto iterator = std::find_if(ports.cbegin(), ports.cend(), [](const QSerialPortInfo &info) {
|
||||
return (info.productIdentifier() == ModuleCommunication::ProductIdentifier) &&
|
||||
(info.vendorIdentifier() == ModuleCommunication::VendorIdentifier);
|
||||
});
|
||||
if (iterator != ports.cend()) {
|
||||
ret << iterator->portName();
|
||||
ports.erase(iterator);
|
||||
}
|
||||
for (auto &port : ports) {
|
||||
if (port.description() == "蓝牙链接上的标准串行") continue;
|
||||
ret << port.portName();
|
||||
@ -200,11 +208,11 @@ void Application::verify(bool captureImage, uint8_t timeout) {
|
||||
m_verifyExtendedMode = captureImage;
|
||||
}
|
||||
|
||||
void Application::enroll(const QString &username, bool persistence, uint8_t timeout) {
|
||||
void Application::enroll(const QString &username, bool strictMode, bool persistence, uint8_t timeout) {
|
||||
if (m_communication->currentMessageId() != ModuleCommunication::Idle) {
|
||||
m_communication->reset();
|
||||
}
|
||||
m_communication->enroll(username.toStdString(), persistence, timeout);
|
||||
m_communication->enroll(username.toStdString(), strictMode, persistence, timeout);
|
||||
m_palmUsername = username;
|
||||
}
|
||||
|
||||
@ -222,11 +230,11 @@ void Application::deleteAll() {
|
||||
m_communication->deleteAll();
|
||||
}
|
||||
|
||||
void Application::enrollExtended(const QString &username, bool persistence, uint8_t timeout) {
|
||||
void Application::enrollExtended(const QString &username, bool strictMode, bool persistence, uint8_t timeout) {
|
||||
if (m_communication->currentMessageId() != ModuleCommunication::Idle) {
|
||||
m_communication->reset();
|
||||
}
|
||||
m_communication->enrollExtended(username.toStdString(), persistence, timeout);
|
||||
m_communication->enrollExtended(username.toStdString(), strictMode, persistence, timeout);
|
||||
m_palmUsername = username;
|
||||
}
|
||||
|
||||
@ -341,8 +349,18 @@ void Application::onNewPalmFeature(const PalmFeature &feature) {
|
||||
}
|
||||
}
|
||||
|
||||
void Application::onErrorOccurred(const QString &error) {
|
||||
void Application::onErrorOccurred(ModuleCommunication::NoteId note, const QString &error,
|
||||
const QString &detailMessage) {
|
||||
TipType type = Tip;
|
||||
if (note == ModuleCommunication::NoteId::DeviceError) {
|
||||
type = Error;
|
||||
QTimer::singleShot(0, this, [this]() { close(); });
|
||||
} else if (note == ModuleCommunication::NoteId::InteractWarning) {
|
||||
type = Warnging;
|
||||
} else {
|
||||
type = Warnging;
|
||||
}
|
||||
emit newStatusTip(type, error, detailMessage);
|
||||
}
|
||||
|
||||
void Application::onNewImageInfo(ModuleCommunication::MessageId messageId, uint32_t size, const uint8_t *md5) {
|
||||
@ -433,11 +451,6 @@ void Application::onCommandFinished(ModuleCommunication::MessageId messageId,
|
||||
(status == ModuleCommunication::Failed4LivenessCheck))) {
|
||||
m_verifyTimer->start(m_persistenceVerifyInterval * 1000);
|
||||
}
|
||||
|
||||
if (((messageId == ModuleCommunication::EnrollSingle) || (messageId == ModuleCommunication::EnrollExtended)) &&
|
||||
(status == ModuleCommunication::Success)) {
|
||||
emit newStatusTip(Info, "录入成功。");
|
||||
}
|
||||
emit isVerifyingChanged();
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@ public:
|
||||
Tip,
|
||||
Error,
|
||||
Info,
|
||||
Warnging,
|
||||
};
|
||||
Q_ENUM(TipType)
|
||||
|
||||
@ -51,8 +52,8 @@ public:
|
||||
Q_INVOKABLE void closeUVC();
|
||||
Q_INVOKABLE bool startOta(const QString &path);
|
||||
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 enroll(const QString &username, bool strictMode, bool persistence, uint8_t timeout);
|
||||
Q_INVOKABLE void enrollExtended(const QString &username, bool strictMode, bool persistence, uint8_t timeout);
|
||||
Q_INVOKABLE void deleteUser(uint16_t userid);
|
||||
Q_INVOKABLE void deleteAll();
|
||||
Q_INVOKABLE void uploadImage(const QString &path, const QString &username, int operation);
|
||||
@ -77,7 +78,7 @@ signals:
|
||||
void uvcOpenedChanged();
|
||||
void newVideoFrame();
|
||||
void newLog(const QString &log);
|
||||
void newStatusTip(TipType type, const QString &tip);
|
||||
void newStatusTip(TipType type, const QString &tip, const QString &detailMessage = "");
|
||||
void updateFinished();
|
||||
void otaMessage(const QString &text);
|
||||
void otaProgressChanged(int32_t progress);
|
||||
@ -87,7 +88,7 @@ protected:
|
||||
void onNewEnrollResult(uint16_t userid);
|
||||
void onNewVerifyResult(uint16_t userid, const QString &username, uint16_t elapsed);
|
||||
void onNewPalmFeature(const PalmFeature &feature);
|
||||
void onErrorOccurred(const QString &error);
|
||||
void onErrorOccurred(ModuleCommunication::NoteId note, const QString &error, const QString &detailMessage);
|
||||
void onNewImageInfo(ModuleCommunication::MessageId messageId, uint32_t size, const uint8_t *md5);
|
||||
void onNewImageSliceData(const std::vector<uint8_t> &data);
|
||||
void onCommandStarted(ModuleCommunication::MessageId messageId);
|
||||
|
@ -1,8 +1,8 @@
|
||||
project(Analyser VERSION 0.3 LANGUAGES C CXX)
|
||||
set(APPLICATION_NAME "掌静脉测试工具")
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick QuickTemplates2 Widgets SerialPort JpegPrivate BundledLibjpeg)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Quick QuickTemplates2 Widgets SerialPort JpegPrivate BundledLibjpeg)
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Quick QuickTemplates2 SerialPort JpegPrivate BundledLibjpeg)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Quick QuickTemplates2 SerialPort JpegPrivate BundledLibjpeg)
|
||||
|
||||
qt_standard_project_setup(REQUIRES 6.5)
|
||||
|
||||
@ -13,7 +13,6 @@ add_executable(Analyser Analyser.rc
|
||||
Application.h Application.cpp
|
||||
CategoryLogSinkBackend.h CategoryLogSinkBackend.cpp
|
||||
ImageDecoder.h ImageDecoder.cpp
|
||||
Widget.h Widget.cpp
|
||||
ModuleCommunication.h ModuleCommunication.cpp
|
||||
PalmFeatureTableModel.h PalmFeatureTableModel.cpp
|
||||
VideoFrameProvider.h VideoFrameProvider.cpp
|
||||
@ -27,7 +26,6 @@ qt_add_qml_module(Analyser
|
||||
qml/Main.qml
|
||||
qml/ConnectionItem.qml
|
||||
qml/OperationItem.qml
|
||||
qml/StatusTip.qml
|
||||
qml/OtaPage.qml
|
||||
RESOURCES
|
||||
resources/successfull.svg
|
||||
@ -67,7 +65,6 @@ target_link_libraries(Analyser
|
||||
PRIVATE avformat
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::Quick
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::QuickTemplates2
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::SerialPort
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::JpegPrivate
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::BundledLibjpeg
|
||||
|
@ -67,8 +67,9 @@ void ModuleCommunication::reset() {
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
|
||||
void ModuleCommunication::enroll(const std::string &username, bool persistence, uint8_t timeout) {
|
||||
void ModuleCommunication::enroll(const std::string &username, bool strictMode, bool persistence, uint8_t timeout) {
|
||||
EnrollData data = {0};
|
||||
data.strictMode = strictMode ? 1 : 0;
|
||||
data.timeout = timeout;
|
||||
data.skipSave = persistence ? 0 : 1;
|
||||
strncpy(reinterpret_cast<char *>(data.username), username.c_str(), sizeof(data.username));
|
||||
@ -81,8 +82,10 @@ void ModuleCommunication::enroll(const std::string &username, bool persistence,
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
|
||||
void ModuleCommunication::enrollExtended(const std::string &username, bool persistence, uint8_t timeout) {
|
||||
void ModuleCommunication::enrollExtended(const std::string &username, bool strictMode, bool persistence,
|
||||
uint8_t timeout) {
|
||||
EnrollData data = {};
|
||||
data.strictMode = strictMode ? 1 : 0;
|
||||
data.timeout = timeout;
|
||||
data.skipSave = persistence ? 0 : 1;
|
||||
strncpy(reinterpret_cast<char *>(data.username), username.c_str(), sizeof(data.username));
|
||||
@ -372,7 +375,11 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
|
||||
}
|
||||
case NoteId::PalmState: { // 模组返回的数据为当前帧的手掌状态
|
||||
auto state = reinterpret_cast<const PalmStateNote *>(data + 6);
|
||||
LOG(info) << "palm state: " << (int)ntohs(state->state);
|
||||
uint16_t palmState = ntohs(state->state);
|
||||
if (palmState == NeedMoveToCenter) {
|
||||
emit errorOccurred(NoteId::InteractWarning, "录入提示", "请将手掌置于画面中心");
|
||||
}
|
||||
LOG(info) << "palm state: " << palmState;
|
||||
break;
|
||||
}
|
||||
case NoteId::UnknownError: {
|
||||
@ -448,7 +455,7 @@ void ModuleCommunication::onReadyRead() {
|
||||
void ModuleCommunication::onErrorOccurred(QSerialPort::SerialPortError error) {
|
||||
if (error == QSerialPort::NoError) return;
|
||||
LOG_CAT(info, GUI) << m_serialPort->portName().toStdString() << ": " << m_serialPort->errorString().toStdString();
|
||||
emit errorOccurred(m_serialPort->errorString());
|
||||
emit errorOccurred(NoteId::DeviceError, m_serialPort->errorString());
|
||||
}
|
||||
|
||||
std::pair<uint8_t *, uint32_t> ModuleCommunication::generateFrame(MessageId command, const uint8_t *data,
|
||||
|
@ -19,6 +19,8 @@ class ModuleCommunication : public QObject {
|
||||
Q_PROPERTY(int otaVerison MEMBER m_otaVerison NOTIFY verisonChanged)
|
||||
|
||||
public:
|
||||
constexpr static uint16_t VendorIdentifier = 0x3346;
|
||||
constexpr static uint16_t ProductIdentifier = 0x0001;
|
||||
constexpr static uint16_t InvalidUserId = std::numeric_limits<uint16_t>::max();
|
||||
enum MessageId : uint8_t {
|
||||
Reply = 0,
|
||||
@ -48,6 +50,9 @@ public:
|
||||
UnknownError = 0x02,
|
||||
DebugInfo = 0x55,
|
||||
NoAliveImage = 0x56,
|
||||
|
||||
DeviceError = 0xF0, // 系统设备出现的错误,例如 QSerialPort
|
||||
InteractWarning,
|
||||
};
|
||||
|
||||
enum PalmState {
|
||||
@ -94,6 +99,7 @@ public:
|
||||
|
||||
struct EnrollData {
|
||||
uint8_t username[32];
|
||||
uint8_t strictMode = 0;
|
||||
uint8_t skipSave = 0;
|
||||
uint8_t timeout;
|
||||
};
|
||||
@ -172,8 +178,8 @@ public:
|
||||
void verifyExtended(bool captureImage, uint8_t timeout);
|
||||
Q_INVOKABLE void reset();
|
||||
|
||||
void enroll(const std::string &username, bool persistence, uint8_t timeout);
|
||||
void enrollExtended(const std::string &username, bool persistence, uint8_t timeout);
|
||||
void enroll(const std::string &username, bool strictMode, bool persistence, uint8_t timeout);
|
||||
void enrollExtended(const std::string &username, bool strictMode, bool persistence, uint8_t timeout);
|
||||
Q_INVOKABLE void deleteUser(uint16_t userid);
|
||||
Q_INVOKABLE void deleteAll();
|
||||
Q_INVOKABLE void requestUniqueId();
|
||||
@ -200,7 +206,7 @@ signals:
|
||||
void newPalmFeature(const PalmFeature &feature);
|
||||
void newImageInfo(MessageId id, uint32_t size, const uint8_t *md5);
|
||||
void newImageSliceData(const std::vector<uint8_t> &data);
|
||||
void errorOccurred(const QString &error);
|
||||
void errorOccurred(NoteId note, const QString &error, const QString &detailMessage = "");
|
||||
void commandStarted(ModuleCommunication::MessageId messageId);
|
||||
void commandFinished(MessageId messageId, MessageStatus status);
|
||||
void currentMessageIdChanged();
|
||||
|
@ -1,287 +0,0 @@
|
||||
#include "Widget.h"
|
||||
#include "Application.h"
|
||||
#include "BoostLog.h"
|
||||
#include "CategoryLogSinkBackend.h"
|
||||
#include "Database.h"
|
||||
#include "ModuleCommunication.h"
|
||||
#include "PalmFeatureTableModel.h"
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QTabWidget>
|
||||
#include <QTableView>
|
||||
#include <QTextBrowser>
|
||||
#include <QTimer>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
Widget::Widget(QWidget *parent) : QWidget{parent} {
|
||||
auto serialGroupBox = new QGroupBox("串口设置");
|
||||
auto serialLayout = new QGridLayout();
|
||||
|
||||
auto label = new QLabel("端口");
|
||||
serialLayout->addWidget(label, 0, 0);
|
||||
|
||||
m_serialComboBox = new QComboBox();
|
||||
serialLayout->addWidget(m_serialComboBox, 0, 1);
|
||||
|
||||
label = new QLabel("波特率");
|
||||
serialLayout->addWidget(label, 1, 0);
|
||||
|
||||
label = new QLabel("115200");
|
||||
serialLayout->addWidget(label, 1, 1);
|
||||
|
||||
auto refreshButton = new QPushButton("刷新");
|
||||
connect(refreshButton, &QPushButton::clicked, this, &Widget::onSerialRefreshButtonClicked);
|
||||
m_serialConnectButton = new QPushButton("连接");
|
||||
connect(m_serialConnectButton, &QPushButton::clicked, this, &Widget::onSerialConnectButtonClicked);
|
||||
serialLayout->addWidget(refreshButton, 2, 0);
|
||||
serialLayout->addWidget(m_serialConnectButton, 2, 1);
|
||||
serialGroupBox->setLayout(serialLayout);
|
||||
|
||||
auto connectLayout = new QHBoxLayout();
|
||||
connectLayout->addWidget(serialGroupBox);
|
||||
connectLayout->addWidget(initializeUvcGroupBox());
|
||||
|
||||
m_logBrowser = new QTextBrowser();
|
||||
m_logBrowser->setReadOnly(true);
|
||||
auto logLayout = new QVBoxLayout();
|
||||
m_logBrowser->setLayout(logLayout);
|
||||
auto btn = new QPushButton("清空");
|
||||
connect(btn, &QPushButton::clicked, this, &Widget::onClearLogButtonClicked);
|
||||
logLayout->addWidget(btn, 0, Qt::AlignBottom | Qt::AlignRight);
|
||||
|
||||
m_featureTableView = new QTableView();
|
||||
|
||||
auto tabWidget = new QTabWidget();
|
||||
tabWidget->addTab(m_logBrowser, "日志");
|
||||
tabWidget->addTab(new QWidget(), "视频流");
|
||||
tabWidget->addTab(m_featureTableView, "本地特征值列表");
|
||||
|
||||
m_commandGroupBox = initializeCommandGroupBox();
|
||||
|
||||
auto operatorLayout = new QVBoxLayout();
|
||||
operatorLayout->addLayout(connectLayout);
|
||||
operatorLayout->addWidget(m_commandGroupBox);
|
||||
operatorLayout->addStretch(2);
|
||||
|
||||
auto layout = new QHBoxLayout(this);
|
||||
layout->addLayout(operatorLayout, 1);
|
||||
layout->addWidget(tabWidget, 3);
|
||||
|
||||
m_featureModel = new PalmFeatureTableModel(this);
|
||||
m_featureTableView->setModel(m_featureModel);
|
||||
|
||||
QTimer::singleShot(0, this, [this]() {
|
||||
onSerialRefreshButtonClicked();
|
||||
m_commandGroupBox->setEnabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
QGroupBox *Widget::initializeCommandGroupBox() {
|
||||
auto ret = new QGroupBox("命令");
|
||||
auto layout = new QGridLayout();
|
||||
|
||||
layout->addWidget(initializeEnrollGroupBox(), 0, 0);
|
||||
layout->addWidget(initializeVerifyGroupBox(), 0, 1);
|
||||
layout->addWidget(initializeDeleteGroupBox(), 1, 0);
|
||||
layout->addWidget(initializePalmFeatureGroupBox(), 1, 1);
|
||||
|
||||
auto resetButton = new QPushButton("复位");
|
||||
connect(resetButton, &QPushButton::clicked, this, &Widget::onResetButtonClicked);
|
||||
layout->addWidget(resetButton, 2, 0);
|
||||
|
||||
ret->setLayout(layout);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Widget::onClearLogButtonClicked() {
|
||||
m_logBrowser->clear();
|
||||
}
|
||||
|
||||
QGroupBox *Widget::initializeEnrollGroupBox() {
|
||||
auto ret = new QGroupBox("注册用户");
|
||||
auto layout = new QFormLayout();
|
||||
|
||||
m_enrollNameEdit = new QLineEdit();
|
||||
layout->addRow("用户姓名:", m_enrollNameEdit);
|
||||
|
||||
m_enrollTimeoutEdit = new QLineEdit("10");
|
||||
layout->addRow("超时时间:", m_enrollTimeoutEdit);
|
||||
|
||||
m_enrollButton = new QPushButton("注册");
|
||||
connect(m_enrollButton, &QPushButton::clicked, this, &Widget::onEnrollButtonClicked);
|
||||
layout->addRow("", m_enrollButton);
|
||||
|
||||
auto enrollExButton = new QPushButton("注册(EX)");
|
||||
connect(enrollExButton, &QPushButton::clicked, this, &Widget::onEnrollExButtonClicked);
|
||||
layout->addRow("", enrollExButton);
|
||||
|
||||
ret->setLayout(layout);
|
||||
return ret;
|
||||
}
|
||||
QGroupBox *Widget::initializeVerifyGroupBox() {
|
||||
auto ret = new QGroupBox("识别用户");
|
||||
auto layout = new QFormLayout();
|
||||
|
||||
m_verifyTimeoutEdit = new QLineEdit("10");
|
||||
layout->addRow("超时时间:", m_verifyTimeoutEdit);
|
||||
|
||||
m_verifyButton = new QPushButton("识别");
|
||||
connect(m_verifyButton, &QPushButton::clicked, this, &Widget::onVerifyButtonClicked);
|
||||
layout->addRow("", m_verifyButton);
|
||||
ret->setLayout(layout);
|
||||
return ret;
|
||||
}
|
||||
QGroupBox *Widget::initializeDeleteGroupBox() {
|
||||
auto ret = new QGroupBox("删除用户");
|
||||
auto layout = new QFormLayout();
|
||||
|
||||
m_deleteIdEdit = new QLineEdit("");
|
||||
layout->addRow("用户ID:", m_deleteIdEdit);
|
||||
|
||||
m_deleteButton = new QPushButton("删除");
|
||||
connect(m_deleteButton, &QPushButton::clicked, this, &Widget::onDeleteButtonClicked);
|
||||
layout->addRow("", m_deleteButton);
|
||||
|
||||
m_deleteAllButton = new QPushButton("删除所有");
|
||||
connect(m_deleteAllButton, &QPushButton::clicked, this, &Widget::onDeleteAllButtonClicked);
|
||||
layout->addRow("", m_deleteAllButton);
|
||||
|
||||
ret->setLayout(layout);
|
||||
return ret;
|
||||
}
|
||||
QGroupBox *Widget::initializePalmFeatureGroupBox() {
|
||||
auto ret = new QGroupBox("特征值下发/上报");
|
||||
|
||||
auto layout = new QFormLayout();
|
||||
|
||||
m_palmFeatureEdit = new QLineEdit("");
|
||||
layout->addRow("用户ID:", m_palmFeatureEdit);
|
||||
|
||||
auto button1 = new QPushButton("特征值上报");
|
||||
layout->addRow("", button1);
|
||||
connect(button1, &QPushButton::clicked, this, &Widget::onRequestPalmFeatureButtonClicked);
|
||||
|
||||
auto button = new QPushButton("特征值下发");
|
||||
connect(button, &QPushButton::clicked, this, &Widget::onRegisterPalmFeatureButtonClicked);
|
||||
layout->addRow("", button);
|
||||
|
||||
ret->setLayout(layout);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QGroupBox *Widget::initializeUvcGroupBox() {
|
||||
auto ret = new QGroupBox("UVC设置");
|
||||
auto uvcLayout = new QGridLayout();
|
||||
auto label = new QLabel("设备名");
|
||||
uvcLayout->addWidget(label, 0, 0);
|
||||
|
||||
auto comboBox = new QComboBox();
|
||||
uvcLayout->addWidget(comboBox, 0, 1);
|
||||
|
||||
auto uvcRefreshButton = new QPushButton("刷新");
|
||||
auto uvcConnectButton = new QPushButton("连接");
|
||||
uvcLayout->addWidget(uvcRefreshButton, 1, 0);
|
||||
uvcLayout->addWidget(uvcConnectButton, 1, 1);
|
||||
ret->setLayout(uvcLayout);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Widget::onSerialConnectButtonClicked() {
|
||||
auto button = dynamic_cast<QPushButton *>(sender());
|
||||
if (button == nullptr) return;
|
||||
auto text = button->text();
|
||||
if (text == "连接") {
|
||||
auto portName = m_serialComboBox->currentText();
|
||||
auto status = Amass::Singleton<Application>::instance()->open(portName, 2000000);
|
||||
if (status) {
|
||||
m_commandGroupBox->setEnabled(true);
|
||||
button->setText("关闭");
|
||||
}
|
||||
} else if (text == "关闭") {
|
||||
Amass::Singleton<Application>::instance()->close();
|
||||
m_commandGroupBox->setEnabled(false);
|
||||
button->setText("连接");
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::onSerialRefreshButtonClicked() {
|
||||
m_serialComboBox->clear();
|
||||
auto ports = QSerialPortInfo::availablePorts();
|
||||
for (auto &port : ports) {
|
||||
if (port.description() == "蓝牙链接上的标准串行") continue;
|
||||
m_serialComboBox->addItem(port.portName());
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::onUvcRefreshButtonClicked() {
|
||||
}
|
||||
|
||||
void Widget::onEnrollButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
auto name = m_enrollNameEdit->text();
|
||||
auto timeout = m_enrollTimeoutEdit->text().toInt();
|
||||
module->enroll(name.toStdString(), true, timeout);
|
||||
}
|
||||
|
||||
void Widget::onEnrollExButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
auto name = m_enrollNameEdit->text();
|
||||
auto timeout = m_enrollTimeoutEdit->text().toInt();
|
||||
module->enrollExtended(name.toStdString(), true, timeout);
|
||||
}
|
||||
|
||||
void Widget::onVerifyButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
auto timeout = m_verifyTimeoutEdit->text().toInt();
|
||||
module->verify(timeout);
|
||||
}
|
||||
|
||||
void Widget::onDeleteAllButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
module->deleteAll();
|
||||
}
|
||||
|
||||
void Widget::onDeleteButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
auto id = m_deleteIdEdit->text().toInt();
|
||||
module->deleteUser(id);
|
||||
}
|
||||
|
||||
void Widget::onRequestPalmFeatureButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
auto id = m_palmFeatureEdit->text().toInt();
|
||||
}
|
||||
|
||||
void Widget::onRegisterPalmFeatureButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
// auto features = m_database->palmFeatures();
|
||||
// if (features.empty()) {
|
||||
// LOG(error) << "feature is empty.";
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
|
||||
void Widget::onResetButtonClicked() {
|
||||
auto module = Amass::Singleton<Application>::instance()->module();
|
||||
if (!module) return;
|
||||
module->reset();
|
||||
}
|
||||
|
||||
void Widget::onNewLog(const QString &log) {
|
||||
m_logBrowser->append(log);
|
||||
}
|
@ -1,70 +0,0 @@
|
||||
#ifndef WIDGET_H
|
||||
#define WIDGET_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <fstream>
|
||||
|
||||
class QPushButton;
|
||||
class QTextBrowser;
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class QGroupBox;
|
||||
class QTableView;
|
||||
class ModuleCommunication;
|
||||
class PalmFeatureTableModel;
|
||||
class Database;
|
||||
|
||||
class Widget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Widget(QWidget *parent = nullptr);
|
||||
void onNewLog(const QString &log);
|
||||
|
||||
protected:
|
||||
QGroupBox *initializeCommandGroupBox();
|
||||
void onClearLogButtonClicked();
|
||||
void onSerialConnectButtonClicked();
|
||||
void onSerialRefreshButtonClicked();
|
||||
|
||||
void onUvcRefreshButtonClicked();
|
||||
|
||||
void onEnrollButtonClicked();
|
||||
void onEnrollExButtonClicked();
|
||||
void onVerifyButtonClicked();
|
||||
void onDeleteAllButtonClicked();
|
||||
void onDeleteButtonClicked();
|
||||
void onRequestPalmFeatureButtonClicked();
|
||||
void onRegisterPalmFeatureButtonClicked();
|
||||
void onResetButtonClicked();
|
||||
|
||||
QGroupBox *initializeEnrollGroupBox();
|
||||
QGroupBox *initializeVerifyGroupBox();
|
||||
QGroupBox *initializeDeleteGroupBox();
|
||||
QGroupBox *initializePalmFeatureGroupBox();
|
||||
|
||||
QGroupBox *initializeUvcGroupBox();
|
||||
|
||||
private:
|
||||
QComboBox *m_serialComboBox = nullptr;
|
||||
QPushButton *m_serialConnectButton = nullptr;
|
||||
QTextBrowser *m_logBrowser = nullptr;
|
||||
QGroupBox *m_commandGroupBox = nullptr;
|
||||
|
||||
QLineEdit *m_enrollNameEdit = nullptr;
|
||||
QLineEdit *m_enrollTimeoutEdit = nullptr;
|
||||
QPushButton *m_enrollButton = nullptr;
|
||||
|
||||
QLineEdit *m_verifyTimeoutEdit = nullptr;
|
||||
QPushButton *m_verifyButton = nullptr;
|
||||
|
||||
QLineEdit *m_deleteIdEdit = nullptr;
|
||||
QPushButton *m_deleteButton = nullptr;
|
||||
QPushButton *m_deleteAllButton = nullptr;
|
||||
|
||||
QLineEdit *m_palmFeatureEdit = nullptr;
|
||||
|
||||
PalmFeatureTableModel *m_featureModel = nullptr;
|
||||
QTableView *m_featureTableView = nullptr;
|
||||
};
|
||||
|
||||
#endif // WIDGET_H
|
@ -2,7 +2,7 @@
|
||||
#include "BoostLog.h"
|
||||
#include "Configuration.h"
|
||||
#include "DeviceDiscovery.h"
|
||||
#include "Widget.h"
|
||||
#include <QQuickStyle>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
using namespace Amass;
|
||||
@ -10,16 +10,8 @@ int main(int argc, char *argv[]) {
|
||||
LOG(info) << "Compiled on: " << __DATE__ << " " << __TIME__ << std::endl;
|
||||
LOG(info) << "Git commit ID: " << GIT_COMMIT_ID << std::endl;
|
||||
LOG(info) << "Program version: " << APP_VERSION << std::endl;
|
||||
|
||||
QQuickStyle::setStyle("Basic"); // Basic Material
|
||||
auto app = Singleton<Application>::instance<Construct>(argc, argv);
|
||||
app->initializeLogger();
|
||||
|
||||
// Widget w;
|
||||
// w.setWindowTitle("L015上位机工具");
|
||||
// w.setMinimumWidth(1120);
|
||||
// w.setMinimumHeight(640);
|
||||
// w.show();
|
||||
// QObject::connect(app.get(), &Application::newLog, &w, &Widget::onNewLog);
|
||||
|
||||
return app->exec();
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ RowLayout {
|
||||
ComboBox {
|
||||
id: serialPort
|
||||
enabled: !App.connected
|
||||
implicitWidth: 100
|
||||
implicitWidth: 116
|
||||
}
|
||||
|
||||
Text {
|
||||
@ -25,7 +25,7 @@ RowLayout {
|
||||
ComboBox {
|
||||
id: baudrate
|
||||
enabled: !App.connected
|
||||
implicitWidth: 110
|
||||
implicitWidth: 116
|
||||
model: ["2000000", "115200"]
|
||||
}
|
||||
|
||||
|
@ -1,17 +1,19 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
import Fluent as Fluent
|
||||
import Analyser
|
||||
|
||||
Window {
|
||||
width: 1120
|
||||
height: 770
|
||||
id: window
|
||||
width: 1220
|
||||
height: 890
|
||||
visible: true
|
||||
title: qsTr(Qt.application.name + " " + Qt.application.version)
|
||||
|
||||
OperationItem {
|
||||
id: operationItem
|
||||
width: 450
|
||||
width: 510
|
||||
anchors.top: parent.top
|
||||
}
|
||||
|
||||
@ -98,22 +100,29 @@ Window {
|
||||
}
|
||||
}
|
||||
|
||||
Fluent.InfoBar{
|
||||
id:info_bar
|
||||
root: window
|
||||
layoutY: 10
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: App
|
||||
function onNewLog(text) {
|
||||
logBrowser.append(text)
|
||||
}
|
||||
function onNewStatusTip(level, tip) {
|
||||
if (level === 0) {
|
||||
statusTip.icon = "../resources/successfull.svg"
|
||||
statusTip.color = "#EBF8ED"
|
||||
statusTip.show(tip, 2000)
|
||||
function onNewStatusTip(level, tip, detailMessage) {
|
||||
if (level === App.Tip) {
|
||||
info_bar.showSuccess(tip,2000,detailMessage)
|
||||
} else if (level === App.Warnging) {
|
||||
info_bar.showWarning(tip,2000,detailMessage)
|
||||
} else if (level === 1) {
|
||||
statusTip.icon = "../resources/warning.svg"
|
||||
statusTip.color = "#FAFAD2"
|
||||
statusTip.show(tip, 2000)
|
||||
} else if (level === 2) {
|
||||
resultBrowser.append(tip)
|
||||
info_bar.showInfo(tip,2000,detailMessage)
|
||||
resultBrowser.append(tip+":"+detailMessage)
|
||||
}
|
||||
}
|
||||
function onNewVideoFrame() {
|
||||
@ -121,11 +130,4 @@ Window {
|
||||
image.source = "image://videoframe/"
|
||||
}
|
||||
}
|
||||
|
||||
StatusTip {
|
||||
id: statusTip
|
||||
width: 200
|
||||
height: 50
|
||||
icon: "../resources/successfull.svg"
|
||||
}
|
||||
}
|
||||
|
@ -32,23 +32,29 @@ Item {
|
||||
title: "注册用户"
|
||||
GridLayout {
|
||||
columns: 2
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("用户姓名")
|
||||
}
|
||||
TextField {
|
||||
id: enrollName
|
||||
implicitWidth: 100
|
||||
}
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("严格模式")
|
||||
}
|
||||
Switch {
|
||||
id: strictMode
|
||||
}
|
||||
Label {
|
||||
text: qsTr("超时时间")
|
||||
}
|
||||
TextField {
|
||||
id: enrollTimeout
|
||||
implicitWidth: 100
|
||||
text: "10"
|
||||
text: "30"
|
||||
}
|
||||
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("持久化")
|
||||
}
|
||||
Switch {
|
||||
@ -56,7 +62,7 @@ Item {
|
||||
checked: true
|
||||
}
|
||||
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("保存图片")
|
||||
}
|
||||
Switch {
|
||||
@ -70,14 +76,9 @@ Item {
|
||||
if (enrolling) {
|
||||
App.module.reset()
|
||||
} else if (extendedMode.checked) {
|
||||
App.enrollExtended(
|
||||
enrollName.text,
|
||||
persistence.checked,
|
||||
parseInt(enrollTimeout.text))
|
||||
App.enrollExtended(enrollName.text, strictMode.checked, persistence.checked, parseInt(enrollTimeout.text))
|
||||
} else {
|
||||
App.enroll(enrollName.text,
|
||||
persistence.checked,
|
||||
parseInt(enrollTimeout.text))
|
||||
App.enroll(enrollName.text, strictMode.checked, persistence.checked, parseInt(enrollTimeout.text))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -87,7 +88,7 @@ Item {
|
||||
title: "识别用户"
|
||||
GridLayout {
|
||||
columns: 2
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("超时时间(s)")
|
||||
}
|
||||
TextField {
|
||||
@ -95,20 +96,20 @@ Item {
|
||||
implicitWidth: 80
|
||||
text: "10"
|
||||
}
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("持续识别")
|
||||
}
|
||||
Switch {
|
||||
checked: App.persistenceMode
|
||||
onToggled: App.persistenceMode = !App.persistenceMode
|
||||
}
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("保存图片")
|
||||
}
|
||||
Switch {
|
||||
id: extendedVerifyMode
|
||||
}
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("识别间隔(s)")
|
||||
}
|
||||
TextField {
|
||||
@ -132,11 +133,13 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Column {
|
||||
GroupBox {
|
||||
title: "删除用户"
|
||||
GridLayout {
|
||||
columns: 2
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("用户ID")
|
||||
}
|
||||
TextField {
|
||||
@ -155,46 +158,8 @@ Item {
|
||||
}
|
||||
}
|
||||
GroupBox {
|
||||
title: "图片注册"
|
||||
visible: true
|
||||
GridLayout {
|
||||
columns: 2
|
||||
TextField {
|
||||
id: imagePath
|
||||
Layout.columnSpan: 2
|
||||
implicitWidth: 200
|
||||
placeholderText: "请选择图片"
|
||||
onPressed: {
|
||||
fileDialog.open()
|
||||
}
|
||||
}
|
||||
Text {
|
||||
text: qsTr("用户姓名")
|
||||
}
|
||||
TextField {
|
||||
id: imageEnrollName
|
||||
implicitWidth: 100
|
||||
text: "测试下发"
|
||||
}
|
||||
Text {
|
||||
text: qsTr("循环")
|
||||
}
|
||||
Switch {
|
||||
checked: App.imageUploadPersistenceMode
|
||||
onToggled: {
|
||||
App.imageUploadPersistenceMode = checked
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "注册"
|
||||
onClicked: App.uploadImage(imagePath.text,imageEnrollName.text, 0)
|
||||
}
|
||||
Button {
|
||||
text: "识别"
|
||||
onClicked: App.uploadImage(imagePath.text,imageEnrollName.text, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "复位"
|
||||
onClicked: App.module.reset()
|
||||
@ -213,7 +178,7 @@ Item {
|
||||
onClicked: loader.active = true
|
||||
}
|
||||
Row {
|
||||
Text {
|
||||
Label {
|
||||
text: qsTr("日志")
|
||||
}
|
||||
Switch {
|
||||
@ -224,6 +189,50 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
GroupBox {
|
||||
title: "图片注册"
|
||||
visible: true
|
||||
GridLayout {
|
||||
columns: 2
|
||||
TextField {
|
||||
id: imagePath
|
||||
Layout.columnSpan: 2
|
||||
implicitWidth: 200
|
||||
placeholderText: "请选择图片"
|
||||
onPressed: {
|
||||
fileDialog.open()
|
||||
}
|
||||
}
|
||||
Label {
|
||||
text: qsTr("用户姓名")
|
||||
}
|
||||
TextField {
|
||||
id: imageEnrollName
|
||||
implicitWidth: 100
|
||||
text: "测试下发"
|
||||
}
|
||||
Label {
|
||||
text: qsTr("循环")
|
||||
}
|
||||
Switch {
|
||||
checked: App.imageUploadPersistenceMode
|
||||
onToggled: {
|
||||
App.imageUploadPersistenceMode = checked
|
||||
}
|
||||
}
|
||||
Button {
|
||||
text: "注册"
|
||||
onClicked: App.uploadImage(imagePath.text,imageEnrollName.text, 0)
|
||||
}
|
||||
Button {
|
||||
text: "识别"
|
||||
onClicked: App.uploadImage(imagePath.text,imageEnrollName.text, 1)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
FileDialog {
|
||||
id: fileDialog
|
||||
nameFilters: ["图片 (*.jpg *.yuv)"]
|
||||
|
@ -1,56 +0,0 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
|
||||
Popup{
|
||||
id: control
|
||||
property alias text: textItem.text
|
||||
property alias icon: image.source
|
||||
property alias color: back.color
|
||||
property string borderColor
|
||||
x: (parent.width-200)/2
|
||||
y: 40
|
||||
width: 200
|
||||
height: 32
|
||||
font.pixelSize: 16
|
||||
contentItem: Row{
|
||||
leftPadding: 4
|
||||
spacing: 9.6
|
||||
Image {
|
||||
id: image
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
Text {
|
||||
id: textItem
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: control.text
|
||||
font: control.font
|
||||
color: "#666666"
|
||||
}
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
id:back
|
||||
anchors.fill: parent
|
||||
color: "#EBF8ED"
|
||||
radius: 3.2
|
||||
border.width: 1
|
||||
border.color: control.borderColor
|
||||
layer.enabled: true
|
||||
}
|
||||
|
||||
Timer {
|
||||
id: timer
|
||||
repeat: false
|
||||
onTriggered: control.visible=false
|
||||
}
|
||||
|
||||
|
||||
function show(text,timeout){
|
||||
control.text = text
|
||||
timer.interval = timeout
|
||||
timer.restart();
|
||||
control.visible=true
|
||||
}
|
||||
|
||||
}
|
@ -61,7 +61,7 @@ HOST_TOOLS := /opt/Xuantie-900-gcc-elf-newlib-x86_64-V2.6.1/bin
|
||||
|
||||
# 编译OTA固件,11为OTA版本号,这个版本号只做固件文件名显示。
|
||||
# 实际的版本设置在 cv181x_alios/solutions/smart_doorbell/package.yaml.L015_V200R002
|
||||
./rebuild-app-ota.sh y L015 V200 R002 02
|
||||
./rebuild-app-ota.sh y L015 V200 R002 03
|
||||
600X800
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user