1.添加上位机工具。
This commit is contained in:
61
Analyser/Analyser.rc
Normal file
61
Analyser/Analyser.rc
Normal file
@ -0,0 +1,61 @@
|
||||
// Microsoft Visual C++ generated resource script.
|
||||
//
|
||||
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
#include "winres.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// 中文(简体,中国) resources
|
||||
|
||||
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
|
||||
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
|
||||
#pragma code_page(936)
|
||||
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// TEXTINCLUDE
|
||||
//
|
||||
|
||||
2 TEXTINCLUDE BEGIN "#include "
|
||||
"winres.h"
|
||||
"\r\n"
|
||||
"\0" END
|
||||
|
||||
3 TEXTINCLUDE BEGIN "\r\n"
|
||||
"\0" END
|
||||
|
||||
#endif // APSTUDIO_INVOKED
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Icon
|
||||
//
|
||||
|
||||
// Icon with lowest ID value placed first to ensure application icon
|
||||
// remains consistent on all systems.
|
||||
IDI_ICON1 ICON "..\\resources\\logo.ico"
|
||||
|
||||
#endif // 中文(简体,中国) resources
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
#ifndef APSTUDIO_INVOKED
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
20
Analyser/CMakeLists.txt
Normal file
20
Analyser/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets SerialPort)
|
||||
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets SerialPort)
|
||||
|
||||
add_executable(Analyser Analyser.rc
|
||||
main.cpp
|
||||
CategoryLogSinkBackend.h CategoryLogSinkBackend.cpp
|
||||
Widget.h Widget.cpp
|
||||
ModuleCommunication.h ModuleCommunication.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(Analyser
|
||||
PRIVATE Universal
|
||||
PRIVATE QtComponets
|
||||
PRIVATE Ws2_32
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
|
||||
PRIVATE Qt${QT_VERSION_MAJOR}::SerialPort
|
||||
)
|
15
Analyser/CategoryLogSinkBackend.cpp
Normal file
15
Analyser/CategoryLogSinkBackend.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
#include "CategoryLogSinkBackend.h"
|
||||
#include "AsyncEvent.h"
|
||||
#include <QTextBrowser>
|
||||
#include <iostream>
|
||||
|
||||
CategoryLogSinkBackend::CategoryLogSinkBackend(const std::string &category, QTextBrowser *target)
|
||||
: m_category(category), m_target(target) {
|
||||
}
|
||||
|
||||
void CategoryLogSinkBackend::consume(const boost::log::record_view &record, string_type const &output) {
|
||||
auto &&category = record[AmassKeywords::category];
|
||||
if (category == m_category) {
|
||||
Amass::executeAtObjectThread(m_target, [this, output]() { m_target->append(QString::fromStdString(output)); });
|
||||
}
|
||||
}
|
20
Analyser/CategoryLogSinkBackend.h
Normal file
20
Analyser/CategoryLogSinkBackend.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __CATEGORYLOGSINKBACKEND_H__
|
||||
#define __CATEGORYLOGSINKBACKEND_H__
|
||||
|
||||
#include <boost/log/sinks.hpp>
|
||||
#include <string>
|
||||
|
||||
class QTextBrowser;
|
||||
|
||||
class CategoryLogSinkBackend
|
||||
: public boost::log::sinks::basic_formatted_sink_backend<char, boost::log::sinks::synchronized_feeding> {
|
||||
public:
|
||||
CategoryLogSinkBackend(const std::string &category, QTextBrowser *target);
|
||||
void consume(const boost::log::record_view &record, string_type const &output);
|
||||
|
||||
private:
|
||||
std::string m_category;
|
||||
QTextBrowser *m_target = nullptr;
|
||||
};
|
||||
|
||||
#endif // __CATEGORYLOGSINKBACKEND_H__
|
204
Analyser/ModuleCommunication.cpp
Normal file
204
Analyser/ModuleCommunication.cpp
Normal file
@ -0,0 +1,204 @@
|
||||
#include "ModuleCommunication.h"
|
||||
#include "BoostLog.h"
|
||||
#include <QSerialPort>
|
||||
#include <WinSock2.h>
|
||||
#include <sstream>
|
||||
|
||||
static inline uint8_t xor_checksum_byte(const uint8_t *data, uint32_t len) {
|
||||
uint8_t sum = 0;
|
||||
for (uint32_t i = 0; i < len; ++i) {
|
||||
sum ^= data[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
ModuleCommunication::ModuleCommunication(QObject *parent) : QObject{parent} {
|
||||
}
|
||||
|
||||
bool ModuleCommunication::open(const QString &portName) {
|
||||
bool ret = true;
|
||||
m_serialPort = std::make_shared<QSerialPort>(portName);
|
||||
m_serialPort->setBaudRate(QSerialPort::Baud115200);
|
||||
connect(m_serialPort.get(), &QSerialPort::readyRead, this, &ModuleCommunication::onReadyRead);
|
||||
|
||||
ret = m_serialPort->open(QSerialPort::ReadWrite);
|
||||
LOG_CAT(info, GUI) << "打开串口(" << portName.toStdString() << ")" << (ret ? "成功" : "失败") << "。";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ModuleCommunication::verify(uint8_t timeout) {
|
||||
VerifyInfo data = {0};
|
||||
data.timeout = timeout;
|
||||
|
||||
auto [frameData, frameSize] = generateFrame(Verify, reinterpret_cast<const uint8_t *>(&data), sizeof(data));
|
||||
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
|
||||
|
||||
LOG_CAT(info, GUI) << "发送识别指令: " << protocolDataFormatString(frameData, frameSize);
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
|
||||
void ModuleCommunication::enroll(const std::string &username, uint8_t timeout) {
|
||||
EnrollData data = {0};
|
||||
data.timeout = timeout;
|
||||
strncpy(reinterpret_cast<char *>(data.username), username.c_str(), sizeof(data.username));
|
||||
auto [frameData, frameSize] = generateFrame(EnrollSingle, reinterpret_cast<const uint8_t *>(&data), sizeof(data));
|
||||
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
|
||||
|
||||
LOG_CAT(info, GUI) << "发送注册指令: " << protocolDataFormatString(frameData, frameSize);
|
||||
LOG_CAT(info, GUI) << "用户名: " << username << ", 超时时间: " << static_cast<int>(timeout) << "s";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
|
||||
void ModuleCommunication::deleteUser(uint16_t userid) {
|
||||
uint16_t n = htons(userid);
|
||||
auto [frameData, frameSize] = generateFrame(DeleteUser, reinterpret_cast<const uint8_t *>(&n), sizeof(n));
|
||||
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
|
||||
LOG_CAT(info, GUI) << "发送删除用户指令: " << protocolDataFormatString(frameData, frameSize);
|
||||
LOG_CAT(info, GUI) << "删除用户ID: " << userid;
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
|
||||
void ModuleCommunication::deleteAll() {
|
||||
auto [frameData, frameSize] = generateFrame(DeleteAll);
|
||||
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
|
||||
LOG_CAT(info, GUI) << "发送删除所有指令: " << protocolDataFormatString(frameData, frameSize);
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
|
||||
void ModuleCommunication::onReadyRead() {
|
||||
auto data = m_serialPort->readAll();
|
||||
if (data.size() < 6) {
|
||||
LOG(warning) << "invalid data: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
return;
|
||||
}
|
||||
uint8_t messageId = data[2];
|
||||
switch (messageId) {
|
||||
case Reply: {
|
||||
uint8_t replyId = data[5];
|
||||
auto result = data[6];
|
||||
switch (replyId) {
|
||||
case Verify: {
|
||||
if (result == Success) {
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()),
|
||||
data.size());
|
||||
auto info = reinterpret_cast<VerifyDataReply *>(data.data() + 7);
|
||||
LOG_CAT(info, GUI) << "用户ID: " << ntohs(info->userid)
|
||||
<< ", 用户名: " << std::string_view(reinterpret_cast<const char *>(info->username));
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
} else if (result == Failed4Timeout) {
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()),
|
||||
data.size());
|
||||
LOG_CAT(info, GUI) << "识别超时。";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
} else if (result == Failed4UnknownReason) {
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()),
|
||||
data.size());
|
||||
LOG_CAT(info, GUI) << "未录入用户。";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
} else {
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case EnrollSingle: {
|
||||
if (result == Success) {
|
||||
auto info = reinterpret_cast<EnrollDataReply *>(data.data() + 7);
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()),
|
||||
data.size());
|
||||
LOG_CAT(info, GUI) << "注册成功,用户ID: " << ntohs(info->userid);
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DeleteUser: {
|
||||
if (result == Success) {
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()),
|
||||
data.size());
|
||||
LOG_CAT(info, GUI) << "删除用户成功。";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
} else {
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()),
|
||||
data.size());
|
||||
LOG_CAT(info, GUI) << "删除用户失败。";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DeleteAll: {
|
||||
if (result == Success) {
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()),
|
||||
data.size());
|
||||
LOG_CAT(info, GUI) << "删除所有用户成功。";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(warning) << "unknown reply command: 0x" << (static_cast<int>(replyId) & 0xff) << ", data: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Note: {
|
||||
uint8_t noteId = data[5];
|
||||
switch (noteId) {
|
||||
case Ready: {
|
||||
LOG_CAT(info, GUI) << "模组: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
LOG_CAT(info, GUI) << "模组上电初始化成功。";
|
||||
LOG_CAT(info, GUI) << Separator;
|
||||
break;
|
||||
}
|
||||
case 0x01: { // 模组返回的数据为当前帧的手掌状态
|
||||
auto info = reinterpret_cast<VerifyNoteInfo *>(data.data() + 7);
|
||||
LOG(info) << info->state;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(warning) << "unknown note command: 0x" << (static_cast<int>(noteId) & 0xff) << ", data: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(warning) << "unknown command: 0x" << (static_cast<int>(data[2]) & 0xff) << ", data: "
|
||||
<< protocolDataFormatString(reinterpret_cast<const uint8_t *>(data.data()), data.size());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::pair<uint8_t *, uint32_t> ModuleCommunication::generateFrame(MessageId command, const uint8_t *data,
|
||||
uint16_t size) {
|
||||
static uint8_t sendBuffer[1024] = {0};
|
||||
memset(sendBuffer, 0, sizeof(sendBuffer));
|
||||
sendBuffer[0] = 0xef;
|
||||
sendBuffer[1] = 0xaa;
|
||||
sendBuffer[2] = command;
|
||||
sendBuffer[3] = size >> 8;
|
||||
sendBuffer[4] = size & 0xff;
|
||||
if (size > 0) {
|
||||
memcpy(sendBuffer + 5, data, size);
|
||||
}
|
||||
sendBuffer[5 + size] = xor_checksum_byte(sendBuffer + 2, 3 + size);
|
||||
return std::make_pair(sendBuffer, size + 6);
|
||||
}
|
||||
|
||||
std::string ModuleCommunication::protocolDataFormatString(const uint8_t *data, int size) {
|
||||
std::ostringstream oss;
|
||||
for (int i = 0; i < size; i++) {
|
||||
oss << "0x" << std::hex << (static_cast<int>(data[i]) & 0xff) << " ";
|
||||
}
|
||||
return oss.str();
|
||||
}
|
100
Analyser/ModuleCommunication.h
Normal file
100
Analyser/ModuleCommunication.h
Normal file
@ -0,0 +1,100 @@
|
||||
#ifndef MODULECOMMUNICATION_H
|
||||
#define MODULECOMMUNICATION_H
|
||||
|
||||
#include <QObject>
|
||||
#include <memory>
|
||||
|
||||
class QSerialPort;
|
||||
|
||||
class ModuleCommunication : public QObject {
|
||||
Q_OBJECT
|
||||
static constexpr uint32_t UsernameSize = 32;
|
||||
static constexpr const char *Separator = "----------";
|
||||
|
||||
public:
|
||||
enum MessageId : uint8_t {
|
||||
Reply = 0,
|
||||
Note = 0x01,
|
||||
Verify = 0x12,
|
||||
EnrollSingle = 0x1D,
|
||||
DeleteUser = 0x20,
|
||||
DeleteAll = 0x21,
|
||||
};
|
||||
|
||||
enum NoteId : uint8_t {
|
||||
Ready = 0x00,
|
||||
};
|
||||
enum MessageStatus : uint8_t {
|
||||
Success = 0,
|
||||
Rejected = 1,
|
||||
Aborted = 2,
|
||||
Failed4Camera = 4,
|
||||
Failed4UnknownReason = 5,
|
||||
Failed4InvalidParam = 6,
|
||||
Failed4NoMemory = 7,
|
||||
Failed4UnknownUser = 8,
|
||||
Failed4MaxUser = 9,
|
||||
Failed4FaceEnrolled = 10,
|
||||
Failed4LivenessCheck = 12,
|
||||
Failed4Timeout = 13,
|
||||
Failed4Authorization = 14,
|
||||
Failed4ReadFile = 19,
|
||||
Failed4WriteFile = 20,
|
||||
Failed4NoEncrypt = 21,
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct VerifyInfo {
|
||||
uint8_t powerDownRightAway; // power down right away after verifying
|
||||
uint8_t timeout; // timeout, unit second, default 10s
|
||||
};
|
||||
struct VerifyNoteInfo {
|
||||
int16_t state; // corresponding to PALM_STATE_*
|
||||
// position
|
||||
int16_t left; // in pixel
|
||||
int16_t top;
|
||||
int16_t right;
|
||||
int16_t bottom;
|
||||
// pose
|
||||
int16_t yaw; // up and down in vertical orientation
|
||||
int16_t pitch; // right or left turned in horizontal orientation
|
||||
int16_t roll; // slope
|
||||
};
|
||||
|
||||
struct EnrollData {
|
||||
uint8_t admin = 0;
|
||||
uint8_t username[32];
|
||||
uint8_t palmDirection;
|
||||
uint8_t timeout;
|
||||
};
|
||||
|
||||
struct EnrollDataReply {
|
||||
uint16_t userid;
|
||||
uint8_t face_direction; // depleted, user ignore this field
|
||||
};
|
||||
|
||||
struct VerifyDataReply {
|
||||
uint16_t userid;
|
||||
uint8_t username[UsernameSize]; // 32Bytes uint8_t admin;
|
||||
uint8_t unlockStatus;
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
explicit ModuleCommunication(QObject *parent = nullptr);
|
||||
bool open(const QString &portName);
|
||||
void verify(uint8_t timeout);
|
||||
|
||||
void enroll(const std::string &username, uint8_t timeout);
|
||||
void deleteUser(uint16_t userid);
|
||||
void deleteAll();
|
||||
|
||||
protected:
|
||||
void onReadyRead();
|
||||
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;
|
||||
};
|
||||
|
||||
#endif // MODULECOMMUNICATION_H
|
221
Analyser/Widget.cpp
Normal file
221
Analyser/Widget.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
#include "Widget.h"
|
||||
#include "BoostLog.h"
|
||||
#include "CategoryLogSinkBackend.h"
|
||||
#include "ModuleCommunication.h"
|
||||
#include <QComboBox>
|
||||
#include <QFormLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QSerialPortInfo>
|
||||
#include <QTabWidget>
|
||||
#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 uvcGroupBox = new QGroupBox("UVC设置");
|
||||
auto uvcLayout = new QGridLayout();
|
||||
label = new QLabel("设备名");
|
||||
uvcLayout->addWidget(label, 0, 0);
|
||||
|
||||
label = new QLabel("未发现设备");
|
||||
uvcLayout->addWidget(label, 0, 1);
|
||||
|
||||
auto uvcRefreshButton = new QPushButton("刷新");
|
||||
auto uvcConnectButton = new QPushButton("连接");
|
||||
uvcLayout->addWidget(uvcRefreshButton, 1, 0);
|
||||
uvcLayout->addWidget(uvcConnectButton, 1, 1);
|
||||
uvcGroupBox->setLayout(uvcLayout);
|
||||
|
||||
auto connectLayout = new QHBoxLayout();
|
||||
connectLayout->addWidget(serialGroupBox);
|
||||
connectLayout->addWidget(uvcGroupBox);
|
||||
|
||||
m_logBrowser = new QTextBrowser();
|
||||
m_logBrowser->setReadOnly(true);
|
||||
|
||||
auto tabWidget = new QTabWidget();
|
||||
tabWidget->addTab(m_logBrowser, "日志");
|
||||
tabWidget->addTab(new QWidget(), "视频流");
|
||||
tabWidget->addTab(new QWidget(), "已注册列表");
|
||||
|
||||
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);
|
||||
|
||||
QTimer::singleShot(0, this, [this]() {
|
||||
onSerialRefreshButtonClicked();
|
||||
m_commandGroupBox->setEnabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
void Widget::initializeLogger() {
|
||||
auto backend = boost::make_shared<CategoryLogSinkBackend>("GUI", m_logBrowser);
|
||||
using SynchronousCategorySink = boost::log::sinks::synchronous_sink<CategoryLogSinkBackend>;
|
||||
auto sink = boost::make_shared<SynchronousCategorySink>(backend);
|
||||
// sink->set_formatter(&zlogFormatter);
|
||||
boost::log::core::get()->add_sink(sink);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
ret->setLayout(layout);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
auto edit = new QLineEdit("");
|
||||
layout->addRow("用户ID:", edit);
|
||||
|
||||
auto button = new QPushButton("特征值下发");
|
||||
layout->addRow("", button);
|
||||
|
||||
auto button1 = new QPushButton("特征值上报");
|
||||
layout->addRow("", button1);
|
||||
|
||||
ret->setLayout(layout);
|
||||
|
||||
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();
|
||||
m_communication = std::make_shared<ModuleCommunication>();
|
||||
bool status = m_communication->open(portName);
|
||||
if (status) {
|
||||
m_commandGroupBox->setEnabled(true);
|
||||
button->setText("关闭");
|
||||
}
|
||||
} else if (text == "关闭") {
|
||||
m_communication.reset();
|
||||
m_commandGroupBox->setEnabled(false);
|
||||
button->setText("连接");
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::onSerialRefreshButtonClicked() {
|
||||
m_serialComboBox->clear();
|
||||
auto ports = QSerialPortInfo::availablePorts();
|
||||
for (auto &port : ports) {
|
||||
m_serialComboBox->addItem(port.portName());
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::onEnrollButtonClicked() {
|
||||
auto name = m_enrollNameEdit->text();
|
||||
auto timeout = m_enrollTimeoutEdit->text().toInt();
|
||||
m_communication->enroll(name.toStdString(), timeout);
|
||||
}
|
||||
|
||||
void Widget::onVerifyButtonClicked() {
|
||||
if (!m_communication) return;
|
||||
auto timeout = m_verifyTimeoutEdit->text().toInt();
|
||||
m_communication->verify(timeout);
|
||||
}
|
||||
|
||||
void Widget::onDeleteAllButtonClicked() {
|
||||
if (!m_communication) return;
|
||||
m_communication->deleteAll();
|
||||
}
|
||||
|
||||
void Widget::onDeleteButtonClicked() {
|
||||
if (!m_communication) return;
|
||||
auto id = m_deleteIdEdit->text().toInt();
|
||||
m_communication->deleteUser(id);
|
||||
}
|
54
Analyser/Widget.h
Normal file
54
Analyser/Widget.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef WIDGET_H
|
||||
#define WIDGET_H
|
||||
|
||||
#include "qgroupbox.h"
|
||||
#include <QWidget>
|
||||
|
||||
class QPushButton;
|
||||
class QTextBrowser;
|
||||
class QComboBox;
|
||||
class QLineEdit;
|
||||
class ModuleCommunication;
|
||||
|
||||
class Widget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Widget(QWidget *parent = nullptr);
|
||||
void initializeLogger();
|
||||
|
||||
protected:
|
||||
QGroupBox *initializeCommandGroupBox();
|
||||
void onSerialConnectButtonClicked();
|
||||
void onSerialRefreshButtonClicked();
|
||||
|
||||
void onEnrollButtonClicked();
|
||||
void onVerifyButtonClicked();
|
||||
void onDeleteAllButtonClicked();
|
||||
void onDeleteButtonClicked();
|
||||
|
||||
QGroupBox *initializeEnrollGroupBox();
|
||||
QGroupBox *initializeVerifyGroupBox();
|
||||
QGroupBox *initializeDeleteGroupBox();
|
||||
QGroupBox *initializePalmFeatureGroupBox();
|
||||
|
||||
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;
|
||||
|
||||
std::shared_ptr<ModuleCommunication> m_communication;
|
||||
};
|
||||
|
||||
#endif // WIDGET_H
|
21
Analyser/main.cpp
Normal file
21
Analyser/main.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include "BoostLog.h"
|
||||
#include "Widget.h"
|
||||
#include <QApplication>
|
||||
#include <QFont>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
boost::log::initialize("logs/app");
|
||||
|
||||
QApplication a(argc, argv);
|
||||
QFont font;
|
||||
font.setPointSize(16);
|
||||
a.setFont(font);
|
||||
Widget w;
|
||||
w.initializeLogger();
|
||||
w.setWindowTitle("L015上位机工具");
|
||||
w.setMinimumWidth(1120);
|
||||
w.setMinimumHeight(640);
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
Reference in New Issue
Block a user