1.所有模块验证完成。
This commit is contained in:
parent
89ae5b9e16
commit
8660c10742
@ -13,6 +13,7 @@ add_executable(Analyser Analyser.rc
|
|||||||
|
|
||||||
target_link_libraries(Analyser
|
target_link_libraries(Analyser
|
||||||
PRIVATE QtComponets
|
PRIVATE QtComponets
|
||||||
|
PRIVATE Encrypt
|
||||||
PRIVATE Database
|
PRIVATE Database
|
||||||
PRIVATE Ws2_32
|
PRIVATE Ws2_32
|
||||||
PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
|
PRIVATE Qt${QT_VERSION_MAJOR}::Widgets
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "BoostLog.h"
|
#include "BoostLog.h"
|
||||||
#include <QSerialPort>
|
#include <QSerialPort>
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
|
#include <mbedtls/md5.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
static inline uint8_t xor_checksum_byte(const uint8_t *data, uint32_t len) {
|
static inline uint8_t xor_checksum_byte(const uint8_t *data, uint32_t len) {
|
||||||
@ -38,6 +39,13 @@ void ModuleCommunication::verify(uint8_t timeout) {
|
|||||||
LOG_CAT(info, GUI) << Separator;
|
LOG_CAT(info, GUI) << Separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleCommunication::reset() {
|
||||||
|
auto [frameData, frameSize] = generateFrame(Reset);
|
||||||
|
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) {
|
void ModuleCommunication::enroll(const std::string &username, uint8_t timeout) {
|
||||||
EnrollData data = {0};
|
EnrollData data = {0};
|
||||||
data.timeout = timeout;
|
data.timeout = timeout;
|
||||||
@ -75,6 +83,33 @@ void ModuleCommunication::requestPalmFeature(uint16_t userid) {
|
|||||||
LOG_CAT(info, GUI) << Separator;
|
LOG_CAT(info, GUI) << Separator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModuleCommunication::enrollPalmFeature(uint16_t userid, const PalmFeature &feature) {
|
||||||
|
auto buffer = new uint8_t[sizeof(PalmFeatureHeader) + feature.feature.size()];
|
||||||
|
auto header = reinterpret_cast<PalmFeatureHeader *>(buffer);
|
||||||
|
header->userid = htons(userid);
|
||||||
|
header->featureTotalSize = htons(feature.feature.size());
|
||||||
|
strncpy(reinterpret_cast<char *>(header->username), feature.username.c_str(), sizeof(header->username));
|
||||||
|
|
||||||
|
mbedtls_md5_context context;
|
||||||
|
mbedtls_md5_init(&context);
|
||||||
|
mbedtls_md5_starts(&context);
|
||||||
|
uint8_t md5[16];
|
||||||
|
mbedtls_md5_update(&context, feature.feature.data(), feature.feature.size());
|
||||||
|
mbedtls_md5_finish(&context, md5);
|
||||||
|
mbedtls_md5_free(&context);
|
||||||
|
memcpy(header->featureDataMd5, md5, sizeof(header->featureDataMd5));
|
||||||
|
|
||||||
|
memcpy(buffer + sizeof(PalmFeatureHeader), feature.feature.data(), feature.feature.size());
|
||||||
|
|
||||||
|
auto [frameData, frameSize] =
|
||||||
|
generateFrame(RegisterPalmFeature, buffer, sizeof(PalmFeatureHeader) + feature.feature.size());
|
||||||
|
m_serialPort->write(reinterpret_cast<const char *>(frameData), frameSize);
|
||||||
|
LOG_CAT(info, GUI) << "发送注册掌静脉特征指令: " << protocolDataFormatString(frameData, frameSize);
|
||||||
|
LOG_CAT(info, GUI) << Separator;
|
||||||
|
|
||||||
|
if (buffer != nullptr) delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
|
void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
|
||||||
uint8_t messageId = data[2];
|
uint8_t messageId = data[2];
|
||||||
switch (messageId) {
|
switch (messageId) {
|
||||||
@ -82,33 +117,38 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
|
|||||||
uint8_t replyId = data[5];
|
uint8_t replyId = data[5];
|
||||||
auto result = data[6];
|
auto result = data[6];
|
||||||
switch (replyId) {
|
switch (replyId) {
|
||||||
case Verify: {
|
case Reset: {
|
||||||
|
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
||||||
|
if (result == Success) {
|
||||||
|
LOG_CAT(info, GUI) << "复位完成。";
|
||||||
|
}
|
||||||
|
LOG_CAT(info, GUI) << Separator;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case Verify: {
|
||||||
|
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
||||||
if (result == Success) {
|
if (result == Success) {
|
||||||
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
|
||||||
auto info = reinterpret_cast<const VerifyDataReply *>(data + 7);
|
auto info = reinterpret_cast<const VerifyDataReply *>(data + 7);
|
||||||
LOG_CAT(info, GUI) << "用户ID: " << ntohs(info->userid)
|
LOG_CAT(info, GUI) << "用户ID: " << ntohs(info->userid)
|
||||||
<< ", 用户名: " << std::string_view(reinterpret_cast<const char *>(info->username));
|
<< ", 用户名: " << std::string_view(reinterpret_cast<const char *>(info->username));
|
||||||
LOG_CAT(info, GUI) << Separator;
|
|
||||||
} else if (result == Failed4Timeout) {
|
} else if (result == Failed4Timeout) {
|
||||||
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
|
||||||
LOG_CAT(info, GUI) << "识别超时。";
|
LOG_CAT(info, GUI) << "识别超时。";
|
||||||
LOG_CAT(info, GUI) << Separator;
|
|
||||||
} else if (result == Failed4UnknownReason) {
|
} else if (result == Failed4UnknownReason) {
|
||||||
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
|
||||||
LOG_CAT(info, GUI) << "未录入用户。";
|
LOG_CAT(info, GUI) << "未录入用户。";
|
||||||
LOG_CAT(info, GUI) << Separator;
|
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
|
LOG_CAT(info, GUI) << Separator;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case EnrollSingle: {
|
case EnrollSingle: {
|
||||||
|
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
||||||
if (result == Success) {
|
if (result == Success) {
|
||||||
auto info = reinterpret_cast<const EnrollDataReply *>(data + 7);
|
auto info = reinterpret_cast<const EnrollDataReply *>(data + 7);
|
||||||
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
|
||||||
LOG_CAT(info, GUI) << "注册成功,用户ID: " << ntohs(info->userid);
|
LOG_CAT(info, GUI) << "注册成功,用户ID: " << ntohs(info->userid);
|
||||||
LOG_CAT(info, GUI) << Separator;
|
} else if (result == Failed4Timeout) {
|
||||||
|
LOG_CAT(info, GUI) << "识别超时。";
|
||||||
}
|
}
|
||||||
|
LOG_CAT(info, GUI) << Separator;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DeleteUser: {
|
case DeleteUser: {
|
||||||
@ -147,6 +187,14 @@ void ModuleCommunication::processPackage(const uint8_t *data, uint16_t size) {
|
|||||||
LOG_CAT(info, GUI) << Separator;
|
LOG_CAT(info, GUI) << Separator;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case RegisterPalmFeature: {
|
||||||
|
LOG_CAT(info, GUI) << "模组: " << protocolDataFormatString(data, size);
|
||||||
|
if (result == Success) {
|
||||||
|
LOG_CAT(info, GUI) << "掌静脉特征值注册成功。";
|
||||||
|
}
|
||||||
|
LOG_CAT(info, GUI) << Separator;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
LOG(warning) << "unknown reply command: 0x" << (static_cast<int>(replyId) & 0xff)
|
LOG(warning) << "unknown reply command: 0x" << (static_cast<int>(replyId) & 0xff)
|
||||||
<< ", data: " << protocolDataFormatString(data, size);
|
<< ", data: " << protocolDataFormatString(data, size);
|
||||||
|
@ -16,6 +16,7 @@ public:
|
|||||||
enum MessageId : uint8_t {
|
enum MessageId : uint8_t {
|
||||||
Reply = 0,
|
Reply = 0,
|
||||||
Note = 0x01,
|
Note = 0x01,
|
||||||
|
Reset = 0x10,
|
||||||
Verify = 0x12,
|
Verify = 0x12,
|
||||||
EnrollSingle = 0x1D,
|
EnrollSingle = 0x1D,
|
||||||
DeleteUser = 0x20,
|
DeleteUser = 0x20,
|
||||||
@ -94,12 +95,14 @@ public:
|
|||||||
explicit ModuleCommunication(QObject *parent = nullptr);
|
explicit ModuleCommunication(QObject *parent = nullptr);
|
||||||
bool open(const QString &portName);
|
bool open(const QString &portName);
|
||||||
void verify(uint8_t timeout);
|
void verify(uint8_t timeout);
|
||||||
|
void reset();
|
||||||
|
|
||||||
void enroll(const std::string &username, uint8_t timeout);
|
void enroll(const std::string &username, uint8_t timeout);
|
||||||
void deleteUser(uint16_t userid);
|
void deleteUser(uint16_t userid);
|
||||||
void deleteAll();
|
void deleteAll();
|
||||||
|
|
||||||
void requestPalmFeature(uint16_t userid);
|
void requestPalmFeature(uint16_t userid);
|
||||||
|
void enrollPalmFeature(uint16_t userid, const PalmFeature &feature);
|
||||||
signals:
|
signals:
|
||||||
void newPalmFeature(const PalmFeature &feature);
|
void newPalmFeature(const PalmFeature &feature);
|
||||||
|
|
||||||
|
@ -95,6 +95,10 @@ QGroupBox *Widget::initializeCommandGroupBox() {
|
|||||||
layout->addWidget(initializeDeleteGroupBox(), 1, 0);
|
layout->addWidget(initializeDeleteGroupBox(), 1, 0);
|
||||||
layout->addWidget(initializePalmFeatureGroupBox(), 1, 1);
|
layout->addWidget(initializePalmFeatureGroupBox(), 1, 1);
|
||||||
|
|
||||||
|
auto resetButton = new QPushButton("复位");
|
||||||
|
connect(resetButton, &QPushButton::clicked, this, &Widget::onResetButtonClicked);
|
||||||
|
layout->addWidget(resetButton, 2, 0);
|
||||||
|
|
||||||
ret->setLayout(layout);
|
ret->setLayout(layout);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -159,13 +163,14 @@ QGroupBox *Widget::initializePalmFeatureGroupBox() {
|
|||||||
m_palmFeatureEdit = new QLineEdit("");
|
m_palmFeatureEdit = new QLineEdit("");
|
||||||
layout->addRow("用户ID:", m_palmFeatureEdit);
|
layout->addRow("用户ID:", m_palmFeatureEdit);
|
||||||
|
|
||||||
auto button = new QPushButton("特征值下发");
|
|
||||||
layout->addRow("", button);
|
|
||||||
|
|
||||||
auto button1 = new QPushButton("特征值上报");
|
auto button1 = new QPushButton("特征值上报");
|
||||||
layout->addRow("", button1);
|
layout->addRow("", button1);
|
||||||
connect(button1, &QPushButton::clicked, this, &Widget::onRequestPalmFeatureButtonClicked);
|
connect(button1, &QPushButton::clicked, this, &Widget::onRequestPalmFeatureButtonClicked);
|
||||||
|
|
||||||
|
auto button = new QPushButton("特征值下发");
|
||||||
|
connect(button, &QPushButton::clicked, this, &Widget::onRegisterPalmFeatureButtonClicked);
|
||||||
|
layout->addRow("", button);
|
||||||
|
|
||||||
ret->setLayout(layout);
|
ret->setLayout(layout);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -258,3 +263,18 @@ void Widget::onRequestPalmFeatureButtonClicked() {
|
|||||||
auto id = m_palmFeatureEdit->text().toInt();
|
auto id = m_palmFeatureEdit->text().toInt();
|
||||||
m_communication->requestPalmFeature(id);
|
m_communication->requestPalmFeature(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::onRegisterPalmFeatureButtonClicked() {
|
||||||
|
if (!m_communication) return;
|
||||||
|
auto features = m_database->palmFeatures();
|
||||||
|
if (features.empty()) {
|
||||||
|
LOG(error) << "feature is empty.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_communication->enrollPalmFeature(264, features.at(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::onResetButtonClicked() {
|
||||||
|
if (!m_communication) return;
|
||||||
|
m_communication->reset();
|
||||||
|
}
|
||||||
|
@ -30,6 +30,8 @@ protected:
|
|||||||
void onDeleteAllButtonClicked();
|
void onDeleteAllButtonClicked();
|
||||||
void onDeleteButtonClicked();
|
void onDeleteButtonClicked();
|
||||||
void onRequestPalmFeatureButtonClicked();
|
void onRequestPalmFeatureButtonClicked();
|
||||||
|
void onRegisterPalmFeatureButtonClicked();
|
||||||
|
void onResetButtonClicked();
|
||||||
|
|
||||||
QGroupBox *initializeEnrollGroupBox();
|
QGroupBox *initializeEnrollGroupBox();
|
||||||
QGroupBox *initializeVerifyGroupBox();
|
QGroupBox *initializeVerifyGroupBox();
|
||||||
|
@ -19,6 +19,7 @@ add_subdirectory(${Projects_ROOT}/Kylin/Universal Universal)
|
|||||||
add_subdirectory(${Projects_ROOT}/Kylin/Encrypt Encrypt)
|
add_subdirectory(${Projects_ROOT}/Kylin/Encrypt Encrypt)
|
||||||
add_subdirectory(${Projects_ROOT}/Kylin/QtComponets QtComponets)
|
add_subdirectory(${Projects_ROOT}/Kylin/QtComponets QtComponets)
|
||||||
|
|
||||||
|
add_subdirectory(Peripheral)
|
||||||
add_subdirectory(Database)
|
add_subdirectory(Database)
|
||||||
add_subdirectory(Analyser)
|
add_subdirectory(Analyser)
|
||||||
add_subdirectory(OtaUpdate)
|
add_subdirectory(OtaUpdate)
|
||||||
|
@ -7,7 +7,6 @@ find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets SerialPort)
|
|||||||
set(PROJECT_SOURCES OtaUpdate.rc
|
set(PROJECT_SOURCES OtaUpdate.rc
|
||||||
main.cpp
|
main.cpp
|
||||||
CdcUpdater.h CdcUpdater.cpp
|
CdcUpdater.h CdcUpdater.cpp
|
||||||
DeviceDiscovery.h DeviceDiscovery.cpp
|
|
||||||
Widget.cpp
|
Widget.cpp
|
||||||
Widget.h
|
Widget.h
|
||||||
)
|
)
|
||||||
@ -18,7 +17,7 @@ qt_add_executable(SmartLockerUpdater
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(SmartLockerUpdater
|
target_link_libraries(SmartLockerUpdater
|
||||||
PRIVATE Universal
|
PRIVATE Peripheral
|
||||||
PRIVATE Encrypt
|
PRIVATE Encrypt
|
||||||
PRIVATE mfplat
|
PRIVATE mfplat
|
||||||
PRIVATE mfuuid
|
PRIVATE mfuuid
|
||||||
|
11
Peripheral/CMakeLists.txt
Normal file
11
Peripheral/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
add_library(Peripheral
|
||||||
|
DeviceDiscovery.h DeviceDiscovery.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(Peripheral
|
||||||
|
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(Peripheral
|
||||||
|
PUBLIC Universal
|
||||||
|
)
|
@ -1,4 +1,4 @@
|
|||||||
## 串口配置
|
## 1 串口配置
|
||||||
|
|
||||||
- 波特率:115200
|
- 波特率:115200
|
||||||
- 数据位:8
|
- 数据位:8
|
||||||
@ -6,7 +6,7 @@
|
|||||||
- 奇偶检验:无
|
- 奇偶检验:无
|
||||||
- 流控制:无
|
- 流控制:无
|
||||||
|
|
||||||
## 消息格式
|
## 2 消息格式
|
||||||
|
|
||||||
主控和模块通讯的基本格式如下表所示,字节序为 **大端字节序(Big Endian)**:
|
主控和模块通讯的基本格式如下表所示,字节序为 **大端字节序(Big Endian)**:
|
||||||
|
|
||||||
@ -24,28 +24,40 @@
|
|||||||
| Data | N bytes | 消息(MsgID)对应的数据内容,长度 N 为 DataSize 。<br/>0表示此消息无参数 |
|
| Data | N bytes | 消息(MsgID)对应的数据内容,长度 N 为 DataSize 。<br/>0表示此消息无参数 |
|
||||||
| ParityCheck | 1 byte | 协议的奇偶检验码。<br/>去除SyncWord,对 MsgID、DataSize、Data 的内容字节做XOR运算 |
|
| ParityCheck | 1 byte | 协议的奇偶检验码。<br/>去除SyncWord,对 MsgID、DataSize、Data 的内容字节做XOR运算 |
|
||||||
|
|
||||||
## 消息列表
|
## 3 消息列表
|
||||||
|
|
||||||
| MsgID | Code | 说明 |
|
| MsgID | Code | 说明 |
|
||||||
| ----------------------- | ---- | ------------------------------------------------------------ |
|
| ----------------------- | ---- | ------------------------------------------------------------ |
|
||||||
| MID_REPLY | 0x00 | 模组对主控发送出的命令的应答,对于主控下发的每条命令,模组最终都会使用 MID_REPLY 进行结果应答上报 |
|
| MID_REPLY | 0x00 | 模组对主控发送出的命令的应答,对于主控下发的每条命令,模组最终都会使用 MID_REPLY 进行结果应答上报 |
|
||||||
| MID_NOTE | 0x01 | 摸组主动上报给主控的信息,根据 NID 判断消息类型和对应的 Data 结构(详细内容见下文) |
|
| MID_NOTE | 0x01 | 摸组主动上报给主控的信息,根据 NID 判断消息类型和对应的 Data 结构(详细内容见下文) |
|
||||||
|
| MID_RESET | 0x10 | 主控下发,用于打断模组当前执行的任务 |
|
||||||
| MID_VERIFY | 0x12 | 掌静脉识别比对 |
|
| MID_VERIFY | 0x12 | 掌静脉识别比对 |
|
||||||
| MID_ENROLL_SINGLE | 0x1D | 掌静脉录入(单帧) |
|
| MID_ENROLL_SINGLE | 0x1D | 掌静脉录入(单帧) |
|
||||||
| MID_DELUSER | 0x20 | 删除一个已注册的掌静脉 |
|
| MID_DELUSER | 0x20 | 删除一个已录入的掌静脉 |
|
||||||
| MID_DELALL | 0x21 | 删除所有已注册的掌静脉 |
|
| MID_DELALL | 0x21 | 删除所有已录入的掌静脉 |
|
||||||
| MID_ENROLL_PALM_FEATUTE | 0xF9 | 主控下发掌静脉特征值给模组进行注册 |
|
| MID_ENROLL_PALM_FEATUTE | 0xF9 | 主控下发掌静脉特征值给模组进行录入 |
|
||||||
| MID_GET_PALM_FEATUTE | 0xFA | 主控请求获取指定用户掌静脉特征值 |
|
| MID_GET_PALM_FEATUTE | 0xFA | 主控请求获取指定用户掌静脉特征值 |
|
||||||
|
|
||||||
### 设备初始化完成
|
### 3.1 设备初始化完成
|
||||||
|
|
||||||
模组上电初始化完成后,会通过串口向主控发送一条 NID 为 NID_READY 的 MID_NOTE 消息: 0xEF 0xAA 0x01 0x00 0x01 0x00 0x00。(消息详细解释见 `模组状态上报(MID_NOTE)`)。
|
模组上电初始化完成后,会通过串口向主控发送一条 NID 为 NID_READY 的 MID_NOTE 消息: 0xEF 0xAA 0x01 0x00 0x01 0x00 0x00。(消息详细解释见 `模组状态上报(MID_NOTE)`)。
|
||||||
|
|
||||||
主机在接收到握手信号后,可以和模组进行指令交互。
|
主控在接收到 MID_NOTE 信息后,可以和模组进行指令交互。
|
||||||
|
|
||||||
### 掌静脉识别(MID_VERIFY)
|
### 3.2 模组复位(MID_RESET)
|
||||||
|
|
||||||
主控下发该指令给模组,模组开始识别掌静脉进行比对,指令下发携带的参数 msg_verify_data 定义如下:
|
模组同一时刻,只能执行一个任务,当模组在执行耗时长的任务时(例如掌静脉识别 MID_VERIFY),主控可以向模组下发 MID_RESET 打断取消当前任务,进而再去执行其它任务。
|
||||||
|
|
||||||
|
该指令无需携带参数。
|
||||||
|
|
||||||
|
指令执行结束后,通过消息 MID_REPLY 返回结果:
|
||||||
|
|
||||||
|
- 0x00(MR_SUCCESS):复位成功
|
||||||
|
- 0x05(MR_FAILED4_UNKNOWNREASON):未知错误
|
||||||
|
|
||||||
|
### 3.3 掌静脉识别(MID_VERIFY)
|
||||||
|
|
||||||
|
主控下发该指令给模组,模组开始检测摄像头图像中的掌静脉,并和底库中的掌静脉进行比对。指令下发携带的参数 msg_verify_data 定义如下:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
struct msg_verify_data {
|
struct msg_verify_data {
|
||||||
@ -56,7 +68,7 @@ struct msg_verify_data {
|
|||||||
|
|
||||||
参数说明:
|
参数说明:
|
||||||
|
|
||||||
- pd_rightaway:表示是否在识别完成后立刻关机(预留参数),默认设 00。
|
- pd_rightaway:保留,暂未使用。可设置为 0x00。
|
||||||
- timeout:识别超时时间,默认为10s,用户可以自行设置(最大不超过255s)。**主控等待模组录入应答的超时时间应大于此参数设置值。**
|
- timeout:识别超时时间,默认为10s,用户可以自行设置(最大不超过255s)。**主控等待模组录入应答的超时时间应大于此参数设置值。**
|
||||||
|
|
||||||
主控下发消息格式如下:
|
主控下发消息格式如下:
|
||||||
@ -117,7 +129,7 @@ struct msg_reply_verify_data {
|
|||||||
<th rowspan="3">MsgID</th>
|
<th rowspan="3">MsgID</th>
|
||||||
<th rowspan="3">DataSize</th>
|
<th rowspan="3">DataSize</th>
|
||||||
<th colspan="6">Data</th>
|
<th colspan="6">Data</th>
|
||||||
<th>ParityCheck</th>
|
<th rowspan="2">ParityCheck</th>
|
||||||
</tr>
|
</tr>
|
||||||
<td>RID</td>
|
<td>RID</td>
|
||||||
<td>Result</td>
|
<td>Result</td>
|
||||||
@ -139,8 +151,8 @@ struct msg_reply_verify_data {
|
|||||||
<td>0x26</td>
|
<td>0x26</td>
|
||||||
<td>MID_VERIFY<br/>(0x12)</td>
|
<td>MID_VERIFY<br/>(0x12)</td>
|
||||||
<td>Result<br/>(1 byte)</td>
|
<td>Result<br/>(1 byte)</td>
|
||||||
<td>user_id<br/>(2 byte)</td>
|
<td>user_id<br/>(2 bytes)</td>
|
||||||
<td>username<br/>(32 byte)</td>
|
<td>username<br/>(32 bytes)</td>
|
||||||
<td>admin<br/>(1 byte)</td>
|
<td>admin<br/>(1 byte)</td>
|
||||||
<td>unlockStatus<br/>(1 byte)</td>
|
<td>unlockStatus<br/>(1 byte)</td>
|
||||||
<td> </td>
|
<td> </td>
|
||||||
@ -148,9 +160,10 @@ struct msg_reply_verify_data {
|
|||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
### 掌静脉注册(MID_ENROLL_SINGLE)
|
|
||||||
|
|
||||||
掌静脉注册指令下发携带的参数 `msg_enroll_data` 定义如下:
|
### 3.4 掌静脉录入(MID_ENROLL_SINGLE)
|
||||||
|
|
||||||
|
掌静脉录入指令下发携带的参数 `msg_enroll_data` 定义如下:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
struct msg_enroll_data {
|
struct msg_enroll_data {
|
||||||
@ -163,7 +176,7 @@ struct msg_enroll_data {
|
|||||||
|
|
||||||
参数说明:
|
参数说明:
|
||||||
|
|
||||||
- admin:设置该录入的掌静脉人员为管理员。
|
- admin:设置该录入的掌静脉人员为管理员。0:非管理员,1:管理员。
|
||||||
- username:录入用户的用户名。
|
- username:录入用户的用户名。
|
||||||
- palm_direction:保留,暂未使用。可设置为 0x00。
|
- palm_direction:保留,暂未使用。可设置为 0x00。
|
||||||
- timeout:录入过程的超时时间(s),默认为10s,用户可以自行设置(最大不超过255s)。**主控等待模组录入应答的超时时间应大于此参数设置值。**
|
- timeout:录入过程的超时时间(s),默认为10s,用户可以自行设置(最大不超过255s)。**主控等待模组录入应答的超时时间应大于此参数设置值。**
|
||||||
@ -184,7 +197,7 @@ struct msg_reply_enroll_data {
|
|||||||
- user_id:用户 ID 每次录入都会增加 1,即使删除某个 ID 后,再次录入 ID 会继续增加,直至 65530,ID 变为 0。
|
- user_id:用户 ID 每次录入都会增加 1,即使删除某个 ID 后,再次录入 ID 会继续增加,直至 65530,ID 变为 0。
|
||||||
- face_direction:保留,暂未使用。
|
- face_direction:保留,暂未使用。
|
||||||
|
|
||||||
### 删除单个掌静脉(MID_DELUSER)
|
### 3.5 删除单个掌静脉(MID_DELUSER)
|
||||||
|
|
||||||
通过传入用户 ID, 删除指定 ID 的单个用户。
|
通过传入用户 ID, 删除指定 ID 的单个用户。
|
||||||
|
|
||||||
@ -206,9 +219,9 @@ struct msg_deluser_data {
|
|||||||
- 0x05(MR_FAILED4_UNKNOWNREASON):未知错误
|
- 0x05(MR_FAILED4_UNKNOWNREASON):未知错误
|
||||||
- 0x08(MR_FAILED4_UNKNOWNUSER):删除的用户ID不存在
|
- 0x08(MR_FAILED4_UNKNOWNUSER):删除的用户ID不存在
|
||||||
|
|
||||||
### 删除所有掌静脉(MID_DELALL)
|
### 3.6 删除所有掌静脉(MID_DELALL)
|
||||||
|
|
||||||
删除所有已注册的用户。
|
删除所有已录入的用户。
|
||||||
|
|
||||||
该指令无需携带参数。
|
该指令无需携带参数。
|
||||||
|
|
||||||
@ -217,11 +230,11 @@ struct msg_deluser_data {
|
|||||||
- 0x00(MR_SUCCESS):删除成功
|
- 0x00(MR_SUCCESS):删除成功
|
||||||
- 0x05(MR_FAILED4_UNKNOWNREASON):未知错误
|
- 0x05(MR_FAILED4_UNKNOWNREASON):未知错误
|
||||||
|
|
||||||
### 掌静脉特征值注册(MID_ENROLL_PALM_FEATUTE)
|
### 3.7 掌静脉特征值录入(MID_ENROLL_PALM_FEATUTE)
|
||||||
|
|
||||||
该命令用于直接将掌静脉特征值下发给模组进行注册。
|
该命令用于直接将掌静脉特征值下发给模组进行录入。
|
||||||
|
|
||||||
下发掌静脉特征值注册携带的参数 msg_palm_feature_enroll_data 如下:
|
下发掌静脉特征值录入携带的参数 msg_palm_feature_enroll_data 如下:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
struct msg_palm_feature_enroll_data {
|
struct msg_palm_feature_enroll_data {
|
||||||
@ -245,12 +258,12 @@ struct msg_palm_feature_enroll_data {
|
|||||||
|
|
||||||
指令执行结束后,通过消息 MID_REPLY 返回结果(主控等待应答超时时间建议设置为 5s):
|
指令执行结束后,通过消息 MID_REPLY 返回结果(主控等待应答超时时间建议设置为 5s):
|
||||||
|
|
||||||
- 0x00(MR_SUCCESS):注册成功
|
- 0x00(MR_SUCCESS):录入成功
|
||||||
- 0x05(MR_FAILED4_UNKNOWNREASON):未知错误
|
- 0x05(MR_FAILED4_UNKNOWNREASON):未知错误
|
||||||
|
|
||||||
### 获取掌静脉特征值(MID_GET_PALM_FEATUTE)
|
### 3.8 获取掌静脉特征值(MID_GET_PALM_FEATUTE)
|
||||||
|
|
||||||
该命令用于获取对应已注册用户的掌静脉特征值,携带参数 msg_get_palm_feature_data 如下:
|
该命令用于获取对应已录入用户的掌静脉特征值,携带参数 msg_get_palm_feature_data 如下:
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
struct msg_get_palm_feature_data {
|
struct msg_get_palm_feature_data {
|
||||||
@ -273,11 +286,11 @@ struct msg_palm_feature_enroll_data {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
参数定义见 `掌静脉特征值注册(MID_ENROLL_PALM_FEATUTE)` 携带参数的参数定义说明。
|
参数定义见 `掌静脉特征值录入(MID_ENROLL_PALM_FEATUTE)` 携带参数的参数定义说明。
|
||||||
|
|
||||||
### 命令结果上报(MID_REPLY)
|
### 3.9 命令结果上报(MID_REPLY)
|
||||||
|
|
||||||
模组向主控发送的 MID_NOTE 消息的完整协议如下所示:
|
模组向主控发送的 MID_REPLY 消息的完整协议如下所示:
|
||||||
|
|
||||||
<table align="center">
|
<table align="center">
|
||||||
<tr align="center">
|
<tr align="center">
|
||||||
@ -305,7 +318,7 @@ struct msg_palm_feature_enroll_data {
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
RID表示模组当前正在处理的任务,例如当 RID 为 MID_ENROLL_SINGLE 是,表示该消息是模组处理完单帧录入任务后回复的消息。
|
RID表示模组当前正在处理的任务,例如当 RID 为 MID_ENROLL_SINGLE 时,表示该消息是模组处理完掌静脉录入任务后回复的消息。
|
||||||
|
|
||||||
消息对应的 ResultData 会在主控下发命令(例如 MID_ENROLL_SINGLE )中进行介绍。
|
消息对应的 ResultData 会在主控下发命令(例如 MID_ENROLL_SINGLE )中进行介绍。
|
||||||
|
|
||||||
@ -332,7 +345,7 @@ Result 表示该命令的最终执行结果,详细如下表所示。
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 模组状态上报(MID_NOTE)
|
### 3.10 模组状态上报(MID_NOTE)
|
||||||
|
|
||||||
MID_NOTE 消息主要作用是主动向主控上报一些信息,报文格式如下:
|
MID_NOTE 消息主要作用是主动向主控上报一些信息,报文格式如下:
|
||||||
|
|
||||||
@ -341,14 +354,14 @@ MID_NOTE 消息主要作用是主动向主控上报一些信息,报文格式
|
|||||||
<th>SyncWord</th>
|
<th>SyncWord</th>
|
||||||
<th>MsgID</th>
|
<th>MsgID</th>
|
||||||
<th>DataSize</th>
|
<th>DataSize</th>
|
||||||
<th colspan="3">Data</th>
|
<th colspan="2">Data</th>
|
||||||
<th>ParityCheck</th>
|
<th>ParityCheck</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr align="center">
|
<tr align="center">
|
||||||
<td>2 bytes</td>
|
<td>2 bytes</td>
|
||||||
<td>1 byte</td>
|
<td>1 byte</td>
|
||||||
<td>2 bytes</td>
|
<td>2 bytes</td>
|
||||||
<td colspan="3">N bytes</td>
|
<td colspan="2">N bytes</td>
|
||||||
<td>1 byte</td>
|
<td>1 byte</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr align="center">
|
<tr align="center">
|
||||||
@ -361,13 +374,44 @@ MID_NOTE 消息主要作用是主动向主控上报一些信息,报文格式
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
目前NID主要内容如下:
|
目前NID主要内容如下:
|
||||||
|
|
||||||
| NID(*表示该消息携带 NoteData 数据) | Code | 说明 |
|
| NID(*表示该消息携带 NoteData 数据) | Code | 说明 |
|
||||||
| ------------------------------------ | ---- | -------------------- |
|
| ------------------------------------ | ---- | -------------------- |
|
||||||
| NID_READY | 0x00 | 模组已上电初始化成功 |
|
| NID_READY | 0x00 | 模组已上电初始化成功 |
|
||||||
|
|
||||||
## 示例报文
|
## 4 示例报文
|
||||||
|
|
||||||
|
- 掌静脉录入
|
||||||
|
|
||||||
|
录入 admin为0,username为 test 的用户,超时时间 10s,主控发送:
|
||||||
|
|
||||||
|
0xef 0xaa 0x1d 0x00 0x23 0x00 0x74 0x65 0x73 0x74 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x0a 0x22
|
||||||
|
|
||||||
|
录入成功,ID为1,模组上报:
|
||||||
|
|
||||||
|
0xef 0xaa 0x00 0x00 0x05 0x1d 0x00 0x00 0x01 0x00 0x19
|
||||||
|
|
||||||
|
- 掌静脉识别
|
||||||
|
|
||||||
|
开始识别比对,超时时间20s,主控发送:
|
||||||
|
|
||||||
|
0xef 0xaa 0x12 0x00 0x02 0x00 0x14 0x04
|
||||||
|
|
||||||
|
识别比对成功,user_id为1,username为amass,admin为0,模组上报:
|
||||||
|
|
||||||
|
0xef 0xaa 0x00 0x00 0x26 0x12 0x00 0x00 0x01 0x74 0x65 0x73 0x74 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0xc8 0xeb
|
||||||
|
|
||||||
|
- 删除所有录入掌静脉
|
||||||
|
|
||||||
|
主控发送:
|
||||||
|
|
||||||
|
0xef 0xaa 0x21 0x00 0x00 0x21
|
||||||
|
|
||||||
|
删除成功,模组上报:
|
||||||
|
|
||||||
|
0xef 0xaa 0x00 0x00 0x02 0x21 0x00 0x23
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user