#ifndef MODULECOMMUNICATION_H #define MODULECOMMUNICATION_H #include "DataStructure.h" #include #include #include class ModuleCommunication : public QObject { Q_OBJECT static constexpr uint32_t UsernameSize = 32; static constexpr const char *Separator = "----------"; public: constexpr static uint16_t InvalidUserId = std::numeric_limits::max(); enum MessageId : uint8_t { Reply = 0, Note = 0x01, Reset = 0x10, Verify = 0x12, EnrollSingle = 0x1D, EnrollGetImage = 0x1E, GetEnrolledImage = 0x1F, DeleteUser = 0x20, DeleteAll = 0x21, RegisterPalmFeature = 0xF9, RequestPalmFeature = 0xFA, Idle = 0xFF, }; enum NoteId : uint8_t { Ready = 0x00, PalmState = 0x01, UnknownError = 0x02, }; 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 EnrolledImageReply { uint8_t image_format; // 0: 只有Y分量,灰度图 uint16_t width; uint16_t height; uint8_t md5[16]; }; struct ImageSliceRequest { uint32_t offset; uint32_t size; }; struct ImageSliceReply { uint32_t size; uint8_t data[0]; }; struct VerifyDataReply { uint16_t userid; uint8_t username[UsernameSize]; // 32Bytes uint8_t admin; uint8_t unlockStatus; }; struct PalmFeatureHeader { uint16_t userid; // 用户ID uint8_t username[32]; // 用户姓名 uint8_t admin; // 是否管理员,YES:1 NO:0 uint8_t featureDataMd5[16]; // 整体特征数据的MD5值 uint16_t featureTotalSize; // 特征数据总长度 uint8_t feature[0]; }; #pragma pack() explicit ModuleCommunication(QObject *parent = nullptr); bool open(const QString &portName, int baudRate); Q_INVOKABLE void verify(uint8_t timeout); Q_INVOKABLE void reset(); void enroll(const std::string &username, uint8_t timeout); void enrollEx(const std::string &username, uint8_t timeout); Q_INVOKABLE void deleteUser(uint16_t userid); Q_INVOKABLE void deleteAll(); void requestEnrolledImage(uint32_t offset, uint32_t size); void requestPalmFeature(uint16_t userid); void enrollPalmFeature(uint16_t userid, const PalmFeature &feature); MessageId currentMessageId() const; signals: void newVerifyResult(uint16_t userid, const QString &username); void newPalmFeature(const PalmFeature &feature); void newEnrolledImageInfo(uint32_t size, const uint8_t *md5); void newImageSliceData(const std::vector &data); void errorOccurred(const QString &error); void commandStarted(ModuleCommunication::MessageId messageId); void commandFinished(MessageId messageId, MessageStatus status); protected: void processPackage(const uint8_t *data, uint16_t size); void onReadyRead(); void onErrorOccurred(QSerialPort::SerialPortError error); std::pair generateFrame(MessageId command, const uint8_t *data = nullptr, uint16_t size = 0); std::string protocolDataFormatString(const uint8_t *data, int size); private: std::shared_ptr m_serialPort; QByteArray m_receivedBuffer; MessageId m_currentMessageId = ModuleCommunication::Idle; }; #endif // MODULECOMMUNICATION_H