From 32493833fbfc67b079a85e41811051dd44a7e5d4 Mon Sep 17 00:00:00 2001 From: dorababu <dorababu@subcom.tech> Date: Sat, 23 Jul 2022 10:57:32 +0530 Subject: [PATCH] Moved to here from key repo --- FingerPrintMatching/include/DFRobot_ID809.h | 494 ++++++++ FingerPrintMatching/platformio.ini | 12 + FingerPrintMatching/src/DFRobot_ID809.cpp | 748 +++++++++++ FingerPrintMatching/src/src.cpp | 107 ++ FingerPrintRegister/include/DFRobot_ID809.h | 494 ++++++++ FingerPrintRegister/platformio.ini | 11 + FingerPrintRegister/src/DFRobot_ID809.cpp | 748 +++++++++++ FingerPrintRegister/src/src.cpp | 132 ++ FingerPrintUnregister/include/DFRobot_ID809.h | 494 ++++++++ FingerPrintUnregister/platformio.ini | 9 + FingerPrintUnregister/src/DFRobot_ID809.cpp | 748 +++++++++++ FingerPrintUnregister/src/platformio.ini | 0 FingerPrintUnregister/src/src.cpp | 110 ++ .../lib/DFRobot_ID809/DFRobot_ID809.cpp | 1089 +++++++++++++++++ .../lib/DFRobot_ID809/DFRobot_ID809.h | 504 ++++++++ RegFPwithHash/platformio.ini | 12 + RegFPwithHash/src/src.cpp | 216 ++++ .../lib/DFRobot_ID809/DFRobot_ID809.cpp | 1089 +++++++++++++++++ .../lib/DFRobot_ID809/DFRobot_ID809.h | 504 ++++++++ matchFPandHash/platformio.ini | 13 + matchFPandHash/src/src.cpp | 178 +++ .../lib/DFRobot_ID809/DFRobot_ID809.cpp | 1089 +++++++++++++++++ .../lib/DFRobot_ID809/DFRobot_ID809.h | 504 ++++++++ readTemplate/platformio.ini | 13 + readTemplate/src/src.cpp | 192 +++ 25 files changed, 9510 insertions(+) create mode 100644 FingerPrintMatching/include/DFRobot_ID809.h create mode 100644 FingerPrintMatching/platformio.ini create mode 100644 FingerPrintMatching/src/DFRobot_ID809.cpp create mode 100644 FingerPrintMatching/src/src.cpp create mode 100644 FingerPrintRegister/include/DFRobot_ID809.h create mode 100644 FingerPrintRegister/platformio.ini create mode 100644 FingerPrintRegister/src/DFRobot_ID809.cpp create mode 100644 FingerPrintRegister/src/src.cpp create mode 100644 FingerPrintUnregister/include/DFRobot_ID809.h create mode 100644 FingerPrintUnregister/platformio.ini create mode 100644 FingerPrintUnregister/src/DFRobot_ID809.cpp create mode 100644 FingerPrintUnregister/src/platformio.ini create mode 100644 FingerPrintUnregister/src/src.cpp create mode 100644 RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.cpp create mode 100644 RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.h create mode 100644 RegFPwithHash/platformio.ini create mode 100644 RegFPwithHash/src/src.cpp create mode 100644 matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.cpp create mode 100644 matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.h create mode 100644 matchFPandHash/platformio.ini create mode 100644 matchFPandHash/src/src.cpp create mode 100644 readTemplate/lib/DFRobot_ID809/DFRobot_ID809.cpp create mode 100644 readTemplate/lib/DFRobot_ID809/DFRobot_ID809.h create mode 100644 readTemplate/platformio.ini create mode 100644 readTemplate/src/src.cpp diff --git a/FingerPrintMatching/include/DFRobot_ID809.h b/FingerPrintMatching/include/DFRobot_ID809.h new file mode 100644 index 0000000..4cb90d9 --- /dev/null +++ b/FingerPrintMatching/include/DFRobot_ID809.h @@ -0,0 +1,494 @@ +/*! + * @file DFRobot_ID809.h + * @brief Define basic structure of DFRobot_ID809 class + * @n This is an library for capacitive fingerprint module + * @n Main functions: fingerprint image capturing, fingerprint comparison, fingerprint deletion + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#ifndef _DFRobot_ID809_H +#define _DFRobot_ID809_H + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif +#include <Wire.h> + +#include <stdint.h> + +//Open this macro to see the detailed running process of the program + +//#define ENABLE_DBG +#ifdef ENABLE_DBG +#define LDBG(...) if(dbg) {dbg->print("["); dbg->print(__FUNCTION__); dbg->print("(): "); dbg->print(__LINE__); dbg->print(" ] "); dbg->println(__VA_ARGS__);} +#else +#define LDBG(...) +#endif + +extern Stream *dbg; + + /* + Frame struct of command packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t CMD; + uint16_t LEN; + uint8_t payload[0]; +}__attribute__ ((packed)) sCmdPacketHeader_t, *pCmdPacketHeader_t; + + /* + Frame struct of response packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t RCM; + uint16_t LEN; + uint16_t RET; + uint8_t payload[0]; +}__attribute__ ((packed)) sRcmPacketHeader_t, *pRcmPacketHeader_t; + + + + +class DFRobot_ID809{ +public: + +#define FINGERPRINT_CAPACITY 80 //Fingerprint module capacity +#define MODULE_SN_SIZE 16 //Module SN length + + +#define DELALL 0xFF //Delete all fingerprints + +#define CMD_PREFIX_CODE 0xAA55 //Command packet prefix code +#define RCM_PREFIX_CODE 0x55AA //Response packet prefix code +#define CMD_DATA_PREFIX_CODE 0xA55A //Command data packet prefix code +#define RCM_DATA_PREFIX_CODE 0x5AA5 //Response data packet prefix code + +#define CMD_TYPE 0xF0 //Command packet type +#define RCM_TYPE 0xF0 //Response packet type +#define DATA_TYPE 0x0F //Data packet type + +#define CMD_TEST_CONNECTION 0X0001 //Test connection +#define CMD_SET_PARAM 0X0002 //Set parameter +#define CMD_GET_PARAM 0X0003 //Read parameter +#define CMD_DEVICE_INFO 0X0004 //Read device information +#define CMD_SET_MODULE_SN 0X0008 //Set module serial number +#define CMD_GET_MODULE_SN 0X0009 //Read module serial number +#define CMD_ENTER_STANDBY_STATE 0X000C //Enter sleep mode +#define CMD_GET_IMAGE 0X0020 //Capture fingerprint image +#define CMD_FINGER_DETECT 0X0021 //Detect fingerprint + #define CMD_UP_IMAGE_CODE 0X0022 //Upload fingerprint image to host + #define CMD_DOWN_IMAGE 0X0023 //Download fingerprint image to module +#define CMD_SLED_CTRL 0X0024 //Control collector backlight +#define CMD_STORE_CHAR 0X0040 //Save fingerprint template data into fingerprint library +#define CMD_LOAD_CHAR 0X0041 //Read fingerprint in module and save it in RAMBUFFER temporarily + #define CMD_UP_CHAR 0X0042 //Upload the fingerprint template saved in RAMBUFFER to host + #define CMD_DOWN_CHAR 0X0043 //Download fingerprint template to module designated RAMBUFFER +#define CMD_DEL_CHAR 0X0044 //Delete fingerprint in specific ID range +#define CMD_GET_EMPTY_ID 0X0045 //Get the first registerable ID in specific ID range +#define CMD_GET_STATUS 0X0046 //Check if the designated ID has been registered +#define CMD_GET_BROKEN_ID 0X0047 //Check whether there is damaged data in fingerprint library of specific range +#define CMD_GET_ENROLL_COUNT 0X0048 //Get the number of registered fingerprints in specific ID range +#define CMD_GET_ENROLLED_ID_LIST 0X0049 //Get registered ID list +#define CMD_GENERATE 0X0060 //Generate template from the fingerprint images saved in IMAGEBUFFER temporarily +#define CMD_MERGE 0X0061 //Synthesize fingerprint template data +#define CMD_MATCH 0X0062 //Compare templates in 2 designated RAMBUFFER +#define CMD_SEARCH 0X0063 //1:N Recognition in specific ID range +#define CMD_VERIFY 0X0064 //Compare specific RAMBUFFER template with specific ID template in fingerprint library + +#define ERR_SUCCESS 0x00 //Command processed successfully +#define ERR_ID809 0xFF //error + + +public: + + typedef enum{ + eBreathing = 1, //Breathing + eFastBlink, //Quick blink + eKeepsOn, //On + eNormalClose, //Off + eFadeIn, //Fade in + eFadeOut, //Fade out + eSlowBlink //Slow blink + }eLEDMode_t; + + typedef enum{ + eLEDGreen = 1, //green + eLEDRed, //red + eLEDYellow, //yellow + eLEDBlue, //blue + eLEDCyan, //cyan + eLEDMagenta, //magenta + eLEDWhite //white + }eLEDColor_t; + + typedef enum{ + e9600bps = 1, + e19200bps, + e38400bps, + e57600bps, + e115200bps + }eDeviceBaudrate_t; + + typedef enum{ + eErrorSuccess = 0x00, //Command processed successfully + eErrorFail = 0x01, //Command processing failed + eErrorVerify = 0x10, //1:1 Templates comparison in specific ID failed + eErrorIdentify = 0x11, //1:N comparison has been made, no same templates here + eErrorTmplEmpty = 0x12, //No registered template in the designated ID + eErrorTmplNotEmpty = 0x13, //Template already exists in the specified ID + eErrorAllTmplEmpty = 0x14, //No registered Template + eErrorEmptyIDNoexist = 0x15, //No registerable Template ID + eErrorBrokenIDNoexist = 0x16, //No damaged Template + eErrorInvalidTmplData = 0x17, //The designated Template Data is invalid + eErrorDuplicationID = 0x18, //The fingerprint has been registered + eErrorBadQuality = 0x19, //Poor quality fingerprint image + eErrorMergeFail = 0x1A, //Template synthesis failed + eErrorNotAuthorized = 0x1B, //Communication password not authorized + eErrorMemory = 0x1C, //Error in exernal Flash burning + eErrorInvalidTmplNo = 0x1D, //The designated template ID is invalid + eErrorInvalidParam = 0x22, //Incorrect parameter has been used + eErrorTimeOut = 0x23, //Acquisition timeout + eErrorGenCount = 0x25, //Invalid number of fingerprint synthesis + eErrorInvalidBufferID = 0x26, //Wrong Buffer ID value + eErrorFPNotDetected = 0x28, //No fingerprint input into fingerprint reader + eErrorFPCancel = 0x41, //Command cancelled + eErrorRecvLength = 0x42, //Wrong length of recieved data + eErrorRecvCks = 0x43, //Wrong check code + eErrorGatherOut = 0x45, //Exceed upper limit of acquisition times + eErrorRecvTimeout = 0x46 //Communication timeout + }eError_t; + + typedef struct{ + /**< Gesture enumeration variable X */ + eError_t error; + /**< Description about the gesture enumeration variable X */ + const char * description; + }sErrorDescription_t; + +public: + DFRobot_ID809(); + ~DFRobot_ID809(); + + /** + * @brief Init communication port + * @param Software serial or hardware serial + * @return true or false + */ + bool begin(Stream &s_); + + /** + * @brief Test whether the module connection is ok + * @return true or false + */ + bool isConnected(); + + /** + * @brief Set module ID + * @param ID:1-255 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDeviceID(uint8_t deviceID); + + /** + * @brief Set module security level + * @param security level:1-5 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSecurityLevel(uint8_t securityLevel); + + /** + * @brief Set module fingerprint replication check (Check whether the fingperint has been registered when saving it) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDuplicationCheck(uint8_t duplicationCheck); + + /** + * @brief Set module baud rate + * @param Baudrate:in typedef enum eDeviceBaudrate_t + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setBaudrate(eDeviceBaudrate_t baudrate); + + /** + * @brief Set module self-learning function (Update fingeprint when fingerprint comparison succeeds) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSelfLearn(uint8_t selfLearn); + + /** + * @brief Read module ID + * @return IDå·:1-255 or ERR_ID809 + */ + uint8_t getDeviceID(); + + /** + * @brief Read module security level + * @return Security level:1-5 or ERR_ID809 + */ + uint8_t getSecurityLevel(); + + /** + * @brief Read module fingerprint replication check status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getDuplicationCheck(); + + /** + * @brief Read module baud rate + * @return Baudrate:in typedef enum eDEVICE_BAUDRATE_t or ERR_ID809 + */ + uint8_t getBaudrate(); + + /** + * @brief Read module self-learning function status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getSelfLearn(); + + /** + * @brief Read device number + * @return Device number + */ + String getDeviceInfo(); + + /** + * @brief Set serial number + * @param String pointer + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setModuleSN(const char* SN); + /** + * @brief Read serial number + * @return Serial number + */ + String getModuleSN(); + + /** + * @brief Set LED + * @param mode:in typedef enum eLEDMode_t + * @param color:in typedef enum eLEDColor_t + * @param blink Count: 00 represents blinking all the time + * @This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + * @return 0(succeed) or ERR_ID809 + */ + uint8_t ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount); + + /** + * @brief Detect if there is finger touched + * @return 1(Touched) or 0(No touch) + */ + uint8_t detectFinger(); + + /** + * @brief Get the first registerable ID + * @return Registerable ID or ERR_ID809 + */ + uint8_t getEmptyID(); + + /** + * @brief Check if the ID has been registered + * @return 0(Registered), 1(Unregistered) or ERR_ID809 + */ + uint8_t getStatusID(uint8_t ID); + + /** + * @brief Get the number of registered users + * @return Number of registered users or ERR_ID809 + */ + uint8_t getEnrollCount(); + + /** + * @brief Get registered user list + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getEnrolledIDList(uint8_t* list); + + /** + * @brief Fingerprint acquisition + * @return 0(succeed) or ERR_ID809 + */ + uint8_t collectionFingerprint(uint16_t timeout); + + /** + * @brief Save fingerprint + * @param Fingerprint ID + * @return 0(succeed) or ERR_ID809 + */ + uint8_t storeFingerprint(uint8_t ID); + + /** + * @brief Delete fingerprint + * @param Delete ID or DELALL(delete all) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t delFingerprint(uint8_t ID); + + /** + * @brief Match the fingerprint with all fingeprints + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t search(); + + /** + * @brief Match the fingerprint with specific fingerprint + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t verify(uint8_t ID); + + /** + * @brief Compare templates in two specific RamBuffers + * @param RamBuffer number + * @param RamBuffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t match(uint8_t RamBufferID0, uint8_t RamBufferID1); + + /** + * @brief Get the number of damaged fingerprints + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenQuantity(); + + /** + * @brief Get the first damaged fingerprint ID + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenID(); + + /** + * @brief Take out fingerprint template, temporarily save into RamBuffer + * @param Fingerprint ID + * @param RamBuffer number 0-2 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t loadFingerprint(uint8_t ID, uint8_t RamBufferID); + + /** + * @brief Enter sleep mode + * @return 0(succeed) or ERR_ID809 + */ + uint8_t enterSleepState(); + + /** + * @brief Get error information + * @return Text description of error information + */ + String getErrorDescription(); + + bool setDbgSerial(Stream &s_){dbg = &s_; return true;} +protected: + /** + * @brief Set parameter + * @param Data type+ data + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setParam(uint8_t* data); + + /** + * @brief Read parameter + * @param Data type + * @return data or ERR_ID809 + */ + uint8_t getParam(uint8_t* data); + + /** + * @brief Capture fingerprint image + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getImage(); + + /** + * @brief Take image as template + * @param Ram Buffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t generate(uint8_t RamBufferID); + + /** + * @brief Fingerprint synthesis + * @return 0(succeed) or ERR_ID809 + */ + uint8_t merge(); + + /** + * @brief Packing data frame + * @param Data type:CMD_TYPE or DATA_TYPE + * @param Command + * @param Data + * @param Length + * @return Data frame + */ + pCmdPacketHeader_t pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len); + + /** + * @brief Send data + * @param Data frame + */ + void sendPacket(pCmdPacketHeader_t header); + + /** + * @brief Read byte + * @param Pointer for saving data + * @param Length of data to be received + * @return Actual received data length + */ + size_t readN(void* buf_, size_t len); + + /** + * @brief Read frame header + * @param Frame header struct of response packet + * @return Response packet type:RCM_TYPE,DATA_TYPE or 1(reading timeout) + */ + uint16_t readPrefix( pRcmPacketHeader_t header ); + + /** + * @brief Read data + * @param Pointer for saving data + * @return 0(success) or ERR_ID809 + */ + uint8_t responsePayload(void* buf); + + /** + * @brief Get command packet CKS + * @param Command packet frame + * @return CKS + */ + uint16_t getCmdCKS(pCmdPacketHeader_t packet); + + /** + * @brief Get response packet CKS + * @param Response packet frame + * @return CKS + */ + uint16_t getRcmCKS(pRcmPacketHeader_t packet); + +private: + Stream *s; + uint8_t buf[20]; //For saving response packet data + pCmdPacketHeader_t sendHeader; + pRcmPacketHeader_t recHeader; + + static const sErrorDescription_t /*PROGMEM*/ errorDescriptionsTable[26]; //Error information list + + uint8_t _number = 0; //Fingerprint acquisistion times + eError_t _error; //Error code + uint16_t _PacketSize = 0; //Data packet length to be sent +}; + +#endif diff --git a/FingerPrintMatching/platformio.ini b/FingerPrintMatching/platformio.ini new file mode 100644 index 0000000..3f073b4 --- /dev/null +++ b/FingerPrintMatching/platformio.ini @@ -0,0 +1,12 @@ +[env:teensy_u2f] + +platform = teensy +framework = arduino +board = teensy31 +build_flags = + -D USB_SERIAL + -D TEENSY_OPT_SMALLEST_CODE + +lib_deps = + Wire + diff --git a/FingerPrintMatching/src/DFRobot_ID809.cpp b/FingerPrintMatching/src/DFRobot_ID809.cpp new file mode 100644 index 0000000..4561698 --- /dev/null +++ b/FingerPrintMatching/src/DFRobot_ID809.cpp @@ -0,0 +1,748 @@ +/*! + * @file DFRobot_ID809.cpp + * @brief Define the basic structure of DFRobot_ID809 class and the implementation of underlying methods + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#include "DFRobot_ID809.h" +#include <Arduino.h> +#include <string.h> +#include <stdio.h> +Stream *dbg=NULL; + +DFRobot_ID809::DFRobot_ID809() + :s(NULL){ + +} + +DFRobot_ID809::~DFRobot_ID809(){ + +} + +bool DFRobot_ID809::begin(Stream &s_){ + s = &s_; + if(s == NULL){ + return false; + } + return true; +} + +bool DFRobot_ID809::isConnected(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_TEST_CONNECTION, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + return true; + }else{ + return false; + } +} + +uint8_t DFRobot_ID809::setDeviceID(uint8_t deviceID){ + uint8_t data[5] = {0}; //data:1bytes Parameter Type+4bytes Parameter Value + data[1] = deviceID; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSecurityLevel(uint8_t securityLevel){ + uint8_t data[5] = {0}; + data[0] = 1; + data[1] = securityLevel; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setDuplicationCheck(uint8_t duplicationCheck){ + uint8_t data[5] = {0}; + data[0] = 2; + data[1] = duplicationCheck; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setBaudrate(eDeviceBaudrate_t baudrate){ + uint8_t data[5] = {0}; + data[0] = 3; + data[1] = baudrate; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSelfLearn(uint8_t selfLearn){ + uint8_t data[5] = {0}; + data[0] = 4; + data[1] = selfLearn; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDeviceID(){ + uint8_t data[1]; //data:1byte Parameter Type + data[0] = 0; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSecurityLevel(){ + uint8_t data[1]; + data[0] = 1; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDuplicationCheck(){ + uint8_t data[1]; + data[0] = 2; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getBaudrate(){ + uint8_t data[1]; + data[0] = 3; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSelfLearn(){ + uint8_t data[1]; + data[0] = 4; + uint8_t ret = getParam(data); + return ret; +} + +String DFRobot_ID809::getDeviceInfo(){ + char *data; + uint8_t result; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEVICE_INFO, NULL, 0); + sendPacket(header); + free(header); + result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::setModuleSN(const char* SN){ + char data[2]; + data[0] = MODULE_SN_SIZE; + if(strlen(SN) > MODULE_SN_SIZE){ + LDBG("The serial number exceeds 15 characters"); + return ERR_ID809; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_MODULE_SN, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + header = pack(DATA_TYPE, CMD_SET_MODULE_SN, SN, MODULE_SN_SIZE); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +String DFRobot_ID809::getModuleSN(){ + char *data; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_MODULE_SN, NULL, 0); + sendPacket(header); + free(header); + uint8_t result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount){ + char data[4] = {0}; + data[0] = mode; + data[2] = data[1] = color; + data[3] = blinkCount; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SLED_CTRL, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::detectFinger(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_FINGER_DETECT, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEmptyID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; //80 fingerprints at most, default to full range + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_EMPTY_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getStatusID(uint8_t ID){ + char data[2] = {0}; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_STATUS, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEnrollCount(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLL_COUNT, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +#define getID(A, V) (A[0 + V/8] & (0x01 << (V & 0x07))) +uint8_t DFRobot_ID809::getEnrolledIDList(uint8_t* list) +{ + char *data; + uint8_t i = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLLED_ID_LIST, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + uint16_t dataLen = buf[0]+(buf[1]<<8); + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + ret = responsePayload(data); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else{ + for(uint16_t j = 0; j < (dataLen*8); j++){ + if(getID(data, j) != 0){ + list[i] = j; + i++; + } + } + } + free(data); + return ret; +} + +uint8_t DFRobot_ID809::storeFingerprint(uint8_t ID){ + char data[4] = {0}; + uint8_t ret; + ret = merge(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number = 0; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; + +} + +uint8_t DFRobot_ID809::delFingerprint(uint8_t ID){ + char data[4] = {0}; + if(ID == DELALL){ + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + }else{ + data[0] = data[2] = ID; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEL_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::search(){ + char data[6] = {0}; + data[2] = 1; + data[4] = FINGERPRINT_CAPACITY; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SEARCH, data, 6); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::verify(uint8_t ID){ + char data[4] = {0}; + data[0] = ID; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_VERIFY, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::match(uint8_t RamBufferID0, uint8_t RamBufferID1){ + char data[4] = {0}; + data[0] = RamBufferID0; + data[2] = RamBufferID1; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenQuantity(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[2]; + } + return ret; +} + +uint8_t DFRobot_ID809::loadFingerprint(uint8_t ID, uint8_t RamBufferID){ + char data[4] = {0}; + data[0] = ID; + data[2] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::enterSleepState(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_ENTER_STANDBY_STATE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::setParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_PARAM, (const char *)data, 5); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::getParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_PARAM, (const char *)data, 1); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getImage(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::collectionFingerprint(uint16_t timeout){ //Collect fingerprint + uint16_t i = 0; + uint8_t ret; + if(_number > 2){ + _error = eErrorGatherOut; + LDBG("Exceed upper limit of acquisition times "); + return ERR_ID809; + } + while(!detectFinger()){ + if(timeout != 0){ + delay(10); + if(++i > timeout*1){ + _error = eErrorTimeOut; + LDBG("Acquisition timeout "); + LDBG("ret=");LDBG(ret); + return ERR_ID809; + } + } + } + ret = getImage(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + ret = generate(_number); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number++; + return ret; +} + +uint8_t DFRobot_ID809::generate(uint8_t RamBufferID){ + char data[2] = {0}; + data[0] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GENERATE, (const char *)data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::merge(){ + char data[3] = {0}; + data[2] = _number; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MERGE, data, 3); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +pCmdPacketHeader_t DFRobot_ID809::pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len){ + pCmdPacketHeader_t header; + uint16_t cks=0; + uint16_t dataLen; + if(type == CMD_TYPE){ //Structure of command packet, fixed 26 bytes:10(frame header)+14(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+16+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_PREFIX_CODE; + for(int i=0;i<16;i++){ + header->payload[i] = 0; + } + dataLen = 16; //Length of data to be replicated + }else{ //Structure of command data packet, unfixed length:10(frame header)+LEN(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+len+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_DATA_PREFIX_CODE; + dataLen = len; //Length of data to be replicated + } + header->SID = 0; + header->DID = 0; + header->CMD = cmd; + header->LEN = len; + if(len){ + memcpy(header->payload, payload, len); + } + cks = getCmdCKS(header); + memcpy(&header->payload[dataLen],&cks,2); + _PacketSize = sizeof(sCmdPacketHeader_t) + dataLen +2; + return header; +} + + +void DFRobot_ID809::sendPacket(pCmdPacketHeader_t header){ + s->write((uint8_t *)header,_PacketSize); +} + +uint8_t DFRobot_ID809::responsePayload(void* buf){ + sRcmPacketHeader_t header; + uint16_t dataLen,dataCount,cks; + uint8_t ch,ret; + int16_t type; + type = readPrefix(&header); + if(type == 1){ + LDBG("--recv timeout---"); + _error = eErrorRecvTimeout; + return ERR_ID809; + } + pRcmPacketHeader_t packet; + if(type == RCM_TYPE){ //Structure of response packet, fixed 26 bytes: 10(frame header)+14(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+14+2); + dataLen = 14+2; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + }else{ //Structure of response data packet, unfixed length: 10(frame header)+(LEN-2)(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+header.LEN); + dataLen = header.LEN; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + } + memcpy(packet, &header, 10); + dataCount = readN(packet->payload, dataLen); + cks = packet->payload[dataLen-2]+(packet->payload[dataLen-1]<<8); + ret = (header.RET&0xFF); + _error = (eError_t)ret; + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else if(dataLen != dataCount){ + LDBG("--recvRspPacket length error---"); + _error = eErrorRecvLength; + ret = ERR_ID809; + }else if(getRcmCKS(packet) != cks){ + LDBG("--recvRspPacket cks error---"); + _error = eErrorRecvCks; + ret = ERR_ID809; + }else{ + LDBG("--recvRspPacket OK---"); + memcpy(buf, packet->payload, dataLen); + } + free(packet); + packet = NULL; + return ret; +} + +uint16_t DFRobot_ID809::readPrefix( pRcmPacketHeader_t header ){ + uint8_t ch,ret; + typedef enum{ + RECV_HEADER_INIT, + RECV_HEADER_AA, + RECV_HEADER_A5, + RECV_HEADER_OK + }eRecvHeaderState; + eRecvHeaderState state = RECV_HEADER_INIT; + while(state != RECV_HEADER_OK){ //Can judge the received command packet and command data packet prefix at the same time + if(readN(&ch, 1) != 1){ + ret = 1; + return ret; + } + if((ch == 0xAA) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_AA; + continue; + }else if((ch == 0xA5) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_A5; + continue; + }else if((ch == 0x55) && (state == RECV_HEADER_AA)){ + state = RECV_HEADER_OK; + ret = RCM_TYPE; + continue; + }else if((ch == 0x5A) && (state == RECV_HEADER_A5)){ + state = RECV_HEADER_OK; + ret = DATA_TYPE; + continue; + }else{ + state = RECV_HEADER_INIT; + if(ch == 0xAA){ + state = RECV_HEADER_AA; + }else if(ch == 0xA5){ + state = RECV_HEADER_A5; + } + } + } + if(ret == RCM_TYPE){ + header->PREFIX = RCM_PREFIX_CODE; + }else if(ret == DATA_TYPE){ + header->PREFIX = RCM_DATA_PREFIX_CODE; + } + readN(&header->SID, 1); + readN(&header->DID, 1); + readN(&header->RCM, 2); + readN(&header->LEN, 2); + readN(&header->RET, 2); + return ret; +} + +size_t DFRobot_ID809::readN(void* buffer, size_t len){ + size_t offset = 0,left = len; + uint8_t *buf = (uint8_t*)buffer; + long long curr = millis(); + while(left){ + if(s->available()){ + buf[offset++] = s->read(); + left--; + } + if(millis() - curr > 5000){ + LDBG("----------!!!!!!!!!recv timeout----------"); + break; + } + } + return offset; +} + +uint16_t DFRobot_ID809::getCmdCKS(pCmdPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->CMD&0xFF; + cks += packet->CMD>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint8_t i = 0; i < packet->LEN; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +uint16_t DFRobot_ID809::getRcmCKS(pRcmPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->RCM&0xFF; + cks += packet->RCM>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + cks += packet->RET&0xFF; + cks += packet->RET>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint8_t i = 0; i < packet->LEN-2; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +const DFRobot_ID809::sErrorDescription_t DFRobot_ID809::errorDescriptionsTable[]={ + {eErrorSuccess, "Command processed successfully"}, + {eErrorFail, "Command processing failed"}, + {eErrorVerify, "1:1 comparison failed"}, + {eErrorIdentify, "Comparison with all fingerprints failed"}, + {eErrorTmplEmpty, "No fingerprint in designated ID"}, + {eErrorTmplNotEmpty, "Designated ID has fingerprint"}, + {eErrorAllTmplEmpty, "Module unregistered fingerprint"}, + {eErrorEmptyIDNoexist, "No registerable ID here"}, + {eErrorBrokenIDNoexist, "No broken fingerprint"}, + {eErrorInvalidTmplData, "Invalid desingated fingerprint data"}, + {eErrorDuplicationID, "The fingerprint has been registered"}, + {eErrorBadQuality, "Poor quality fingerprint image"}, + {eErrorMergeFail, "Fingerprint synthesis failed"}, + {eErrorNotAuthorized, "Communication password not authorized"}, + {eErrorMemory, "External Flash burning error"}, + {eErrorInvalidTmplNo, "Invalid designated ID"}, + {eErrorInvalidParam, "Incorrect parameter"}, + {eErrorTimeOut, "Acquisition timeout"}, + {eErrorGenCount, "Invalid number of fingerprint synthesis"}, + {eErrorInvalidBufferID, "Incorrect Buffer ID value"}, + {eErrorFPNotDetected, "No fingerprint input into fingerprint reader"}, + {eErrorFPCancel, "Command cancelled"}, + {eErrorRecvLength, "Wrong data length"}, + {eErrorRecvCks, "Wrong data check code"}, + {eErrorGatherOut, "Exceed upper limit of acquisition times"}, + {eErrorRecvTimeout,"Data reading timeout"} +}; + +String DFRobot_ID809::getErrorDescription() +{ + for(int i=0;i<sizeof(errorDescriptionsTable)/sizeof(errorDescriptionsTable[0]);i++){ + if(_error == errorDescriptionsTable[i].error){ + return errorDescriptionsTable[i].description; + } + } + return ""; +} diff --git a/FingerPrintMatching/src/src.cpp b/FingerPrintMatching/src/src.cpp new file mode 100644 index 0000000..d82aba8 --- /dev/null +++ b/FingerPrintMatching/src/src.cpp @@ -0,0 +1,107 @@ +/*! + * @file fingerprintMatching.ino + * @brief Gather fingerprint and compare it with fingerprints in fingerprint library + * @n Experiment Phenomenon:capture fingerprint image and compare it with all fingerprints in the fingerprint library + If matched successfully, light up green LED and print ID number. Return 0 when failed. + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](Eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 +*/ +#include <Arduino.h> +#include "DFRobot_ID809.h" + +/*Use software serial when using UNO or NANO*/ +//#if ((defined ARDUINO_AVR_UNO) || (defined ARDUINO_AVR_NANO)) +// #include <SoftwareSerial.h> +// SoftwareSerial Serial1(2, 3); //RX, TX +// #define FPSerial Serial1 +//#else +// #define FPSerial Serial1 +//#endif + +#define FPSerial Serial3 + +DFRobot_ID809 fingerprint; +//String desc; + +void setup(){ + /*Init print serial port*/ + Serial.begin(9600); + /*Init FPSerial*/ + FPSerial.begin(115200); + /*Take FPSerial as communication serial port of the fingerprint module*/ + fingerprint.begin(FPSerial); + /*Wait for Serial to open*/ + //while(!Serial); + /*Test whether the device can properly communicate with mainboard + Return true or false + */ + while(fingerprint.isConnected() == false){ + Serial.println("Communication with device failed, please check connection"); + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + delay(1000); + } +} + +uint8_t ret; + +void loop(){ + /*Set fingerprint LED ring mode, color, and number of blinks + Can be set as follows: + Parameter 1:<LEDMode> + eBreathing eFastBlink eKeepsOn eNormalClose + eFadeIn eFadeOut eSlowBlink + Parameter 2:<LEDColor> + eLEDGreen eLEDRed eLEDYellow eLEDBlue + eLEDCyan eLEDMagenta eLEDWhite + Parameter 3:<number of blinks> 0 represents blinking all the time + This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eBreathing, /*LEDColor = */fingerprint.eLEDBlue, /*blinkCount = */0); + Serial.println("Please press down your finger"); + /*Capture fingerprint image, Disable the collection timeout function + If succeed return 0, otherwise return ERR_ID809 + */ + if((fingerprint.collectionFingerprint(/*timeout=*/0)) != ERR_ID809){ + /*Set fingerprint LED ring to quick blink in yellow 3 times*/ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eFastBlink, /*LEDColor = */fingerprint.eLEDYellow, /*blinkCount = */3); + Serial.println("Capturing succeeds"); + Serial.println("Please release your finger"); + /*Wait for finger to release + Return 1 when finger is detected, otherwise return 0 + */ + while(fingerprint.detectFinger()); + + /*Compare the captured fingerprint with all the fingerprints in the fingerprint library + Return fingerprint ID(1-80) if succeed, return 0 when failed + */ + ret = fingerprint.search(); + /*Compare the captured fingerprint with a fingerprint of specific ID + Return fingerprint ID(1-80) if succeed, return 0 when failed + */ + //ret = fingerprint.verify(/*Fingerprint ID = */1); + if(ret != 0){ + /*Set fingerprint LED ring to always ON in green */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eKeepsOn, /*LEDColor = */fingerprint.eLEDGreen, /*blinkCount = */0); + Serial.print("Matching succeeds,ID="); + Serial.println(ret); + }else{ + /*Set fingerprint LED ring to always ON in red*/ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eKeepsOn, /*LEDColor = */fingerprint.eLEDRed, /*blinkCount = */0); + Serial.println("Matching fails"); + } + }else{ + Serial.println("Capturing fails"); + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + } + Serial.println("-----------------------------"); + delay(1000); +} diff --git a/FingerPrintRegister/include/DFRobot_ID809.h b/FingerPrintRegister/include/DFRobot_ID809.h new file mode 100644 index 0000000..4cb90d9 --- /dev/null +++ b/FingerPrintRegister/include/DFRobot_ID809.h @@ -0,0 +1,494 @@ +/*! + * @file DFRobot_ID809.h + * @brief Define basic structure of DFRobot_ID809 class + * @n This is an library for capacitive fingerprint module + * @n Main functions: fingerprint image capturing, fingerprint comparison, fingerprint deletion + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#ifndef _DFRobot_ID809_H +#define _DFRobot_ID809_H + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif +#include <Wire.h> + +#include <stdint.h> + +//Open this macro to see the detailed running process of the program + +//#define ENABLE_DBG +#ifdef ENABLE_DBG +#define LDBG(...) if(dbg) {dbg->print("["); dbg->print(__FUNCTION__); dbg->print("(): "); dbg->print(__LINE__); dbg->print(" ] "); dbg->println(__VA_ARGS__);} +#else +#define LDBG(...) +#endif + +extern Stream *dbg; + + /* + Frame struct of command packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t CMD; + uint16_t LEN; + uint8_t payload[0]; +}__attribute__ ((packed)) sCmdPacketHeader_t, *pCmdPacketHeader_t; + + /* + Frame struct of response packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t RCM; + uint16_t LEN; + uint16_t RET; + uint8_t payload[0]; +}__attribute__ ((packed)) sRcmPacketHeader_t, *pRcmPacketHeader_t; + + + + +class DFRobot_ID809{ +public: + +#define FINGERPRINT_CAPACITY 80 //Fingerprint module capacity +#define MODULE_SN_SIZE 16 //Module SN length + + +#define DELALL 0xFF //Delete all fingerprints + +#define CMD_PREFIX_CODE 0xAA55 //Command packet prefix code +#define RCM_PREFIX_CODE 0x55AA //Response packet prefix code +#define CMD_DATA_PREFIX_CODE 0xA55A //Command data packet prefix code +#define RCM_DATA_PREFIX_CODE 0x5AA5 //Response data packet prefix code + +#define CMD_TYPE 0xF0 //Command packet type +#define RCM_TYPE 0xF0 //Response packet type +#define DATA_TYPE 0x0F //Data packet type + +#define CMD_TEST_CONNECTION 0X0001 //Test connection +#define CMD_SET_PARAM 0X0002 //Set parameter +#define CMD_GET_PARAM 0X0003 //Read parameter +#define CMD_DEVICE_INFO 0X0004 //Read device information +#define CMD_SET_MODULE_SN 0X0008 //Set module serial number +#define CMD_GET_MODULE_SN 0X0009 //Read module serial number +#define CMD_ENTER_STANDBY_STATE 0X000C //Enter sleep mode +#define CMD_GET_IMAGE 0X0020 //Capture fingerprint image +#define CMD_FINGER_DETECT 0X0021 //Detect fingerprint + #define CMD_UP_IMAGE_CODE 0X0022 //Upload fingerprint image to host + #define CMD_DOWN_IMAGE 0X0023 //Download fingerprint image to module +#define CMD_SLED_CTRL 0X0024 //Control collector backlight +#define CMD_STORE_CHAR 0X0040 //Save fingerprint template data into fingerprint library +#define CMD_LOAD_CHAR 0X0041 //Read fingerprint in module and save it in RAMBUFFER temporarily + #define CMD_UP_CHAR 0X0042 //Upload the fingerprint template saved in RAMBUFFER to host + #define CMD_DOWN_CHAR 0X0043 //Download fingerprint template to module designated RAMBUFFER +#define CMD_DEL_CHAR 0X0044 //Delete fingerprint in specific ID range +#define CMD_GET_EMPTY_ID 0X0045 //Get the first registerable ID in specific ID range +#define CMD_GET_STATUS 0X0046 //Check if the designated ID has been registered +#define CMD_GET_BROKEN_ID 0X0047 //Check whether there is damaged data in fingerprint library of specific range +#define CMD_GET_ENROLL_COUNT 0X0048 //Get the number of registered fingerprints in specific ID range +#define CMD_GET_ENROLLED_ID_LIST 0X0049 //Get registered ID list +#define CMD_GENERATE 0X0060 //Generate template from the fingerprint images saved in IMAGEBUFFER temporarily +#define CMD_MERGE 0X0061 //Synthesize fingerprint template data +#define CMD_MATCH 0X0062 //Compare templates in 2 designated RAMBUFFER +#define CMD_SEARCH 0X0063 //1:N Recognition in specific ID range +#define CMD_VERIFY 0X0064 //Compare specific RAMBUFFER template with specific ID template in fingerprint library + +#define ERR_SUCCESS 0x00 //Command processed successfully +#define ERR_ID809 0xFF //error + + +public: + + typedef enum{ + eBreathing = 1, //Breathing + eFastBlink, //Quick blink + eKeepsOn, //On + eNormalClose, //Off + eFadeIn, //Fade in + eFadeOut, //Fade out + eSlowBlink //Slow blink + }eLEDMode_t; + + typedef enum{ + eLEDGreen = 1, //green + eLEDRed, //red + eLEDYellow, //yellow + eLEDBlue, //blue + eLEDCyan, //cyan + eLEDMagenta, //magenta + eLEDWhite //white + }eLEDColor_t; + + typedef enum{ + e9600bps = 1, + e19200bps, + e38400bps, + e57600bps, + e115200bps + }eDeviceBaudrate_t; + + typedef enum{ + eErrorSuccess = 0x00, //Command processed successfully + eErrorFail = 0x01, //Command processing failed + eErrorVerify = 0x10, //1:1 Templates comparison in specific ID failed + eErrorIdentify = 0x11, //1:N comparison has been made, no same templates here + eErrorTmplEmpty = 0x12, //No registered template in the designated ID + eErrorTmplNotEmpty = 0x13, //Template already exists in the specified ID + eErrorAllTmplEmpty = 0x14, //No registered Template + eErrorEmptyIDNoexist = 0x15, //No registerable Template ID + eErrorBrokenIDNoexist = 0x16, //No damaged Template + eErrorInvalidTmplData = 0x17, //The designated Template Data is invalid + eErrorDuplicationID = 0x18, //The fingerprint has been registered + eErrorBadQuality = 0x19, //Poor quality fingerprint image + eErrorMergeFail = 0x1A, //Template synthesis failed + eErrorNotAuthorized = 0x1B, //Communication password not authorized + eErrorMemory = 0x1C, //Error in exernal Flash burning + eErrorInvalidTmplNo = 0x1D, //The designated template ID is invalid + eErrorInvalidParam = 0x22, //Incorrect parameter has been used + eErrorTimeOut = 0x23, //Acquisition timeout + eErrorGenCount = 0x25, //Invalid number of fingerprint synthesis + eErrorInvalidBufferID = 0x26, //Wrong Buffer ID value + eErrorFPNotDetected = 0x28, //No fingerprint input into fingerprint reader + eErrorFPCancel = 0x41, //Command cancelled + eErrorRecvLength = 0x42, //Wrong length of recieved data + eErrorRecvCks = 0x43, //Wrong check code + eErrorGatherOut = 0x45, //Exceed upper limit of acquisition times + eErrorRecvTimeout = 0x46 //Communication timeout + }eError_t; + + typedef struct{ + /**< Gesture enumeration variable X */ + eError_t error; + /**< Description about the gesture enumeration variable X */ + const char * description; + }sErrorDescription_t; + +public: + DFRobot_ID809(); + ~DFRobot_ID809(); + + /** + * @brief Init communication port + * @param Software serial or hardware serial + * @return true or false + */ + bool begin(Stream &s_); + + /** + * @brief Test whether the module connection is ok + * @return true or false + */ + bool isConnected(); + + /** + * @brief Set module ID + * @param ID:1-255 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDeviceID(uint8_t deviceID); + + /** + * @brief Set module security level + * @param security level:1-5 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSecurityLevel(uint8_t securityLevel); + + /** + * @brief Set module fingerprint replication check (Check whether the fingperint has been registered when saving it) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDuplicationCheck(uint8_t duplicationCheck); + + /** + * @brief Set module baud rate + * @param Baudrate:in typedef enum eDeviceBaudrate_t + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setBaudrate(eDeviceBaudrate_t baudrate); + + /** + * @brief Set module self-learning function (Update fingeprint when fingerprint comparison succeeds) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSelfLearn(uint8_t selfLearn); + + /** + * @brief Read module ID + * @return IDå·:1-255 or ERR_ID809 + */ + uint8_t getDeviceID(); + + /** + * @brief Read module security level + * @return Security level:1-5 or ERR_ID809 + */ + uint8_t getSecurityLevel(); + + /** + * @brief Read module fingerprint replication check status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getDuplicationCheck(); + + /** + * @brief Read module baud rate + * @return Baudrate:in typedef enum eDEVICE_BAUDRATE_t or ERR_ID809 + */ + uint8_t getBaudrate(); + + /** + * @brief Read module self-learning function status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getSelfLearn(); + + /** + * @brief Read device number + * @return Device number + */ + String getDeviceInfo(); + + /** + * @brief Set serial number + * @param String pointer + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setModuleSN(const char* SN); + /** + * @brief Read serial number + * @return Serial number + */ + String getModuleSN(); + + /** + * @brief Set LED + * @param mode:in typedef enum eLEDMode_t + * @param color:in typedef enum eLEDColor_t + * @param blink Count: 00 represents blinking all the time + * @This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + * @return 0(succeed) or ERR_ID809 + */ + uint8_t ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount); + + /** + * @brief Detect if there is finger touched + * @return 1(Touched) or 0(No touch) + */ + uint8_t detectFinger(); + + /** + * @brief Get the first registerable ID + * @return Registerable ID or ERR_ID809 + */ + uint8_t getEmptyID(); + + /** + * @brief Check if the ID has been registered + * @return 0(Registered), 1(Unregistered) or ERR_ID809 + */ + uint8_t getStatusID(uint8_t ID); + + /** + * @brief Get the number of registered users + * @return Number of registered users or ERR_ID809 + */ + uint8_t getEnrollCount(); + + /** + * @brief Get registered user list + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getEnrolledIDList(uint8_t* list); + + /** + * @brief Fingerprint acquisition + * @return 0(succeed) or ERR_ID809 + */ + uint8_t collectionFingerprint(uint16_t timeout); + + /** + * @brief Save fingerprint + * @param Fingerprint ID + * @return 0(succeed) or ERR_ID809 + */ + uint8_t storeFingerprint(uint8_t ID); + + /** + * @brief Delete fingerprint + * @param Delete ID or DELALL(delete all) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t delFingerprint(uint8_t ID); + + /** + * @brief Match the fingerprint with all fingeprints + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t search(); + + /** + * @brief Match the fingerprint with specific fingerprint + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t verify(uint8_t ID); + + /** + * @brief Compare templates in two specific RamBuffers + * @param RamBuffer number + * @param RamBuffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t match(uint8_t RamBufferID0, uint8_t RamBufferID1); + + /** + * @brief Get the number of damaged fingerprints + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenQuantity(); + + /** + * @brief Get the first damaged fingerprint ID + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenID(); + + /** + * @brief Take out fingerprint template, temporarily save into RamBuffer + * @param Fingerprint ID + * @param RamBuffer number 0-2 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t loadFingerprint(uint8_t ID, uint8_t RamBufferID); + + /** + * @brief Enter sleep mode + * @return 0(succeed) or ERR_ID809 + */ + uint8_t enterSleepState(); + + /** + * @brief Get error information + * @return Text description of error information + */ + String getErrorDescription(); + + bool setDbgSerial(Stream &s_){dbg = &s_; return true;} +protected: + /** + * @brief Set parameter + * @param Data type+ data + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setParam(uint8_t* data); + + /** + * @brief Read parameter + * @param Data type + * @return data or ERR_ID809 + */ + uint8_t getParam(uint8_t* data); + + /** + * @brief Capture fingerprint image + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getImage(); + + /** + * @brief Take image as template + * @param Ram Buffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t generate(uint8_t RamBufferID); + + /** + * @brief Fingerprint synthesis + * @return 0(succeed) or ERR_ID809 + */ + uint8_t merge(); + + /** + * @brief Packing data frame + * @param Data type:CMD_TYPE or DATA_TYPE + * @param Command + * @param Data + * @param Length + * @return Data frame + */ + pCmdPacketHeader_t pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len); + + /** + * @brief Send data + * @param Data frame + */ + void sendPacket(pCmdPacketHeader_t header); + + /** + * @brief Read byte + * @param Pointer for saving data + * @param Length of data to be received + * @return Actual received data length + */ + size_t readN(void* buf_, size_t len); + + /** + * @brief Read frame header + * @param Frame header struct of response packet + * @return Response packet type:RCM_TYPE,DATA_TYPE or 1(reading timeout) + */ + uint16_t readPrefix( pRcmPacketHeader_t header ); + + /** + * @brief Read data + * @param Pointer for saving data + * @return 0(success) or ERR_ID809 + */ + uint8_t responsePayload(void* buf); + + /** + * @brief Get command packet CKS + * @param Command packet frame + * @return CKS + */ + uint16_t getCmdCKS(pCmdPacketHeader_t packet); + + /** + * @brief Get response packet CKS + * @param Response packet frame + * @return CKS + */ + uint16_t getRcmCKS(pRcmPacketHeader_t packet); + +private: + Stream *s; + uint8_t buf[20]; //For saving response packet data + pCmdPacketHeader_t sendHeader; + pRcmPacketHeader_t recHeader; + + static const sErrorDescription_t /*PROGMEM*/ errorDescriptionsTable[26]; //Error information list + + uint8_t _number = 0; //Fingerprint acquisistion times + eError_t _error; //Error code + uint16_t _PacketSize = 0; //Data packet length to be sent +}; + +#endif diff --git a/FingerPrintRegister/platformio.ini b/FingerPrintRegister/platformio.ini new file mode 100644 index 0000000..f539a67 --- /dev/null +++ b/FingerPrintRegister/platformio.ini @@ -0,0 +1,11 @@ +[env:teensy_u2f] + +platform = teensy +framework = arduino +board = teensy31 +build_flags = + -D USB_SERIAL + -D TEENSY_OPT_SMALLEST_CODE + +lib_deps = + Wire diff --git a/FingerPrintRegister/src/DFRobot_ID809.cpp b/FingerPrintRegister/src/DFRobot_ID809.cpp new file mode 100644 index 0000000..f2aa3a2 --- /dev/null +++ b/FingerPrintRegister/src/DFRobot_ID809.cpp @@ -0,0 +1,748 @@ +/*! + * @file DFRobot_ID809.cpp + * @brief Define the basic structure of DFRobot_ID809 class and the implementation of underlying methods + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#include "DFRobot_ID809.h" +#include <Arduino.h> +#include <string.h> +#include <stdio.h> +Stream *dbg=NULL; + +DFRobot_ID809::DFRobot_ID809() + :s(NULL){ + +} + +DFRobot_ID809::~DFRobot_ID809(){ + +} + +bool DFRobot_ID809::begin(Stream &s_){ + s = &s_; + if(s == NULL){ + return false; + } + return true; +} + +bool DFRobot_ID809::isConnected(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_TEST_CONNECTION, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + return true; + }else{ + return false; + } +} + +uint8_t DFRobot_ID809::setDeviceID(uint8_t deviceID){ + uint8_t data[5] = {0}; //data:1bytes Parameter Type+4bytes Parameter Value + data[1] = deviceID; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSecurityLevel(uint8_t securityLevel){ + uint8_t data[5] = {0}; + data[0] = 1; + data[1] = securityLevel; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setDuplicationCheck(uint8_t duplicationCheck){ + uint8_t data[5] = {0}; + data[0] = 2; + data[1] = duplicationCheck; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setBaudrate(eDeviceBaudrate_t baudrate){ + uint8_t data[5] = {0}; + data[0] = 3; + data[1] = baudrate; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSelfLearn(uint8_t selfLearn){ + uint8_t data[5] = {0}; + data[0] = 4; + data[1] = selfLearn; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDeviceID(){ + uint8_t data[1]; //data:1byte Parameter Type + data[0] = 0; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSecurityLevel(){ + uint8_t data[1]; + data[0] = 1; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDuplicationCheck(){ + uint8_t data[1]; + data[0] = 2; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getBaudrate(){ + uint8_t data[1]; + data[0] = 3; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSelfLearn(){ + uint8_t data[1]; + data[0] = 4; + uint8_t ret = getParam(data); + return ret; +} + +String DFRobot_ID809::getDeviceInfo(){ + char *data; + uint8_t result; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEVICE_INFO, NULL, 0); + sendPacket(header); + free(header); + result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::setModuleSN(const char* SN){ + char data[2]; + data[0] = MODULE_SN_SIZE; + if(strlen(SN) > MODULE_SN_SIZE){ + LDBG("The serial number exceeds 15 characters"); + return ERR_ID809; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_MODULE_SN, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + header = pack(DATA_TYPE, CMD_SET_MODULE_SN, SN, MODULE_SN_SIZE); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +String DFRobot_ID809::getModuleSN(){ + char *data; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_MODULE_SN, NULL, 0); + sendPacket(header); + free(header); + uint8_t result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount){ + char data[4] = {0}; + data[0] = mode; + data[2] = data[1] = color; + data[3] = blinkCount; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SLED_CTRL, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::detectFinger(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_FINGER_DETECT, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEmptyID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; //80 fingerprints at most, default to full range + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_EMPTY_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getStatusID(uint8_t ID){ + char data[2] = {0}; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_STATUS, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEnrollCount(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLL_COUNT, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +#define getID(A, V) (A[0 + V/8] & (0x01 << (V & 0x07))) +uint8_t DFRobot_ID809::getEnrolledIDList(uint8_t* list) +{ + char *data; + uint8_t i = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLLED_ID_LIST, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + uint16_t dataLen = buf[0]+(buf[1]<<8); + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + ret = responsePayload(data); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else{ + for(uint16_t j = 0; j < (dataLen*8); j++){ + if(getID(data, j) != 0){ + list[i] = j; + i++; + } + } + } + free(data); + return ret; +} + +uint8_t DFRobot_ID809::storeFingerprint(uint8_t ID){ + char data[4] = {0}; + uint8_t ret; + ret = merge(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number = 0; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; + +} + +uint8_t DFRobot_ID809::delFingerprint(uint8_t ID){ + char data[4] = {0}; + if(ID == DELALL){ + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + }else{ + data[0] = data[2] = ID; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEL_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::search(){ + char data[6] = {0}; + data[2] = 1; + data[4] = FINGERPRINT_CAPACITY; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SEARCH, data, 6); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::verify(uint8_t ID){ + char data[4] = {0}; + data[0] = ID; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_VERIFY, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::match(uint8_t RamBufferID0, uint8_t RamBufferID1){ + char data[4] = {0}; + data[0] = RamBufferID0; + data[2] = RamBufferID1; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenQuantity(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[2]; + } + return ret; +} + +uint8_t DFRobot_ID809::loadFingerprint(uint8_t ID, uint8_t RamBufferID){ + char data[4] = {0}; + data[0] = ID; + data[2] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::enterSleepState(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_ENTER_STANDBY_STATE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::setParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_PARAM, (const char *)data, 5); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::getParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_PARAM, (const char *)data, 1); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getImage(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::collectionFingerprint(uint16_t timeout){ //Collect fingerprint + uint16_t i = 0; + uint8_t ret; + if(_number > 2){ + _error = eErrorGatherOut; + LDBG("Exceed upper limit of acquisition times "); + return ERR_ID809; + } + while(!detectFinger()){ + if(timeout != 0){ + delay(10); + if(++i > timeout*10){ + _error = eErrorTimeOut; + LDBG("Acquisition timeout "); + LDBG("ret=");LDBG(ret); + return ERR_ID809; + } + } + } + ret = getImage(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + ret = generate(_number); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number++; + return ret; +} + +uint8_t DFRobot_ID809::generate(uint8_t RamBufferID){ + char data[2] = {0}; + data[0] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GENERATE, (const char *)data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::merge(){ + char data[3] = {0}; + data[2] = _number; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MERGE, data, 3); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +pCmdPacketHeader_t DFRobot_ID809::pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len){ + pCmdPacketHeader_t header; + uint16_t cks=0; + uint16_t dataLen; + if(type == CMD_TYPE){ //Structure of command packet, fixed 26 bytes:10(frame header)+14(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+16+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_PREFIX_CODE; + for(int i=0;i<16;i++){ + header->payload[i] = 0; + } + dataLen = 16; //Length of data to be replicated + }else{ //Structure of command data packet, unfixed length:10(frame header)+LEN(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+len+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_DATA_PREFIX_CODE; + dataLen = len; //Length of data to be replicated + } + header->SID = 0; + header->DID = 0; + header->CMD = cmd; + header->LEN = len; + if(len){ + memcpy(header->payload, payload, len); + } + cks = getCmdCKS(header); + memcpy(&header->payload[dataLen],&cks,2); + _PacketSize = sizeof(sCmdPacketHeader_t) + dataLen +2; + return header; +} + + +void DFRobot_ID809::sendPacket(pCmdPacketHeader_t header){ + s->write((uint8_t *)header,_PacketSize); +} + +uint8_t DFRobot_ID809::responsePayload(void* buf){ + sRcmPacketHeader_t header; + uint16_t dataLen,dataCount,cks; + uint8_t ch,ret; + int16_t type; + type = readPrefix(&header); + if(type == 1){ + LDBG("--recv timeout---"); + _error = eErrorRecvTimeout; + return ERR_ID809; + } + pRcmPacketHeader_t packet; + if(type == RCM_TYPE){ //Structure of response packet, fixed 26 bytes: 10(frame header)+14(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+14+2); + dataLen = 14+2; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + }else{ //Structure of response data packet, unfixed length: 10(frame header)+(LEN-2)(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+header.LEN); + dataLen = header.LEN; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + } + memcpy(packet, &header, 10); + dataCount = readN(packet->payload, dataLen); + cks = packet->payload[dataLen-2]+(packet->payload[dataLen-1]<<8); + ret = (header.RET&0xFF); + _error = (eError_t)ret; + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else if(dataLen != dataCount){ + LDBG("--recvRspPacket length error---"); + _error = eErrorRecvLength; + ret = ERR_ID809; + }else if(getRcmCKS(packet) != cks){ + LDBG("--recvRspPacket cks error---"); + _error = eErrorRecvCks; + ret = ERR_ID809; + }else{ + LDBG("--recvRspPacket OK---"); + memcpy(buf, packet->payload, dataLen); + } + free(packet); + packet = NULL; + return ret; +} + +uint16_t DFRobot_ID809::readPrefix( pRcmPacketHeader_t header ){ + uint8_t ch,ret; + typedef enum{ + RECV_HEADER_INIT, + RECV_HEADER_AA, + RECV_HEADER_A5, + RECV_HEADER_OK + }eRecvHeaderState; + eRecvHeaderState state = RECV_HEADER_INIT; + while(state != RECV_HEADER_OK){ //Can judge the received command packet and command data packet prefix at the same time + if(readN(&ch, 1) != 1){ + ret = 1; + return ret; + } + if((ch == 0xAA) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_AA; + continue; + }else if((ch == 0xA5) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_A5; + continue; + }else if((ch == 0x55) && (state == RECV_HEADER_AA)){ + state = RECV_HEADER_OK; + ret = RCM_TYPE; + continue; + }else if((ch == 0x5A) && (state == RECV_HEADER_A5)){ + state = RECV_HEADER_OK; + ret = DATA_TYPE; + continue; + }else{ + state = RECV_HEADER_INIT; + if(ch == 0xAA){ + state = RECV_HEADER_AA; + }else if(ch == 0xA5){ + state = RECV_HEADER_A5; + } + } + } + if(ret == RCM_TYPE){ + header->PREFIX = RCM_PREFIX_CODE; + }else if(ret == DATA_TYPE){ + header->PREFIX = RCM_DATA_PREFIX_CODE; + } + readN(&header->SID, 1); + readN(&header->DID, 1); + readN(&header->RCM, 2); + readN(&header->LEN, 2); + readN(&header->RET, 2); + return ret; +} + +size_t DFRobot_ID809::readN(void* buffer, size_t len){ + size_t offset = 0,left = len; + uint8_t *buf = (uint8_t*)buffer; + long long curr = millis(); + while(left){ + if(s->available()){ + buf[offset++] = s->read(); + left--; + } + if(millis() - curr > 5000){ + LDBG("----------!!!!!!!!!recv timeout----------"); + break; + } + } + return offset; +} + +uint16_t DFRobot_ID809::getCmdCKS(pCmdPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->CMD&0xFF; + cks += packet->CMD>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint8_t i = 0; i < packet->LEN; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +uint16_t DFRobot_ID809::getRcmCKS(pRcmPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->RCM&0xFF; + cks += packet->RCM>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + cks += packet->RET&0xFF; + cks += packet->RET>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint8_t i = 0; i < packet->LEN-2; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +const DFRobot_ID809::sErrorDescription_t DFRobot_ID809::errorDescriptionsTable[]={ + {eErrorSuccess, "Command processed successfully"}, + {eErrorFail, "Command processing failed"}, + {eErrorVerify, "1:1 comparison failed"}, + {eErrorIdentify, "Comparison with all fingerprints failed"}, + {eErrorTmplEmpty, "No fingerprint in designated ID"}, + {eErrorTmplNotEmpty, "Designated ID has fingerprint"}, + {eErrorAllTmplEmpty, "Module unregistered fingerprint"}, + {eErrorEmptyIDNoexist, "No registerable ID here"}, + {eErrorBrokenIDNoexist, "No broken fingerprint"}, + {eErrorInvalidTmplData, "Invalid desingated fingerprint data"}, + {eErrorDuplicationID, "The fingerprint has been registered"}, + {eErrorBadQuality, "Poor quality fingerprint image"}, + {eErrorMergeFail, "Fingerprint synthesis failed"}, + {eErrorNotAuthorized, "Communication password not authorized"}, + {eErrorMemory, "External Flash burning error"}, + {eErrorInvalidTmplNo, "Invalid designated ID"}, + {eErrorInvalidParam, "Incorrect parameter"}, + {eErrorTimeOut, "Acquisition timeout"}, + {eErrorGenCount, "Invalid number of fingerprint synthesis"}, + {eErrorInvalidBufferID, "Incorrect Buffer ID value"}, + {eErrorFPNotDetected, "No fingerprint input into fingerprint reader"}, + {eErrorFPCancel, "Command cancelled"}, + {eErrorRecvLength, "Wrong data length"}, + {eErrorRecvCks, "Wrong data check code"}, + {eErrorGatherOut, "Exceed upper limit of acquisition times"}, + {eErrorRecvTimeout,"Data reading timeout"} +}; + +String DFRobot_ID809::getErrorDescription() +{ + for(int i=0;i<sizeof(errorDescriptionsTable)/sizeof(errorDescriptionsTable[0]);i++){ + if(_error == errorDescriptionsTable[i].error){ + return errorDescriptionsTable[i].description; + } + } + return ""; +} diff --git a/FingerPrintRegister/src/src.cpp b/FingerPrintRegister/src/src.cpp new file mode 100644 index 0000000..0efe98a --- /dev/null +++ b/FingerPrintRegister/src/src.cpp @@ -0,0 +1,132 @@ + +/*! + * @file fingerprintRegistration.ino + * @brief Fingerprint Acquisition and Saving + * @n This module can be controlled by hardware serial or software serial + * @n Experiment Phenomenon:auto retrieve unregistered ID, collect fingerprint 3 times. + * @n In collecting, set LED ring to breathing lighting in blue, and then to quick blink in yellow 3 times when completed + * @n At last, save the fingerprint in an unregistered ID, the green LED lights up for 1s and turns off. + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](Eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 +*/ +#include <Arduino.h> +#include "DFRobot_ID809.h" + +#define COLLECT_NUMBER 3 //Fingerprint sampling times, can be set to 2-3 + +///*Use software serial when using UNO or NANO */ +//#if ((defined ARDUINO_AVR_UNO) || (defined ARDUINO_AVR_NANO)) +// #include <SoftwareSerial.h> +// SoftwareSerial Serial1(2, 3); //RX, TX +// #define FPSerial Serial1 +//#else +// #define FPSerial Serial1 +//#endif +#ifndef FPSerial + #define FPSerial Serial3 +#endif + +DFRobot_ID809 fingerprint; +//String desc; + +void setup(){ + /*Init print serial port */ + Serial.begin(9600); + /*Init FPSerial*/ + FPSerial.begin(115200); + /*Take FPSerial as communication port of the module*/ + fingerprint.begin(FPSerial); + /*Wait for Serial to open*/ + // while(!Serial); + /*Test whether the device can communicate properly with mainboard + Return true or false + */ + while(fingerprint.isConnected() == false){ + Serial.println("Communication with device failed, please check connection"); + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + delay(1000); + } +} + +uint8_t ID,i,ret; + +void loop(){ + /*Get an unregistered ID for saving fingerprint + Return ID when succeeded + Return ERR_ID809 if failed + */ + if((ID = fingerprint.getEmptyID()) == ERR_ID809){ + while(1){ + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + delay(1000); + } + } + Serial.print("unresistered ID,ID="); + Serial.println(ID); + i = 0; //Clear sampling times + /*Fingerprint sampling 3 times*/ + while(i < COLLECT_NUMBER){ + /*Set fingerprint LED ring mode, color, and number of blinks + Can be set as follows: + Parameter 1:<LEDMode> + eBreathing eFastBlink eKeepsOn eNormalClose + eFadeIn eFadeOut eSlowBlink + Parameter 2:<LEDColor> + eLEDGreen eLEDRed eLEDYellow eLEDBlue + eLEDCyan eLEDMagenta eLEDWhite + Parameter 3:<Number of blinks> 0 represents blinking all the time + This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eBreathing, /*LEDColor = */fingerprint.eLEDBlue, /*blinkCount = */0); + Serial.print("The fingerprint sampling of the"); + Serial.print(i+1); + Serial.println("(th) is being taken"); + Serial.println("Please press down your finger"); + /*Capture fingerprint image, 10s idle timeout, if timeout=0,Disable the collection timeout function + IF succeeded, return 0, otherwise, return ERR_ID809 + */ + if((fingerprint.collectionFingerprint(/*timeout = */10)) != ERR_ID809){ + /*Set fingerprint LED ring to quick blink in yellow 3 times */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eFastBlink, /*LEDColor = */fingerprint.eLEDYellow, /*blinkCount = */3); + Serial.println("Sampling succeeds"); + i++; //Sampling times +1 + }else{ + Serial.println("Sampling failed"); + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + } + Serial.println("Please release your finger"); + /*Wait for finger to release + Return 1 when finger is detected, otherwise return 0 + */ + while(fingerprint.detectFinger()); + } + + /*Save fingerprint in an unregistered ID */ + if(fingerprint.storeFingerprint(/*Empty ID = */ID) != ERR_ID809){ + Serial.print("Saving succeed,ID="); + Serial.println(ID); + Serial.println("-----------------------------"); + /*Set fingerprint LED ring to always ON in green */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eKeepsOn, /*LEDColor = */fingerprint.eLEDGreen, /*blinkCount = */0); + delay(1000); + /*Turn off fingerprint LED ring */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eNormalClose, /*LEDColor = */fingerprint.eLEDBlue, /*blinkCount = */0); + delay(1000); + }else{ + Serial.println("Saving failed"); + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + } +} diff --git a/FingerPrintUnregister/include/DFRobot_ID809.h b/FingerPrintUnregister/include/DFRobot_ID809.h new file mode 100644 index 0000000..4cb90d9 --- /dev/null +++ b/FingerPrintUnregister/include/DFRobot_ID809.h @@ -0,0 +1,494 @@ +/*! + * @file DFRobot_ID809.h + * @brief Define basic structure of DFRobot_ID809 class + * @n This is an library for capacitive fingerprint module + * @n Main functions: fingerprint image capturing, fingerprint comparison, fingerprint deletion + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#ifndef _DFRobot_ID809_H +#define _DFRobot_ID809_H + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif +#include <Wire.h> + +#include <stdint.h> + +//Open this macro to see the detailed running process of the program + +//#define ENABLE_DBG +#ifdef ENABLE_DBG +#define LDBG(...) if(dbg) {dbg->print("["); dbg->print(__FUNCTION__); dbg->print("(): "); dbg->print(__LINE__); dbg->print(" ] "); dbg->println(__VA_ARGS__);} +#else +#define LDBG(...) +#endif + +extern Stream *dbg; + + /* + Frame struct of command packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t CMD; + uint16_t LEN; + uint8_t payload[0]; +}__attribute__ ((packed)) sCmdPacketHeader_t, *pCmdPacketHeader_t; + + /* + Frame struct of response packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t RCM; + uint16_t LEN; + uint16_t RET; + uint8_t payload[0]; +}__attribute__ ((packed)) sRcmPacketHeader_t, *pRcmPacketHeader_t; + + + + +class DFRobot_ID809{ +public: + +#define FINGERPRINT_CAPACITY 80 //Fingerprint module capacity +#define MODULE_SN_SIZE 16 //Module SN length + + +#define DELALL 0xFF //Delete all fingerprints + +#define CMD_PREFIX_CODE 0xAA55 //Command packet prefix code +#define RCM_PREFIX_CODE 0x55AA //Response packet prefix code +#define CMD_DATA_PREFIX_CODE 0xA55A //Command data packet prefix code +#define RCM_DATA_PREFIX_CODE 0x5AA5 //Response data packet prefix code + +#define CMD_TYPE 0xF0 //Command packet type +#define RCM_TYPE 0xF0 //Response packet type +#define DATA_TYPE 0x0F //Data packet type + +#define CMD_TEST_CONNECTION 0X0001 //Test connection +#define CMD_SET_PARAM 0X0002 //Set parameter +#define CMD_GET_PARAM 0X0003 //Read parameter +#define CMD_DEVICE_INFO 0X0004 //Read device information +#define CMD_SET_MODULE_SN 0X0008 //Set module serial number +#define CMD_GET_MODULE_SN 0X0009 //Read module serial number +#define CMD_ENTER_STANDBY_STATE 0X000C //Enter sleep mode +#define CMD_GET_IMAGE 0X0020 //Capture fingerprint image +#define CMD_FINGER_DETECT 0X0021 //Detect fingerprint + #define CMD_UP_IMAGE_CODE 0X0022 //Upload fingerprint image to host + #define CMD_DOWN_IMAGE 0X0023 //Download fingerprint image to module +#define CMD_SLED_CTRL 0X0024 //Control collector backlight +#define CMD_STORE_CHAR 0X0040 //Save fingerprint template data into fingerprint library +#define CMD_LOAD_CHAR 0X0041 //Read fingerprint in module and save it in RAMBUFFER temporarily + #define CMD_UP_CHAR 0X0042 //Upload the fingerprint template saved in RAMBUFFER to host + #define CMD_DOWN_CHAR 0X0043 //Download fingerprint template to module designated RAMBUFFER +#define CMD_DEL_CHAR 0X0044 //Delete fingerprint in specific ID range +#define CMD_GET_EMPTY_ID 0X0045 //Get the first registerable ID in specific ID range +#define CMD_GET_STATUS 0X0046 //Check if the designated ID has been registered +#define CMD_GET_BROKEN_ID 0X0047 //Check whether there is damaged data in fingerprint library of specific range +#define CMD_GET_ENROLL_COUNT 0X0048 //Get the number of registered fingerprints in specific ID range +#define CMD_GET_ENROLLED_ID_LIST 0X0049 //Get registered ID list +#define CMD_GENERATE 0X0060 //Generate template from the fingerprint images saved in IMAGEBUFFER temporarily +#define CMD_MERGE 0X0061 //Synthesize fingerprint template data +#define CMD_MATCH 0X0062 //Compare templates in 2 designated RAMBUFFER +#define CMD_SEARCH 0X0063 //1:N Recognition in specific ID range +#define CMD_VERIFY 0X0064 //Compare specific RAMBUFFER template with specific ID template in fingerprint library + +#define ERR_SUCCESS 0x00 //Command processed successfully +#define ERR_ID809 0xFF //error + + +public: + + typedef enum{ + eBreathing = 1, //Breathing + eFastBlink, //Quick blink + eKeepsOn, //On + eNormalClose, //Off + eFadeIn, //Fade in + eFadeOut, //Fade out + eSlowBlink //Slow blink + }eLEDMode_t; + + typedef enum{ + eLEDGreen = 1, //green + eLEDRed, //red + eLEDYellow, //yellow + eLEDBlue, //blue + eLEDCyan, //cyan + eLEDMagenta, //magenta + eLEDWhite //white + }eLEDColor_t; + + typedef enum{ + e9600bps = 1, + e19200bps, + e38400bps, + e57600bps, + e115200bps + }eDeviceBaudrate_t; + + typedef enum{ + eErrorSuccess = 0x00, //Command processed successfully + eErrorFail = 0x01, //Command processing failed + eErrorVerify = 0x10, //1:1 Templates comparison in specific ID failed + eErrorIdentify = 0x11, //1:N comparison has been made, no same templates here + eErrorTmplEmpty = 0x12, //No registered template in the designated ID + eErrorTmplNotEmpty = 0x13, //Template already exists in the specified ID + eErrorAllTmplEmpty = 0x14, //No registered Template + eErrorEmptyIDNoexist = 0x15, //No registerable Template ID + eErrorBrokenIDNoexist = 0x16, //No damaged Template + eErrorInvalidTmplData = 0x17, //The designated Template Data is invalid + eErrorDuplicationID = 0x18, //The fingerprint has been registered + eErrorBadQuality = 0x19, //Poor quality fingerprint image + eErrorMergeFail = 0x1A, //Template synthesis failed + eErrorNotAuthorized = 0x1B, //Communication password not authorized + eErrorMemory = 0x1C, //Error in exernal Flash burning + eErrorInvalidTmplNo = 0x1D, //The designated template ID is invalid + eErrorInvalidParam = 0x22, //Incorrect parameter has been used + eErrorTimeOut = 0x23, //Acquisition timeout + eErrorGenCount = 0x25, //Invalid number of fingerprint synthesis + eErrorInvalidBufferID = 0x26, //Wrong Buffer ID value + eErrorFPNotDetected = 0x28, //No fingerprint input into fingerprint reader + eErrorFPCancel = 0x41, //Command cancelled + eErrorRecvLength = 0x42, //Wrong length of recieved data + eErrorRecvCks = 0x43, //Wrong check code + eErrorGatherOut = 0x45, //Exceed upper limit of acquisition times + eErrorRecvTimeout = 0x46 //Communication timeout + }eError_t; + + typedef struct{ + /**< Gesture enumeration variable X */ + eError_t error; + /**< Description about the gesture enumeration variable X */ + const char * description; + }sErrorDescription_t; + +public: + DFRobot_ID809(); + ~DFRobot_ID809(); + + /** + * @brief Init communication port + * @param Software serial or hardware serial + * @return true or false + */ + bool begin(Stream &s_); + + /** + * @brief Test whether the module connection is ok + * @return true or false + */ + bool isConnected(); + + /** + * @brief Set module ID + * @param ID:1-255 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDeviceID(uint8_t deviceID); + + /** + * @brief Set module security level + * @param security level:1-5 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSecurityLevel(uint8_t securityLevel); + + /** + * @brief Set module fingerprint replication check (Check whether the fingperint has been registered when saving it) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDuplicationCheck(uint8_t duplicationCheck); + + /** + * @brief Set module baud rate + * @param Baudrate:in typedef enum eDeviceBaudrate_t + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setBaudrate(eDeviceBaudrate_t baudrate); + + /** + * @brief Set module self-learning function (Update fingeprint when fingerprint comparison succeeds) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSelfLearn(uint8_t selfLearn); + + /** + * @brief Read module ID + * @return IDå·:1-255 or ERR_ID809 + */ + uint8_t getDeviceID(); + + /** + * @brief Read module security level + * @return Security level:1-5 or ERR_ID809 + */ + uint8_t getSecurityLevel(); + + /** + * @brief Read module fingerprint replication check status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getDuplicationCheck(); + + /** + * @brief Read module baud rate + * @return Baudrate:in typedef enum eDEVICE_BAUDRATE_t or ERR_ID809 + */ + uint8_t getBaudrate(); + + /** + * @brief Read module self-learning function status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getSelfLearn(); + + /** + * @brief Read device number + * @return Device number + */ + String getDeviceInfo(); + + /** + * @brief Set serial number + * @param String pointer + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setModuleSN(const char* SN); + /** + * @brief Read serial number + * @return Serial number + */ + String getModuleSN(); + + /** + * @brief Set LED + * @param mode:in typedef enum eLEDMode_t + * @param color:in typedef enum eLEDColor_t + * @param blink Count: 00 represents blinking all the time + * @This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + * @return 0(succeed) or ERR_ID809 + */ + uint8_t ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount); + + /** + * @brief Detect if there is finger touched + * @return 1(Touched) or 0(No touch) + */ + uint8_t detectFinger(); + + /** + * @brief Get the first registerable ID + * @return Registerable ID or ERR_ID809 + */ + uint8_t getEmptyID(); + + /** + * @brief Check if the ID has been registered + * @return 0(Registered), 1(Unregistered) or ERR_ID809 + */ + uint8_t getStatusID(uint8_t ID); + + /** + * @brief Get the number of registered users + * @return Number of registered users or ERR_ID809 + */ + uint8_t getEnrollCount(); + + /** + * @brief Get registered user list + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getEnrolledIDList(uint8_t* list); + + /** + * @brief Fingerprint acquisition + * @return 0(succeed) or ERR_ID809 + */ + uint8_t collectionFingerprint(uint16_t timeout); + + /** + * @brief Save fingerprint + * @param Fingerprint ID + * @return 0(succeed) or ERR_ID809 + */ + uint8_t storeFingerprint(uint8_t ID); + + /** + * @brief Delete fingerprint + * @param Delete ID or DELALL(delete all) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t delFingerprint(uint8_t ID); + + /** + * @brief Match the fingerprint with all fingeprints + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t search(); + + /** + * @brief Match the fingerprint with specific fingerprint + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t verify(uint8_t ID); + + /** + * @brief Compare templates in two specific RamBuffers + * @param RamBuffer number + * @param RamBuffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t match(uint8_t RamBufferID0, uint8_t RamBufferID1); + + /** + * @brief Get the number of damaged fingerprints + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenQuantity(); + + /** + * @brief Get the first damaged fingerprint ID + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenID(); + + /** + * @brief Take out fingerprint template, temporarily save into RamBuffer + * @param Fingerprint ID + * @param RamBuffer number 0-2 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t loadFingerprint(uint8_t ID, uint8_t RamBufferID); + + /** + * @brief Enter sleep mode + * @return 0(succeed) or ERR_ID809 + */ + uint8_t enterSleepState(); + + /** + * @brief Get error information + * @return Text description of error information + */ + String getErrorDescription(); + + bool setDbgSerial(Stream &s_){dbg = &s_; return true;} +protected: + /** + * @brief Set parameter + * @param Data type+ data + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setParam(uint8_t* data); + + /** + * @brief Read parameter + * @param Data type + * @return data or ERR_ID809 + */ + uint8_t getParam(uint8_t* data); + + /** + * @brief Capture fingerprint image + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getImage(); + + /** + * @brief Take image as template + * @param Ram Buffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t generate(uint8_t RamBufferID); + + /** + * @brief Fingerprint synthesis + * @return 0(succeed) or ERR_ID809 + */ + uint8_t merge(); + + /** + * @brief Packing data frame + * @param Data type:CMD_TYPE or DATA_TYPE + * @param Command + * @param Data + * @param Length + * @return Data frame + */ + pCmdPacketHeader_t pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len); + + /** + * @brief Send data + * @param Data frame + */ + void sendPacket(pCmdPacketHeader_t header); + + /** + * @brief Read byte + * @param Pointer for saving data + * @param Length of data to be received + * @return Actual received data length + */ + size_t readN(void* buf_, size_t len); + + /** + * @brief Read frame header + * @param Frame header struct of response packet + * @return Response packet type:RCM_TYPE,DATA_TYPE or 1(reading timeout) + */ + uint16_t readPrefix( pRcmPacketHeader_t header ); + + /** + * @brief Read data + * @param Pointer for saving data + * @return 0(success) or ERR_ID809 + */ + uint8_t responsePayload(void* buf); + + /** + * @brief Get command packet CKS + * @param Command packet frame + * @return CKS + */ + uint16_t getCmdCKS(pCmdPacketHeader_t packet); + + /** + * @brief Get response packet CKS + * @param Response packet frame + * @return CKS + */ + uint16_t getRcmCKS(pRcmPacketHeader_t packet); + +private: + Stream *s; + uint8_t buf[20]; //For saving response packet data + pCmdPacketHeader_t sendHeader; + pRcmPacketHeader_t recHeader; + + static const sErrorDescription_t /*PROGMEM*/ errorDescriptionsTable[26]; //Error information list + + uint8_t _number = 0; //Fingerprint acquisistion times + eError_t _error; //Error code + uint16_t _PacketSize = 0; //Data packet length to be sent +}; + +#endif diff --git a/FingerPrintUnregister/platformio.ini b/FingerPrintUnregister/platformio.ini new file mode 100644 index 0000000..97cb9cb --- /dev/null +++ b/FingerPrintUnregister/platformio.ini @@ -0,0 +1,9 @@ +[env:teensy_u2f] + +platform = teensy +framework = arduino +board = teensy31 +build_flags = + -D USB_SERIAL + -D TEENSY_OPT_SMALLEST_CODE + diff --git a/FingerPrintUnregister/src/DFRobot_ID809.cpp b/FingerPrintUnregister/src/DFRobot_ID809.cpp new file mode 100644 index 0000000..f2aa3a2 --- /dev/null +++ b/FingerPrintUnregister/src/DFRobot_ID809.cpp @@ -0,0 +1,748 @@ +/*! + * @file DFRobot_ID809.cpp + * @brief Define the basic structure of DFRobot_ID809 class and the implementation of underlying methods + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#include "DFRobot_ID809.h" +#include <Arduino.h> +#include <string.h> +#include <stdio.h> +Stream *dbg=NULL; + +DFRobot_ID809::DFRobot_ID809() + :s(NULL){ + +} + +DFRobot_ID809::~DFRobot_ID809(){ + +} + +bool DFRobot_ID809::begin(Stream &s_){ + s = &s_; + if(s == NULL){ + return false; + } + return true; +} + +bool DFRobot_ID809::isConnected(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_TEST_CONNECTION, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + return true; + }else{ + return false; + } +} + +uint8_t DFRobot_ID809::setDeviceID(uint8_t deviceID){ + uint8_t data[5] = {0}; //data:1bytes Parameter Type+4bytes Parameter Value + data[1] = deviceID; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSecurityLevel(uint8_t securityLevel){ + uint8_t data[5] = {0}; + data[0] = 1; + data[1] = securityLevel; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setDuplicationCheck(uint8_t duplicationCheck){ + uint8_t data[5] = {0}; + data[0] = 2; + data[1] = duplicationCheck; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setBaudrate(eDeviceBaudrate_t baudrate){ + uint8_t data[5] = {0}; + data[0] = 3; + data[1] = baudrate; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSelfLearn(uint8_t selfLearn){ + uint8_t data[5] = {0}; + data[0] = 4; + data[1] = selfLearn; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDeviceID(){ + uint8_t data[1]; //data:1byte Parameter Type + data[0] = 0; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSecurityLevel(){ + uint8_t data[1]; + data[0] = 1; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDuplicationCheck(){ + uint8_t data[1]; + data[0] = 2; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getBaudrate(){ + uint8_t data[1]; + data[0] = 3; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSelfLearn(){ + uint8_t data[1]; + data[0] = 4; + uint8_t ret = getParam(data); + return ret; +} + +String DFRobot_ID809::getDeviceInfo(){ + char *data; + uint8_t result; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEVICE_INFO, NULL, 0); + sendPacket(header); + free(header); + result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::setModuleSN(const char* SN){ + char data[2]; + data[0] = MODULE_SN_SIZE; + if(strlen(SN) > MODULE_SN_SIZE){ + LDBG("The serial number exceeds 15 characters"); + return ERR_ID809; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_MODULE_SN, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + header = pack(DATA_TYPE, CMD_SET_MODULE_SN, SN, MODULE_SN_SIZE); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +String DFRobot_ID809::getModuleSN(){ + char *data; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_MODULE_SN, NULL, 0); + sendPacket(header); + free(header); + uint8_t result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount){ + char data[4] = {0}; + data[0] = mode; + data[2] = data[1] = color; + data[3] = blinkCount; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SLED_CTRL, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::detectFinger(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_FINGER_DETECT, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEmptyID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; //80 fingerprints at most, default to full range + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_EMPTY_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getStatusID(uint8_t ID){ + char data[2] = {0}; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_STATUS, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEnrollCount(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLL_COUNT, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +#define getID(A, V) (A[0 + V/8] & (0x01 << (V & 0x07))) +uint8_t DFRobot_ID809::getEnrolledIDList(uint8_t* list) +{ + char *data; + uint8_t i = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLLED_ID_LIST, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + uint16_t dataLen = buf[0]+(buf[1]<<8); + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + ret = responsePayload(data); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else{ + for(uint16_t j = 0; j < (dataLen*8); j++){ + if(getID(data, j) != 0){ + list[i] = j; + i++; + } + } + } + free(data); + return ret; +} + +uint8_t DFRobot_ID809::storeFingerprint(uint8_t ID){ + char data[4] = {0}; + uint8_t ret; + ret = merge(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number = 0; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; + +} + +uint8_t DFRobot_ID809::delFingerprint(uint8_t ID){ + char data[4] = {0}; + if(ID == DELALL){ + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + }else{ + data[0] = data[2] = ID; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEL_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::search(){ + char data[6] = {0}; + data[2] = 1; + data[4] = FINGERPRINT_CAPACITY; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SEARCH, data, 6); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::verify(uint8_t ID){ + char data[4] = {0}; + data[0] = ID; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_VERIFY, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::match(uint8_t RamBufferID0, uint8_t RamBufferID1){ + char data[4] = {0}; + data[0] = RamBufferID0; + data[2] = RamBufferID1; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenQuantity(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[2]; + } + return ret; +} + +uint8_t DFRobot_ID809::loadFingerprint(uint8_t ID, uint8_t RamBufferID){ + char data[4] = {0}; + data[0] = ID; + data[2] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::enterSleepState(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_ENTER_STANDBY_STATE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::setParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_PARAM, (const char *)data, 5); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::getParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_PARAM, (const char *)data, 1); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getImage(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::collectionFingerprint(uint16_t timeout){ //Collect fingerprint + uint16_t i = 0; + uint8_t ret; + if(_number > 2){ + _error = eErrorGatherOut; + LDBG("Exceed upper limit of acquisition times "); + return ERR_ID809; + } + while(!detectFinger()){ + if(timeout != 0){ + delay(10); + if(++i > timeout*10){ + _error = eErrorTimeOut; + LDBG("Acquisition timeout "); + LDBG("ret=");LDBG(ret); + return ERR_ID809; + } + } + } + ret = getImage(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + ret = generate(_number); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number++; + return ret; +} + +uint8_t DFRobot_ID809::generate(uint8_t RamBufferID){ + char data[2] = {0}; + data[0] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GENERATE, (const char *)data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::merge(){ + char data[3] = {0}; + data[2] = _number; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MERGE, data, 3); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +pCmdPacketHeader_t DFRobot_ID809::pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len){ + pCmdPacketHeader_t header; + uint16_t cks=0; + uint16_t dataLen; + if(type == CMD_TYPE){ //Structure of command packet, fixed 26 bytes:10(frame header)+14(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+16+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_PREFIX_CODE; + for(int i=0;i<16;i++){ + header->payload[i] = 0; + } + dataLen = 16; //Length of data to be replicated + }else{ //Structure of command data packet, unfixed length:10(frame header)+LEN(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+len+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_DATA_PREFIX_CODE; + dataLen = len; //Length of data to be replicated + } + header->SID = 0; + header->DID = 0; + header->CMD = cmd; + header->LEN = len; + if(len){ + memcpy(header->payload, payload, len); + } + cks = getCmdCKS(header); + memcpy(&header->payload[dataLen],&cks,2); + _PacketSize = sizeof(sCmdPacketHeader_t) + dataLen +2; + return header; +} + + +void DFRobot_ID809::sendPacket(pCmdPacketHeader_t header){ + s->write((uint8_t *)header,_PacketSize); +} + +uint8_t DFRobot_ID809::responsePayload(void* buf){ + sRcmPacketHeader_t header; + uint16_t dataLen,dataCount,cks; + uint8_t ch,ret; + int16_t type; + type = readPrefix(&header); + if(type == 1){ + LDBG("--recv timeout---"); + _error = eErrorRecvTimeout; + return ERR_ID809; + } + pRcmPacketHeader_t packet; + if(type == RCM_TYPE){ //Structure of response packet, fixed 26 bytes: 10(frame header)+14(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+14+2); + dataLen = 14+2; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + }else{ //Structure of response data packet, unfixed length: 10(frame header)+(LEN-2)(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+header.LEN); + dataLen = header.LEN; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + } + memcpy(packet, &header, 10); + dataCount = readN(packet->payload, dataLen); + cks = packet->payload[dataLen-2]+(packet->payload[dataLen-1]<<8); + ret = (header.RET&0xFF); + _error = (eError_t)ret; + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else if(dataLen != dataCount){ + LDBG("--recvRspPacket length error---"); + _error = eErrorRecvLength; + ret = ERR_ID809; + }else if(getRcmCKS(packet) != cks){ + LDBG("--recvRspPacket cks error---"); + _error = eErrorRecvCks; + ret = ERR_ID809; + }else{ + LDBG("--recvRspPacket OK---"); + memcpy(buf, packet->payload, dataLen); + } + free(packet); + packet = NULL; + return ret; +} + +uint16_t DFRobot_ID809::readPrefix( pRcmPacketHeader_t header ){ + uint8_t ch,ret; + typedef enum{ + RECV_HEADER_INIT, + RECV_HEADER_AA, + RECV_HEADER_A5, + RECV_HEADER_OK + }eRecvHeaderState; + eRecvHeaderState state = RECV_HEADER_INIT; + while(state != RECV_HEADER_OK){ //Can judge the received command packet and command data packet prefix at the same time + if(readN(&ch, 1) != 1){ + ret = 1; + return ret; + } + if((ch == 0xAA) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_AA; + continue; + }else if((ch == 0xA5) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_A5; + continue; + }else if((ch == 0x55) && (state == RECV_HEADER_AA)){ + state = RECV_HEADER_OK; + ret = RCM_TYPE; + continue; + }else if((ch == 0x5A) && (state == RECV_HEADER_A5)){ + state = RECV_HEADER_OK; + ret = DATA_TYPE; + continue; + }else{ + state = RECV_HEADER_INIT; + if(ch == 0xAA){ + state = RECV_HEADER_AA; + }else if(ch == 0xA5){ + state = RECV_HEADER_A5; + } + } + } + if(ret == RCM_TYPE){ + header->PREFIX = RCM_PREFIX_CODE; + }else if(ret == DATA_TYPE){ + header->PREFIX = RCM_DATA_PREFIX_CODE; + } + readN(&header->SID, 1); + readN(&header->DID, 1); + readN(&header->RCM, 2); + readN(&header->LEN, 2); + readN(&header->RET, 2); + return ret; +} + +size_t DFRobot_ID809::readN(void* buffer, size_t len){ + size_t offset = 0,left = len; + uint8_t *buf = (uint8_t*)buffer; + long long curr = millis(); + while(left){ + if(s->available()){ + buf[offset++] = s->read(); + left--; + } + if(millis() - curr > 5000){ + LDBG("----------!!!!!!!!!recv timeout----------"); + break; + } + } + return offset; +} + +uint16_t DFRobot_ID809::getCmdCKS(pCmdPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->CMD&0xFF; + cks += packet->CMD>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint8_t i = 0; i < packet->LEN; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +uint16_t DFRobot_ID809::getRcmCKS(pRcmPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->RCM&0xFF; + cks += packet->RCM>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + cks += packet->RET&0xFF; + cks += packet->RET>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint8_t i = 0; i < packet->LEN-2; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +const DFRobot_ID809::sErrorDescription_t DFRobot_ID809::errorDescriptionsTable[]={ + {eErrorSuccess, "Command processed successfully"}, + {eErrorFail, "Command processing failed"}, + {eErrorVerify, "1:1 comparison failed"}, + {eErrorIdentify, "Comparison with all fingerprints failed"}, + {eErrorTmplEmpty, "No fingerprint in designated ID"}, + {eErrorTmplNotEmpty, "Designated ID has fingerprint"}, + {eErrorAllTmplEmpty, "Module unregistered fingerprint"}, + {eErrorEmptyIDNoexist, "No registerable ID here"}, + {eErrorBrokenIDNoexist, "No broken fingerprint"}, + {eErrorInvalidTmplData, "Invalid desingated fingerprint data"}, + {eErrorDuplicationID, "The fingerprint has been registered"}, + {eErrorBadQuality, "Poor quality fingerprint image"}, + {eErrorMergeFail, "Fingerprint synthesis failed"}, + {eErrorNotAuthorized, "Communication password not authorized"}, + {eErrorMemory, "External Flash burning error"}, + {eErrorInvalidTmplNo, "Invalid designated ID"}, + {eErrorInvalidParam, "Incorrect parameter"}, + {eErrorTimeOut, "Acquisition timeout"}, + {eErrorGenCount, "Invalid number of fingerprint synthesis"}, + {eErrorInvalidBufferID, "Incorrect Buffer ID value"}, + {eErrorFPNotDetected, "No fingerprint input into fingerprint reader"}, + {eErrorFPCancel, "Command cancelled"}, + {eErrorRecvLength, "Wrong data length"}, + {eErrorRecvCks, "Wrong data check code"}, + {eErrorGatherOut, "Exceed upper limit of acquisition times"}, + {eErrorRecvTimeout,"Data reading timeout"} +}; + +String DFRobot_ID809::getErrorDescription() +{ + for(int i=0;i<sizeof(errorDescriptionsTable)/sizeof(errorDescriptionsTable[0]);i++){ + if(_error == errorDescriptionsTable[i].error){ + return errorDescriptionsTable[i].description; + } + } + return ""; +} diff --git a/FingerPrintUnregister/src/platformio.ini b/FingerPrintUnregister/src/platformio.ini new file mode 100644 index 0000000..e69de29 diff --git a/FingerPrintUnregister/src/src.cpp b/FingerPrintUnregister/src/src.cpp new file mode 100644 index 0000000..a1de0fb --- /dev/null +++ b/FingerPrintUnregister/src/src.cpp @@ -0,0 +1,110 @@ +/*! + * @file fingerprintDeletion.ino + * @brief Delete a specific fingerprint + * @n Experiment phenomenon:press your finger on the sensor, if this fingerprint is registered, delete it and LED turns on in green. + If it is unregistered or fingerprint collection fails, LED light turns on in red. + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](Eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/DFRobot/DFRobot_ID809 +*/ +#include "DFRobot_ID809.h" + +///*Use software serial when using UNO or NANO */ +//#if ((defined ARDUINO_AVR_UNO) || (defined ARDUINO_AVR_NANO)) +// #include <SoftwareSerial.h> +// SoftwareSerial Serial1(2, 3); //RX, TX +// #define FPSerial Serial1 +//#else +// #define FPSerial Serial1 +//#endif + +#define FPSerial Serial3 + +DFRobot_ID809 fingerprint; +//String desc; + +void setup(){ + /*Init print serial port*/ + Serial.begin(9600); + /*Init FPSerial*/ + FPSerial.begin(115200); + /*Take FPSerial as communication serial port of the fingerprint module */ + fingerprint.begin(FPSerial); + /*Wait for Serial to open*/ + while(!Serial); + /*Test whether the device can properly communicate with mainboard + Return true or false + */ + while(fingerprint.isConnected() == false){ + Serial.println("Communication with device failed, please check connection"); + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + delay(1000); + } +} + +void loop(){ + uint8_t ret = 0; + Serial.println("Press your finger on the sensor to delete the fingerprint"); + /*Set fingerprint LED ring mode, color, and number of blinks + Can be set as follows: + Parameter 1:<LEDMode> + eBreathing eFastBlink eKeepsOn eNormalClose + eFadeIn eFadeOut eSlowBlink + Parameter 2:<LEDColor> + eLEDGreen eLEDRed eLEDYellow eLEDBlue + eLEDCyan eLEDMagenta eLEDWhite + Parameter 3:<Number of blinks> 0 represents blinking all the time + This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eBreathing, /*LEDColor = */fingerprint.eLEDBlue, /*blinkCount = */0); + /*Capture fingerprint image, 10s idle timeout, if timeout=0,Disable the collection timeout function + If succeed return 0, otherwise return ERR_ID809 + */ + if((fingerprint.collectionFingerprint(/*timeout=*/10)) != ERR_ID809){ + /*Compare the captured fingerprint with all the fingerprints in the fingerprint library + Return fingerprint ID(1-80) if succeed, return 0 when failed + */ + ret = fingerprint.search(); + if(ret != 0){ + /*Delete the fingerprint of this ID*/ + fingerprint.delFingerprint(/*Fingerprint ID = */ret); + //fingerprint.delFingerprint(DELALL); //Delete all fingerprints + Serial.print("delete succeeds,ID="); + Serial.println(ret); + /*Set fingerprint LED ring to always ON in green */ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eKeepsOn, /*LEDColor = */fingerprint.eLEDGreen, /*blinkCount = */0); + }else{ + Serial.println("Fingerprint is unregistered"); + /*Set fingerprint LED ring to always ON in red*/ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eKeepsOn, /*LEDColor = */fingerprint.eLEDRed, /*blinkCount = */0); + } + }else{ + Serial.println("Capturing fails"); + /*Get error code information*/ + //desc = fingerprint.getErrorDescription(); + //Serial.println(desc); + /*Set fingerprint LED ring to always ON in red*/ + fingerprint.ctrlLED(/*LEDMode = */fingerprint.eKeepsOn, /*LEDColor = */fingerprint.eLEDRed, /*blinkCount = */0); + } + Serial.println("Please release your finger"); + /*Wait for finger to release + Return 1 when finger is detected, otherwise return 0 + */ + while(fingerprint.detectFinger()); + /*Check whether the fingerprint ID has been registered + Return 1 if registered, otherwise return 0 + */ +// if(fingerprint.getStatusID(/*Fingerprint ID = */ret)){ +// Serial.println("ID has been registered"); +// }else{ +// Serial.println("ID is unregistered"); +// } + Serial.println("-----------------------------"); + delay(1000); +} diff --git a/RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.cpp b/RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.cpp new file mode 100644 index 0000000..d49f6f4 --- /dev/null +++ b/RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.cpp @@ -0,0 +1,1089 @@ +/*! + * @file DFRobot_ID809.cpp + * @brief Define the basic structure of DFRobot_ID809 class and the implementation of underlying methods + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#include <DFRobot_ID809.h> +#include <Arduino.h> +#include <string.h> +#include <stdio.h> +Stream *dbg=NULL; + +DFRobot_ID809::DFRobot_ID809() + :s(NULL){ + +} + +DFRobot_ID809::~DFRobot_ID809(){ + +} + +bool DFRobot_ID809::begin(Stream &s_){ + s = &s_; + String str = getDeviceInfo(); + //Serial.println(str[str.length()-1]); + if(str[str.length()-1] == '4'){ + + FINGERPRINT_CAPACITY = 80 ; + + //Serial.println(str[str.length()-1]); + }else if(str[str.length()-1] == '3'){ + //Serial.println(str[str.length()-1]); + FINGERPRINT_CAPACITY = 200 ; + + } + + if(s == NULL){ + return false; + } + return true; +} + +bool DFRobot_ID809::isConnected(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_TEST_CONNECTION, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + return true; + }else{ + return false; + } +} + +uint8_t DFRobot_ID809::setDeviceID(uint8_t deviceID){ + uint8_t data[5] = {0}; //data:1bytes Parameter Type+4bytes Parameter Value + data[1] = deviceID; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSecurityLevel(uint8_t securityLevel){ + uint8_t data[5] = {0}; + data[0] = 1; + data[1] = securityLevel; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setDuplicationCheck(uint8_t duplicationCheck){ + uint8_t data[5] = {0}; + data[0] = 2; + data[1] = duplicationCheck; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setBaudrate(eDeviceBaudrate_t baudrate){ + uint8_t data[5] = {0}; + data[0] = 3; + data[1] = baudrate; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSelfLearn(uint8_t selfLearn){ + uint8_t data[5] = {0}; + data[0] = 4; + data[1] = selfLearn; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDeviceID(){ + uint8_t data[1]; //data:1byte Parameter Type + data[0] = 0; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSecurityLevel(){ + uint8_t data[1]; + data[0] = 1; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDuplicationCheck(){ + uint8_t data[1]; + data[0] = 2; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getBaudrate(){ + uint8_t data[1]; + data[0] = 3; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSelfLearn(){ + uint8_t data[1]; + data[0] = 4; + uint8_t ret = getParam(data); + return ret; +} + +String DFRobot_ID809::getDeviceInfo(){ + char *data; + uint8_t result; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEVICE_INFO, NULL, 0); + sendPacket(header); + free(header); + result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::setModuleSN(const char* SN){ + char data[2]; + data[0] = MODULE_SN_SIZE; + if(strlen(SN) > MODULE_SN_SIZE){ + LDBG("The serial number exceeds 15 characters"); + return ERR_ID809; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_MODULE_SN, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + header = pack(DATA_TYPE, CMD_SET_MODULE_SN, SN, MODULE_SN_SIZE); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getTemplate(uint16_t id,uint8_t * temp){ + char data[4]; + data[0] = id; + data[1] = 0; + data[2] = 0; + data[3] = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + data[0] = 0; + data[1] = 0; + header = pack(CMD_TYPE, CMD_UP_CHAR, data, 2); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + ret = responsePayload(temp); + + return ret; +} + +uint8_t DFRobot_ID809::downLoadTemplate(uint16_t id,uint8_t * temp){ + + char data[4]; + data[0] = 0xf2; + data[1] = 3; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_CHAR, data, 2); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(0x3f2 +1); + tempData[0] = 0; + tempData[1] = 0; + memcpy(tempData+2,temp,0x3f0); + + + header = pack(DATA_TYPE, CMD_DOWN_CHAR, tempData, 0x3f2); + + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + free(tempData); + + + return store(id); +} + +uint8_t DFRobot_ID809::contrastTemplate(uint8_t *temp){ + + char data[4]; + data[0] = 0xf2; + data[1] = 3; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_CHAR, data, 2); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(0x3f2 +1); + tempData[0] = 2; + tempData[1] = 0; + memcpy(tempData+2,temp,0x3f0); + + + header = pack(DATA_TYPE, CMD_DOWN_CHAR, tempData, 0x3f2); + + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + free(tempData); + data[0] = 0; + data[1] = 0; + data[2] = 2; + data[3] = 0; + header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ret; + } + return ret; + +} +uint8_t DFRobot_ID809::getFingerImage(uint8_t *image) +{ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + char data[1]; + data[0] = 0; + header = pack(CMD_TYPE, CMD_UP_IMAGE_CODE, data, 1); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500 +1); + for(uint8_t i=0;i<52;i++){ + + ret = responsePayload(tempData); + if(i == 51) + memcpy(image+i*496,tempData+2,304); + else + memcpy(image+i*496,tempData+2,496); + } + free(tempData); +} +uint8_t DFRobot_ID809::getQuarterFingerImage(uint8_t *image){ + + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + char data[1]; + data[0] = 1; + header = pack(CMD_TYPE, CMD_UP_IMAGE_CODE, data, 1); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500 +1); + for(uint8_t i=0;i<13;i++){ + + ret = responsePayload(tempData); + if(i == 12) + memcpy(image+i*496,tempData+2,448); + else + memcpy(image+i*496,tempData+2,496); + } + free(tempData); + +} +uint8_t DFRobot_ID809::downLoadImage(uint16_t id,uint8_t * temp) +{ + char data[4]; + data[0] = 0xa0; + data[1] = 0; + data[2] = 0xa0; + data[3] = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_IMAGE, data, 4); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500); + for(uint8_t i =0 ;i<52;i++){ + tempData[0] = i; + tempData[1] = 0; + if(i == 51){ + memcpy(tempData+2,temp+i*496,304); + header = pack(DATA_TYPE, CMD_DOWN_IMAGE, tempData, 306); + }else{ + memcpy(tempData+2,temp+i*496,496); + header = pack(DATA_TYPE, CMD_DOWN_IMAGE, tempData, 498); + } + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + } + free(tempData); + + data[0] = 0; + data[1] = 0; + header = pack(CMD_TYPE, CMD_GENERATE, data, 2); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + // return ERR_ID809; + } + return store(id); + +} + +uint8_t DFRobot_ID809::receiveImageData(uint8_t * image){ + + + + uint8_t ret = responsePayload(image); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + +} +String DFRobot_ID809::getModuleSN(){ + char *data; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_MODULE_SN, NULL, 0); + sendPacket(header); + free(header); + uint8_t result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount){ + char data[4] = {0}; + if(FINGERPRINT_CAPACITY == 80){ + data[0] = mode; + data[2] = data[1] = color; + data[3] = blinkCount; + }else{ + if(mode == 1){ + data[0] = 2; + } else if(mode == 2){ + data[0] = 4; + } else if(mode == 3){ + data[0] = 1; + } else if(mode == 4){ + data[0] = 0; + } else if(mode == 5){ + data[0] = 3; + } + if(color == eLEDGreen){ + data[2] = data[1] = 0x84; + }else if(color == eLEDRed){ + data[2] = data[1] = 0x82; + }else if(color == eLEDYellow){ + data[2] = data[1] = 0x86; + }else if(color == eLEDBlue){ + data[2] = data[1] = 0x81; + }else if(color == eLEDCyan){ + data[2] = data[1] = 0x85; + }else if(color == eLEDMagenta){ + data[2] = data[1] = 0x83; + }else { + data[2] = data[1] = 0x87; + } + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SLED_CTRL, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::detectFinger(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_FINGER_DETECT, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEmptyID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; //80 fingerprints at most, default to full range + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_EMPTY_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getStatusID(uint8_t ID){ + char data[2] = {0}; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_STATUS, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEnrollCount(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLL_COUNT, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +#define getID(A, V) (A[0 + V/8] & (0x01 << (V & 0x07))) +uint8_t DFRobot_ID809::getEnrolledIDList(uint8_t* list) +{ + char *data; + uint8_t i = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLLED_ID_LIST, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + uint16_t dataLen = buf[0]+(buf[1]<<8); + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + ret = responsePayload(data); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else{ + for(uint16_t j = 0; j < (dataLen*8); j++){ + if(getID(data, j) != 0){ + list[i] = j; + i++; + } + } + } + free(data); + return ret; +} + +uint8_t DFRobot_ID809::storeFingerprint(uint8_t ID){ + char data[4] = {0}; + uint8_t ret; + ret = merge(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number = 0; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; + +} +uint8_t DFRobot_ID809::store(uint8_t ID){ + + + char data[4] = {0}; + uint8_t ret; + LDBG("ret="); + LDBG(ret); + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + return ret; +} +uint8_t DFRobot_ID809::delFingerprint(uint8_t ID) +{ + char data[4] = {0}; + if(ID == DELALL) { + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + } else { + data[0] = data[2] = ID; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEL_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::search(){ + if(_state == 1){ + char data[6] = {0}; + data[2] = 1; + data[4] = FINGERPRINT_CAPACITY; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SEARCH, data, 6); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; + } + return 0; +} + +uint8_t DFRobot_ID809::verify(uint8_t ID){ + if(_state == 1){ + char data[4] = {0}; + data[0] = ID; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_VERIFY, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; + } + return 0; +} + +uint8_t DFRobot_ID809::match(uint8_t RamBufferID0, uint8_t RamBufferID1){ + char data[4] = {0}; + data[0] = RamBufferID0; + data[2] = RamBufferID1; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenQuantity(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[2]; + } + return ret; +} + +uint8_t DFRobot_ID809::loadFingerprint(uint8_t ID, uint8_t RamBufferID){ + char data[4] = {0}; + data[0] = ID; + data[2] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::enterStandbyState(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_ENTER_STANDBY_STATE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::setParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_PARAM, (const char *)data, 5); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::getParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_PARAM, (const char *)data, 1); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getImage(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::collectionFingerprint(uint16_t timeout,int ramNumber){ //Collect fingerprint + uint16_t i = 0; + uint8_t ret; + if(ramNumber == -1){ + if(_number > 2){ + _error = eErrorGatherOut; + LDBG("Exceed upper limit of acquisition times "); + return ERR_ID809; + } + } + while(!detectFinger()){ + if(timeout != 0){ + delay(10); + if(++i > timeout*10){ + _error = eErrorTimeOut; + LDBG("Acquisition timeout "); + LDBG("ret=");LDBG(ret); + _state = 0; + return ERR_ID809; + } + } + } + ret = getImage(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + _state = 0; + return ERR_ID809; + } + if(ramNumber != -1){ + ret = generate(ramNumber); + } else{ + ret = generate(_number); + } + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + _state = 0; + return ERR_ID809; + } + _number++; + _state = 1; + return ret; +} + +uint8_t DFRobot_ID809::generate(uint8_t RamBufferID){ + char data[2] = {0}; + data[0] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GENERATE, (const char *)data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::merge(){ + char data[3] = {0}; + data[2] = _number; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MERGE, data, 3); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +pCmdPacketHeader_t DFRobot_ID809::pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len){ + pCmdPacketHeader_t header; + uint16_t cks=0; + uint16_t dataLen; + if(type == CMD_TYPE){ //Structure of command packet, fixed 26 bytes:10(frame header)+14(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+16+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_PREFIX_CODE; + for(int i=0;i<16;i++){ + header->payload[i] = 0; + } + dataLen = 16; //Length of data to be replicated + }else{ //Structure of command data packet, unfixed length:10(frame header)+LEN(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+len+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_DATA_PREFIX_CODE; + dataLen = len; //Length of data to be replicated + } + header->SID = 0; + header->DID = 0; + header->CMD = cmd; + header->LEN = len; + if(len){ + memcpy(header->payload, payload, len); + } + cks = getCmdCKS(header); + memcpy(&header->payload[dataLen],&cks,2); + _PacketSize = sizeof(sCmdPacketHeader_t) + dataLen +2; + return header; +} + + +void DFRobot_ID809::sendPacket(pCmdPacketHeader_t header){ + s->write((uint8_t *)header,_PacketSize); +} + +uint8_t DFRobot_ID809::responsePayload(void* buf){ + sRcmPacketHeader_t header; + uint16_t dataLen,dataCount,cks; + uint8_t ch,ret; + int16_t type; + type = readPrefix(&header); + if(type == 1){ + LDBG("--recv timeout---"); + _error = eErrorRecvTimeout; + return ERR_ID809; + } + pRcmPacketHeader_t packet; + if(type == RCM_TYPE){ //Structure of response packet, fixed 26 bytes: 10(frame header)+14(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+14+2); + dataLen = 14+2; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + }else{ //Structure of response data packet, unfixed length: 10(frame header)+(LEN-2)(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+header.LEN); + dataLen = header.LEN; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + } + memcpy(packet, &header, 10); + dataCount = readN(packet->payload, dataLen); + cks = packet->payload[dataLen-2]+(packet->payload[dataLen-1]<<8); + ret = (header.RET&0xFF); + _error = (eError_t)ret; + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else if(dataLen != dataCount){ + LDBG("--recvRspPacket length error---"); + _error = eErrorRecvLength; + ret = ERR_ID809; + }else if(getRcmCKS(packet) != cks){ + LDBG("--recvRspPacket cks error---"); + _error = eErrorRecvCks; + ret = ERR_ID809; + }else{ + LDBG("--recvRspPacket OK---"); + memcpy(buf, packet->payload, dataLen); + } + free(packet); + packet = NULL; + return ret; +} + +uint16_t DFRobot_ID809::readPrefix( pRcmPacketHeader_t header ){ + uint8_t ch,ret; + typedef enum{ + RECV_HEADER_INIT, + RECV_HEADER_AA, + RECV_HEADER_A5, + RECV_HEADER_OK + }eRecvHeaderState; + eRecvHeaderState state = RECV_HEADER_INIT; + while(state != RECV_HEADER_OK){ //Can judge the received command packet and command data packet prefix at the same time + if(readN(&ch, 1) != 1){ + ret = 1; + return ret; + } + if((ch == 0xAA) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_AA; + continue; + }else if((ch == 0xA5) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_A5; + continue; + }else if((ch == 0x55) && (state == RECV_HEADER_AA)){ + state = RECV_HEADER_OK; + ret = RCM_TYPE; + continue; + }else if((ch == 0x5A) && (state == RECV_HEADER_A5)){ + state = RECV_HEADER_OK; + ret = DATA_TYPE; + continue; + }else{ + state = RECV_HEADER_INIT; + if(ch == 0xAA){ + state = RECV_HEADER_AA; + }else if(ch == 0xA5){ + state = RECV_HEADER_A5; + } + } + } + if(ret == RCM_TYPE){ + header->PREFIX = RCM_PREFIX_CODE; + }else if(ret == DATA_TYPE){ + header->PREFIX = RCM_DATA_PREFIX_CODE; + } + readN(&header->SID, 1); + readN(&header->DID, 1); + readN(&header->RCM, 2); + readN(&header->LEN, 2); + readN(&header->RET, 2); + return ret; +} + +size_t DFRobot_ID809::readN(void* buffer, size_t len){ + size_t offset = 0,left = len; + uint8_t *buf = (uint8_t*)buffer; + long long curr = millis(); + while(left){ + if(s->available()){ + buf[offset++] = s->read(); + left--; + } + if(millis() - curr > 5000){ + LDBG("----------!!!!!!!!!recv timeout----------"); + break; + } + } + return offset; +} + +uint16_t DFRobot_ID809::getCmdCKS(pCmdPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->CMD&0xFF; + cks += packet->CMD>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint16_t i = 0; i < packet->LEN; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +uint16_t DFRobot_ID809::getRcmCKS(pRcmPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->RCM&0xFF; + cks += packet->RCM>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + cks += packet->RET&0xFF; + cks += packet->RET>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint16_t i = 0; i < packet->LEN-2; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +const DFRobot_ID809::sErrorDescription_t DFRobot_ID809::errorDescriptionsTable[]={ + {eErrorSuccess, "Command processed successfully"}, + {eErrorFail, "Command processing failed"}, + {eErrorVerify, "1:1 comparison failed"}, + {eErrorIdentify, "Comparison with all fingerprints failed"}, + {eErrorTmplEmpty, "No fingerprint in designated ID"}, + {eErrorTmplNotEmpty, "Designated ID has fingerprint"}, + {eErrorAllTmplEmpty, "Module unregistered fingerprint"}, + {eErrorEmptyIDNoexist, "No registerable ID here"}, + {eErrorBrokenIDNoexist, "No broken fingerprint"}, + {eErrorInvalidTmplData, "Invalid desingated fingerprint data"}, + {eErrorDuplicationID, "The fingerprint has been registered"}, + {eErrorBadQuality, "Poor quality fingerprint image"}, + {eErrorMergeFail, "Fingerprint synthesis failed"}, + {eErrorNotAuthorized, "Communication password not authorized"}, + {eErrorMemory, "External Flash burning error"}, + {eErrorInvalidTmplNo, "Invalid designated ID"}, + {eErrorInvalidParam, "Incorrect parameter"}, + {eErrorTimeOut, "Acquisition timeout"}, + {eErrorGenCount, "Invalid number of fingerprint synthesis"}, + {eErrorInvalidBufferID, "Incorrect Buffer ID value"}, + {eErrorFPNotDetected, "No fingerprint input into fingerprint reader"}, + {eErrorFPCancel, "Command cancelled"}, + {eErrorRecvLength, "Wrong data length"}, + {eErrorRecvCks, "Wrong data check code"}, + {eErrorGatherOut, "Exceed upper limit of acquisition times"}, + {eErrorRecvTimeout,"Data reading timeout"} +}; + +String DFRobot_ID809::getErrorDescription() +{ + for(int i=0;i<sizeof(errorDescriptionsTable)/sizeof(errorDescriptionsTable[0]);i++){ + if(_error == errorDescriptionsTable[i].error){ + return errorDescriptionsTable[i].description; + } + } + return ""; +} + + diff --git a/RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.h b/RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.h new file mode 100644 index 0000000..83ca50d --- /dev/null +++ b/RegFPwithHash/lib/DFRobot_ID809/DFRobot_ID809.h @@ -0,0 +1,504 @@ +/*! + * @file DFRobot_ID809.h + * @brief Define basic structure of DFRobot_ID809 class + * @n This is an library for capacitive fingerprint module + * @n Main functions: fingerprint image capturing, fingerprint comparison, fingerprint deletion + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#ifndef _DFRobot_ID809_H +#define _DFRobot_ID809_H + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif +#include <Wire.h> + +#include <stdint.h> + +//Open this macro to see the detailed running process of the program + +//#define ENABLE_DBG +#ifdef ENABLE_DBG +#define LDBG(...) if(dbg) {dbg->print("["); dbg->print(__FUNCTION__); dbg->print("(): "); dbg->print(__LINE__); dbg->print(" ] "); dbg->println(__VA_ARGS__);} +#else +#define LDBG(...) +#endif + +extern Stream *dbg; + + /* + Frame struct of command packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t CMD; + uint16_t LEN; + uint8_t payload[0]; +}__attribute__ ((packed)) sCmdPacketHeader_t, *pCmdPacketHeader_t; + + /* + Frame struct of response packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t RCM; + uint16_t LEN; + uint16_t RET; + uint8_t payload[0]; +}__attribute__ ((packed)) sRcmPacketHeader_t, *pRcmPacketHeader_t; + + + + +class DFRobot_ID809{ +public: + +//#define FINGERPRINT_CAPACITY 80 //Fingerprint module capacity +#define MODULE_SN_SIZE 16 //Module SN length + + +#define DELALL 0xFF //Delete all fingerprints + +#define CMD_PREFIX_CODE 0xAA55 //Command packet prefix code +#define RCM_PREFIX_CODE 0x55AA //Response packet prefix code +#define CMD_DATA_PREFIX_CODE 0xA55A //Command data packet prefix code +#define RCM_DATA_PREFIX_CODE 0x5AA5 //Response data packet prefix code + +#define CMD_TYPE 0xF0 //Command packet type +#define RCM_TYPE 0xF0 //Response packet type +#define DATA_TYPE 0x0F //Data packet type + +#define CMD_TEST_CONNECTION 0X0001 //Test connection +#define CMD_SET_PARAM 0X0002 //Set parameter +#define CMD_GET_PARAM 0X0003 //Read parameter +#define CMD_DEVICE_INFO 0X0004 //Read device information +#define CMD_SET_MODULE_SN 0X0008 //Set module serial number +#define CMD_GET_MODULE_SN 0X0009 //Read module serial number +#define CMD_ENTER_STANDBY_STATE 0X000C //Enter sleep mode +#define CMD_GET_IMAGE 0X0020 //Capture fingerprint image +#define CMD_FINGER_DETECT 0X0021 //Detect fingerprint + #define CMD_UP_IMAGE_CODE 0X0022 //Upload fingerprint image to host + #define CMD_DOWN_IMAGE 0X0023 //Download fingerprint image to module +#define CMD_SLED_CTRL 0X0024 //Control collector backlight +#define CMD_STORE_CHAR 0X0040 //Save fingerprint template data into fingerprint library +#define CMD_LOAD_CHAR 0X0041 //Read fingerprint in module and save it in RAMBUFFER temporarily + #define CMD_UP_CHAR 0X0042 //Upload the fingerprint template saved in RAMBUFFER to host + #define CMD_DOWN_CHAR 0X0043 //Download fingerprint template to module designated RAMBUFFER +#define CMD_DEL_CHAR 0X0044 //Delete fingerprint in specific ID range +#define CMD_GET_EMPTY_ID 0X0045 //Get the first registerable ID in specific ID range +#define CMD_GET_STATUS 0X0046 //Check if the designated ID has been registered +#define CMD_GET_BROKEN_ID 0X0047 //Check whether there is damaged data in fingerprint library of specific range +#define CMD_GET_ENROLL_COUNT 0X0048 //Get the number of registered fingerprints in specific ID range +#define CMD_GET_ENROLLED_ID_LIST 0X0049 //Get registered ID list +#define CMD_GENERATE 0X0060 //Generate template from the fingerprint images saved in IMAGEBUFFER temporarily +#define CMD_MERGE 0X0061 //Synthesize fingerprint template data +#define CMD_MATCH 0X0062 //Compare templates in 2 designated RAMBUFFER +#define CMD_SEARCH 0X0063 //1:N Recognition in specific ID range +#define CMD_VERIFY 0X0064 //Compare specific RAMBUFFER template with specific ID template in fingerprint library + +#define ERR_SUCCESS 0x00 //Command processed successfully +#define ERR_ID809 0xFF //error + + +public: + + typedef enum{ + eBreathing = 1, //Breathing + eFastBlink, //Quick blink + eKeepsOn, //On + eNormalClose, //Off + eFadeIn, //Fade in + eFadeOut, //Fade out + eSlowBlink //Slow blink + }eLEDMode_t; + + typedef enum{ + eLEDGreen = 1, //green + eLEDRed, //red + eLEDYellow, //yellow + eLEDBlue, //blue + eLEDCyan, //cyan + eLEDMagenta, //magenta + eLEDWhite //white + }eLEDColor_t; + + typedef enum{ + e9600bps = 1, + e19200bps, + e38400bps, + e57600bps, + e115200bps + }eDeviceBaudrate_t; + + typedef enum{ + eErrorSuccess = 0x00, //Command processed successfully + eErrorFail = 0x01, //Command processing failed + eErrorVerify = 0x10, //1:1 Templates comparison in specific ID failed + eErrorIdentify = 0x11, //1:N comparison has been made, no same templates here + eErrorTmplEmpty = 0x12, //No registered template in the designated ID + eErrorTmplNotEmpty = 0x13, //Template already exists in the specified ID + eErrorAllTmplEmpty = 0x14, //No registered Template + eErrorEmptyIDNoexist = 0x15, //No registerable Template ID + eErrorBrokenIDNoexist = 0x16, //No damaged Template + eErrorInvalidTmplData = 0x17, //The designated Template Data is invalid + eErrorDuplicationID = 0x18, //The fingerprint has been registered + eErrorBadQuality = 0x19, //Poor quality fingerprint image + eErrorMergeFail = 0x1A, //Template synthesis failed + eErrorNotAuthorized = 0x1B, //Communication password not authorized + eErrorMemory = 0x1C, //Error in exernal Flash burning + eErrorInvalidTmplNo = 0x1D, //The designated template ID is invalid + eErrorInvalidParam = 0x22, //Incorrect parameter has been used + eErrorTimeOut = 0x23, //Acquisition timeout + eErrorGenCount = 0x25, //Invalid number of fingerprint synthesis + eErrorInvalidBufferID = 0x26, //Wrong Buffer ID value + eErrorFPNotDetected = 0x28, //No fingerprint input into fingerprint reader + eErrorFPCancel = 0x41, //Command cancelled + eErrorRecvLength = 0x42, //Wrong length of recieved data + eErrorRecvCks = 0x43, //Wrong check code + eErrorGatherOut = 0x45, //Exceed upper limit of acquisition times + eErrorRecvTimeout = 0x46 //Communication timeout + }eError_t; + + typedef struct{ + /**< Gesture enumeration variable X */ + eError_t error; + /**< Description about the gesture enumeration variable X */ + const char * description; + }sErrorDescription_t; + +public: + DFRobot_ID809(); + ~DFRobot_ID809(); + + /** + * @brief Init communication port + * @param Software serial or hardware serial + * @return true or false + */ + bool begin(Stream &s_); + + /** + * @brief Test whether the module connection is ok + * @return true or false + */ + bool isConnected(); + + /** + * @brief Set module ID + * @param ID:1-255 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDeviceID(uint8_t deviceID); + + /** + * @brief Set module security level + * @param security level:1-5 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSecurityLevel(uint8_t securityLevel); + + /** + * @brief Set module fingerprint replication check (Check whether the fingperint has been registered when saving it) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDuplicationCheck(uint8_t duplicationCheck); + + /** + * @brief Set module baud rate + * @param Baudrate:in typedef enum eDeviceBaudrate_t + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setBaudrate(eDeviceBaudrate_t baudrate); + + /** + * @brief Set module self-learning function (Update fingeprint when fingerprint comparison succeeds) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSelfLearn(uint8_t selfLearn); + + /** + * @brief Read module ID + * @return IDå·:1-255 or ERR_ID809 + */ + uint8_t getDeviceID(); + + /** + * @brief Read module security level + * @return Security level:1-5 or ERR_ID809 + */ + uint8_t getSecurityLevel(); + + /** + * @brief Read module fingerprint replication check status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getDuplicationCheck(); + + /** + * @brief Read module baud rate + * @return Baudrate:in typedef enum eDEVICE_BAUDRATE_t or ERR_ID809 + */ + uint8_t getBaudrate(); + + /** + * @brief Read module self-learning function status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getSelfLearn(); + uint8_t getTemplate(uint16_t id,uint8_t * temp); + uint8_t downLoadTemplate(uint16_t id,uint8_t * temp); + uint8_t getFingerImage(uint8_t *image); + uint8_t downLoadImage(uint16_t id,uint8_t * temp); + uint8_t receiveImageData(uint8_t *image); + uint8_t getQuarterFingerImage(uint8_t *image); + uint8_t contrastTemplate(uint8_t *temp); + /** + * @brief Read device number + * @return Device number + */ + String getDeviceInfo(); + + /** + * @brief Set serial number + * @param String pointer + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setModuleSN(const char* SN); + /** + * @brief Read serial number + * @return Serial number + */ + String getModuleSN(); + + /** + * @brief Set LED + * @param mode:in typedef enum eLEDMode_t + * @param color:in typedef enum eLEDColor_t + * @param blink Count: 00 represents blinking all the time + * @This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + * @return 0(succeed) or ERR_ID809 + */ + uint8_t ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount); + + /** + * @brief Detect if there is finger touched + * @return 1(Touched) or 0(No touch) + */ + uint8_t detectFinger(); + + /** + * @brief Get the first registerable ID + * @return Registerable ID or ERR_ID809 + */ + uint8_t getEmptyID(); + + /** + * @brief Check if the ID has been registered + * @return 0(Registered), 1(Unregistered) or ERR_ID809 + */ + uint8_t getStatusID(uint8_t ID); + + /** + * @brief Get the number of registered users + * @return Number of registered users or ERR_ID809 + */ + uint8_t getEnrollCount(); + + /** + * @brief Get registered user list + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getEnrolledIDList(uint8_t* list); + + /** + * @brief Fingerprint acquisition + * @return 0(succeed) or ERR_ID809 + */ + uint8_t collectionFingerprint(uint16_t timeout,int ramNumber = -1); + + /** + * @brief Save fingerprint + * @param Fingerprint ID + * @return 0(succeed) or ERR_ID809 + */ + uint8_t storeFingerprint(uint8_t ID); + + /** + * @brief Delete fingerprint + * @param Delete ID or DELALL(delete all) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t delFingerprint(uint8_t ID); + + /** + * @brief Match the fingerprint with all fingeprints + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t search(); + + /** + * @brief Match the fingerprint with specific fingerprint + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t verify(uint8_t ID); + + /** + * @brief Compare templates in two specific RamBuffers + * @param RamBuffer number + * @param RamBuffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t match(uint8_t RamBufferID0, uint8_t RamBufferID1); + + /** + * @brief Get the number of damaged fingerprints + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenQuantity(); + + /** + * @brief Get the first damaged fingerprint ID + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenID(); + + /** + * @brief Take out fingerprint template, temporarily save into RamBuffer + * @param Fingerprint ID + * @param RamBuffer number 0-2 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t loadFingerprint(uint8_t ID, uint8_t RamBufferID); + + /** + * @brief Enter Standby mode + * @return 0(succeed) or ERR_ID809 + */ + uint8_t enterStandbyState(); + + /** + * @brief Get error information + * @return Text description of error information + */ + String getErrorDescription(); + + bool setDbgSerial(Stream &s_){dbg = &s_; return true;} + uint16_t FINGERPRINT_CAPACITY = 80; +protected: + /** + * @brief Set parameter + * @param Data type+ data + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setParam(uint8_t* data); + + /** + * @brief Read parameter + * @param Data type + * @return data or ERR_ID809 + */ + uint8_t getParam(uint8_t* data); + + /** + * @brief Capture fingerprint image + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getImage(); + + /** + * @brief Take image as template + * @param Ram Buffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t generate(uint8_t RamBufferID); + + /** + * @brief Fingerprint synthesis + * @return 0(succeed) or ERR_ID809 + */ + uint8_t merge(); + + /** + * @brief Packing data frame + * @param Data type:CMD_TYPE or DATA_TYPE + * @param Command + * @param Data + * @param Length + * @return Data frame + */ + pCmdPacketHeader_t pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len); + + /** + * @brief Send data + * @param Data frame + */ + void sendPacket(pCmdPacketHeader_t header); + + /** + * @brief Read byte + * @param Pointer for saving data + * @param Length of data to be received + * @return Actual received data length + */ + size_t readN(void* buf_, size_t len); + + /** + * @brief Read frame header + * @param Frame header struct of response packet + * @return Response packet type:RCM_TYPE,DATA_TYPE or 1(reading timeout) + */ + uint16_t readPrefix( pRcmPacketHeader_t header ); + + /** + * @brief Read data + * @param Pointer for saving data + * @return 0(success) or ERR_ID809 + */ + uint8_t responsePayload(void* buf); + + /** + * @brief Get command packet CKS + * @param Command packet frame + * @return CKS + */ + uint16_t getCmdCKS(pCmdPacketHeader_t packet); + + /** + * @brief Get response packet CKS + * @param Response packet frame + * @return CKS + */ + uint16_t getRcmCKS(pRcmPacketHeader_t packet); + uint8_t store(uint8_t ID); + +private: + Stream *s; + uint8_t buf[20]; //For saving response packet data + pCmdPacketHeader_t sendHeader; + pRcmPacketHeader_t recHeader; + + static const sErrorDescription_t /*PROGMEM*/ errorDescriptionsTable[26]; //Error information list + + uint8_t _number = 0; //Fingerprint acquisistion times + uint8_t _state = 0; //Collect fingerprint state + eError_t _error; //Error code + uint16_t _PacketSize = 0; //Data packet length to be sent +}; + +#endif + diff --git a/RegFPwithHash/platformio.ini b/RegFPwithHash/platformio.ini new file mode 100644 index 0000000..f0c71a5 --- /dev/null +++ b/RegFPwithHash/platformio.ini @@ -0,0 +1,12 @@ +[env:Teensy_FP] + +board = teensy31 +framework = arduino +platform = teensy + +build_flags = + -I lib/DFRobot_ID809 + +lib_deps = + intrbiz/crypto + diff --git a/RegFPwithHash/src/src.cpp b/RegFPwithHash/src/src.cpp new file mode 100644 index 0000000..1547c0a --- /dev/null +++ b/RegFPwithHash/src/src.cpp @@ -0,0 +1,216 @@ +#include <Arduino.h> +#include <Crypto.h> +#include <DFRobot_ID809.h> +#include <EEPROM.h> + +// use serial3 as interface with fingerprint +// sensor. + +#define FPSerial Serial3 + +// define buillt_in led + +#define BUILTIN_LED 13 + +// Collect the fingerprint 3 times + +#define COLLECT_NUMBER 3 + +// EEPROM OFFSET to store + +/*------Global variables--------------*/ + +DFRobot_ID809 fingerprint; +uint8_t ID = 0, ret; +byte hash[SHA256_SIZE]; +uint8_t temp[1008]; +const uint16_t EEPROM_FP_HASH = 1696; + +/*---------Compute hash----------------*/ + +void compute_hash() { + + SHA256 hasher; + hasher.doUpdate(temp, sizeof(temp)); + hasher.doFinal(hash); + + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + if (hash[i] < 0x10) { + + Serial.print('0'); + } + + Serial.print(hash[i], HEX); + Serial.print(" "); + } + Serial.println("\n"); + Serial.println("-----------------"); +} + +/*-----Blink on board led -------------- */ + +void blink_led() { + digitalWrite(BUILTIN_LED, HIGH); + delay(500); + digitalWrite(BUILTIN_LED, LOW); + delay(500); +} + +/*-------- Save FingerPrint hash in EEPROM ------*/ + +void saveHash() { + uint16_t memoryAddress; + + memoryAddress = EEPROM_FP_HASH + ((ID - 1) * 32); + + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + EEPROM.write(memoryAddress, hash[i]); + memoryAddress++; + } +} + +/*---------Arduino setup function------*/ + +void setup() { + // config led_pin as output + pinMode(BUILTIN_LED, OUTPUT); + // use serial port to print the baud rate + Serial.begin(9600); + // config fingerprint sensor + FPSerial.begin(115200); + fingerprint.begin(FPSerial); + + while (fingerprint.isConnected() == false) { + Serial.println("Communication with the device failed"); + delay(1000); + } + // Disable self-learn feature + fingerprint.setSelfLearn(0); +} + +/*------Read stored EEPROM data--------- */ + +void readHash() { + + uint16_t memoryAddress; + byte eeprom_data; + + memoryAddress = EEPROM_FP_HASH + ((ID - 1) * 32); + + for (uint16_t i = memoryAddress; i < (memoryAddress + SHA256_SIZE); i++) { + + eeprom_data = EEPROM.read(i); + Serial.print(eeprom_data, HEX); + Serial.print(" "); + } + Serial.println("\n"); + Serial.println("--------------------"); +} + +/*---------Register Finger print ------------*/ + +void regFingerprint() { + uint8_t i = 0; + /*Get an unregistered ID for saving fingerprint +Return ID when succeeded +Return ERR_ID809 if failed +*/ + if ((ID = fingerprint.getEmptyID()) == ERR_ID809) { + while (1) { + /*Get error code information*/ + // desc = fingerprint.getErrorDescription(); + // Serial.println(desc); + delay(1000); + } + } + Serial.print("unresistered ID,ID="); + Serial.println(ID); + i = 0; // Clear sampling times + /*Fingerprint sampling 3 times*/ + while (i < COLLECT_NUMBER) { + /*Set fingerprint LED ring mode, color, and number of blinks + Can be set as follows: + Parameter 1:<LEDMode> + eBreathing eFastBlink eKeepsOn eNormalClose + eFadeIn eFadeOut eSlowBlink + Parameter 2:<LEDColor> + eLEDGreen eLEDRed eLEDYellow eLEDBlue + eLEDCyan eLEDMagenta eLEDWhite + Parameter 3:<Number of blinks> 0 represents blinking all the time + This parameter will only be valid in mode eBreathing, eFastBlink, + eSlowBlink + */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eBreathing, + /*LEDColor = */ fingerprint.eLEDBlue, + /*blinkCount = */ 0); + Serial.print("The fingerprint sampling of the"); + Serial.print(i + 1); + Serial.println("(th) is being taken"); + Serial.println("Please press down your finger"); + /*Capture fingerprint image, 10s idle timeout, if timeout=0,Disable the + collection timeout function IF succeeded, return 0, otherwise, return + ERR_ID809 + */ + if ((fingerprint.collectionFingerprint(/*timeout = */ 10)) != ERR_ID809) { + /*Set fingerprint LED ring to quick blink in yellow 3 times */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eFastBlink, + /*LEDColor = */ fingerprint.eLEDYellow, + /*blinkCount = */ 3); + Serial.println("Sampling succeeds"); + i++; // Sampling times +1 + } else { + Serial.println("Sampling failed"); + /*Get error code information*/ + // desc = fingerprint.getErrorDescription(); + // Serial.println(desc); + } + Serial.println("Please release your finger"); + /*Wait for finger to release + Return 1 when finger is detected, otherwise return 0 + */ + while (fingerprint.detectFinger()) + ; + } + + if (ID < 1) { + Serial.println("Fingerprint registration failed"); + return; + } + + /*Save fingerprint in an unregistered ID */ + if (fingerprint.storeFingerprint(/*Empty ID = */ ID) != ERR_ID809) { + Serial.print("Saving succeed,ID="); + Serial.println(ID); + Serial.println("-----------------------------"); + /*Set fingerprint LED ring to always ON in green */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eKeepsOn, + /*LEDColor = */ fingerprint.eLEDGreen, + /*blinkCount = */ 0); + delay(1000); + /*Turn off fingerprint LED ring */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eNormalClose, + /*LEDColor = */ fingerprint.eLEDBlue, + /*blinkCount = */ 0); + delay(1000); + + fingerprint.getTemplate(ID, temp); + compute_hash(); + saveHash(); + readHash(); + + } else { + Serial.println("Saving failed"); + /*Get error code information*/ + // desc = fingerprint.getErrorDescription(); + // Serial.println(desc); + } +} + +/*-----------Arduino loop function--------- */ + +void loop() { + blink_led(); + regFingerprint(); +} diff --git a/matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.cpp b/matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.cpp new file mode 100644 index 0000000..d49f6f4 --- /dev/null +++ b/matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.cpp @@ -0,0 +1,1089 @@ +/*! + * @file DFRobot_ID809.cpp + * @brief Define the basic structure of DFRobot_ID809 class and the implementation of underlying methods + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#include <DFRobot_ID809.h> +#include <Arduino.h> +#include <string.h> +#include <stdio.h> +Stream *dbg=NULL; + +DFRobot_ID809::DFRobot_ID809() + :s(NULL){ + +} + +DFRobot_ID809::~DFRobot_ID809(){ + +} + +bool DFRobot_ID809::begin(Stream &s_){ + s = &s_; + String str = getDeviceInfo(); + //Serial.println(str[str.length()-1]); + if(str[str.length()-1] == '4'){ + + FINGERPRINT_CAPACITY = 80 ; + + //Serial.println(str[str.length()-1]); + }else if(str[str.length()-1] == '3'){ + //Serial.println(str[str.length()-1]); + FINGERPRINT_CAPACITY = 200 ; + + } + + if(s == NULL){ + return false; + } + return true; +} + +bool DFRobot_ID809::isConnected(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_TEST_CONNECTION, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + return true; + }else{ + return false; + } +} + +uint8_t DFRobot_ID809::setDeviceID(uint8_t deviceID){ + uint8_t data[5] = {0}; //data:1bytes Parameter Type+4bytes Parameter Value + data[1] = deviceID; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSecurityLevel(uint8_t securityLevel){ + uint8_t data[5] = {0}; + data[0] = 1; + data[1] = securityLevel; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setDuplicationCheck(uint8_t duplicationCheck){ + uint8_t data[5] = {0}; + data[0] = 2; + data[1] = duplicationCheck; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setBaudrate(eDeviceBaudrate_t baudrate){ + uint8_t data[5] = {0}; + data[0] = 3; + data[1] = baudrate; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSelfLearn(uint8_t selfLearn){ + uint8_t data[5] = {0}; + data[0] = 4; + data[1] = selfLearn; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDeviceID(){ + uint8_t data[1]; //data:1byte Parameter Type + data[0] = 0; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSecurityLevel(){ + uint8_t data[1]; + data[0] = 1; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDuplicationCheck(){ + uint8_t data[1]; + data[0] = 2; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getBaudrate(){ + uint8_t data[1]; + data[0] = 3; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSelfLearn(){ + uint8_t data[1]; + data[0] = 4; + uint8_t ret = getParam(data); + return ret; +} + +String DFRobot_ID809::getDeviceInfo(){ + char *data; + uint8_t result; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEVICE_INFO, NULL, 0); + sendPacket(header); + free(header); + result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::setModuleSN(const char* SN){ + char data[2]; + data[0] = MODULE_SN_SIZE; + if(strlen(SN) > MODULE_SN_SIZE){ + LDBG("The serial number exceeds 15 characters"); + return ERR_ID809; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_MODULE_SN, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + header = pack(DATA_TYPE, CMD_SET_MODULE_SN, SN, MODULE_SN_SIZE); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getTemplate(uint16_t id,uint8_t * temp){ + char data[4]; + data[0] = id; + data[1] = 0; + data[2] = 0; + data[3] = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + data[0] = 0; + data[1] = 0; + header = pack(CMD_TYPE, CMD_UP_CHAR, data, 2); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + ret = responsePayload(temp); + + return ret; +} + +uint8_t DFRobot_ID809::downLoadTemplate(uint16_t id,uint8_t * temp){ + + char data[4]; + data[0] = 0xf2; + data[1] = 3; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_CHAR, data, 2); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(0x3f2 +1); + tempData[0] = 0; + tempData[1] = 0; + memcpy(tempData+2,temp,0x3f0); + + + header = pack(DATA_TYPE, CMD_DOWN_CHAR, tempData, 0x3f2); + + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + free(tempData); + + + return store(id); +} + +uint8_t DFRobot_ID809::contrastTemplate(uint8_t *temp){ + + char data[4]; + data[0] = 0xf2; + data[1] = 3; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_CHAR, data, 2); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(0x3f2 +1); + tempData[0] = 2; + tempData[1] = 0; + memcpy(tempData+2,temp,0x3f0); + + + header = pack(DATA_TYPE, CMD_DOWN_CHAR, tempData, 0x3f2); + + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + free(tempData); + data[0] = 0; + data[1] = 0; + data[2] = 2; + data[3] = 0; + header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ret; + } + return ret; + +} +uint8_t DFRobot_ID809::getFingerImage(uint8_t *image) +{ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + char data[1]; + data[0] = 0; + header = pack(CMD_TYPE, CMD_UP_IMAGE_CODE, data, 1); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500 +1); + for(uint8_t i=0;i<52;i++){ + + ret = responsePayload(tempData); + if(i == 51) + memcpy(image+i*496,tempData+2,304); + else + memcpy(image+i*496,tempData+2,496); + } + free(tempData); +} +uint8_t DFRobot_ID809::getQuarterFingerImage(uint8_t *image){ + + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + char data[1]; + data[0] = 1; + header = pack(CMD_TYPE, CMD_UP_IMAGE_CODE, data, 1); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500 +1); + for(uint8_t i=0;i<13;i++){ + + ret = responsePayload(tempData); + if(i == 12) + memcpy(image+i*496,tempData+2,448); + else + memcpy(image+i*496,tempData+2,496); + } + free(tempData); + +} +uint8_t DFRobot_ID809::downLoadImage(uint16_t id,uint8_t * temp) +{ + char data[4]; + data[0] = 0xa0; + data[1] = 0; + data[2] = 0xa0; + data[3] = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_IMAGE, data, 4); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500); + for(uint8_t i =0 ;i<52;i++){ + tempData[0] = i; + tempData[1] = 0; + if(i == 51){ + memcpy(tempData+2,temp+i*496,304); + header = pack(DATA_TYPE, CMD_DOWN_IMAGE, tempData, 306); + }else{ + memcpy(tempData+2,temp+i*496,496); + header = pack(DATA_TYPE, CMD_DOWN_IMAGE, tempData, 498); + } + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + } + free(tempData); + + data[0] = 0; + data[1] = 0; + header = pack(CMD_TYPE, CMD_GENERATE, data, 2); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + // return ERR_ID809; + } + return store(id); + +} + +uint8_t DFRobot_ID809::receiveImageData(uint8_t * image){ + + + + uint8_t ret = responsePayload(image); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + +} +String DFRobot_ID809::getModuleSN(){ + char *data; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_MODULE_SN, NULL, 0); + sendPacket(header); + free(header); + uint8_t result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount){ + char data[4] = {0}; + if(FINGERPRINT_CAPACITY == 80){ + data[0] = mode; + data[2] = data[1] = color; + data[3] = blinkCount; + }else{ + if(mode == 1){ + data[0] = 2; + } else if(mode == 2){ + data[0] = 4; + } else if(mode == 3){ + data[0] = 1; + } else if(mode == 4){ + data[0] = 0; + } else if(mode == 5){ + data[0] = 3; + } + if(color == eLEDGreen){ + data[2] = data[1] = 0x84; + }else if(color == eLEDRed){ + data[2] = data[1] = 0x82; + }else if(color == eLEDYellow){ + data[2] = data[1] = 0x86; + }else if(color == eLEDBlue){ + data[2] = data[1] = 0x81; + }else if(color == eLEDCyan){ + data[2] = data[1] = 0x85; + }else if(color == eLEDMagenta){ + data[2] = data[1] = 0x83; + }else { + data[2] = data[1] = 0x87; + } + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SLED_CTRL, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::detectFinger(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_FINGER_DETECT, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEmptyID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; //80 fingerprints at most, default to full range + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_EMPTY_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getStatusID(uint8_t ID){ + char data[2] = {0}; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_STATUS, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEnrollCount(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLL_COUNT, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +#define getID(A, V) (A[0 + V/8] & (0x01 << (V & 0x07))) +uint8_t DFRobot_ID809::getEnrolledIDList(uint8_t* list) +{ + char *data; + uint8_t i = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLLED_ID_LIST, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + uint16_t dataLen = buf[0]+(buf[1]<<8); + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + ret = responsePayload(data); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else{ + for(uint16_t j = 0; j < (dataLen*8); j++){ + if(getID(data, j) != 0){ + list[i] = j; + i++; + } + } + } + free(data); + return ret; +} + +uint8_t DFRobot_ID809::storeFingerprint(uint8_t ID){ + char data[4] = {0}; + uint8_t ret; + ret = merge(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number = 0; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; + +} +uint8_t DFRobot_ID809::store(uint8_t ID){ + + + char data[4] = {0}; + uint8_t ret; + LDBG("ret="); + LDBG(ret); + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + return ret; +} +uint8_t DFRobot_ID809::delFingerprint(uint8_t ID) +{ + char data[4] = {0}; + if(ID == DELALL) { + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + } else { + data[0] = data[2] = ID; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEL_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::search(){ + if(_state == 1){ + char data[6] = {0}; + data[2] = 1; + data[4] = FINGERPRINT_CAPACITY; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SEARCH, data, 6); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; + } + return 0; +} + +uint8_t DFRobot_ID809::verify(uint8_t ID){ + if(_state == 1){ + char data[4] = {0}; + data[0] = ID; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_VERIFY, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; + } + return 0; +} + +uint8_t DFRobot_ID809::match(uint8_t RamBufferID0, uint8_t RamBufferID1){ + char data[4] = {0}; + data[0] = RamBufferID0; + data[2] = RamBufferID1; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenQuantity(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[2]; + } + return ret; +} + +uint8_t DFRobot_ID809::loadFingerprint(uint8_t ID, uint8_t RamBufferID){ + char data[4] = {0}; + data[0] = ID; + data[2] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::enterStandbyState(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_ENTER_STANDBY_STATE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::setParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_PARAM, (const char *)data, 5); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::getParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_PARAM, (const char *)data, 1); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getImage(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::collectionFingerprint(uint16_t timeout,int ramNumber){ //Collect fingerprint + uint16_t i = 0; + uint8_t ret; + if(ramNumber == -1){ + if(_number > 2){ + _error = eErrorGatherOut; + LDBG("Exceed upper limit of acquisition times "); + return ERR_ID809; + } + } + while(!detectFinger()){ + if(timeout != 0){ + delay(10); + if(++i > timeout*10){ + _error = eErrorTimeOut; + LDBG("Acquisition timeout "); + LDBG("ret=");LDBG(ret); + _state = 0; + return ERR_ID809; + } + } + } + ret = getImage(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + _state = 0; + return ERR_ID809; + } + if(ramNumber != -1){ + ret = generate(ramNumber); + } else{ + ret = generate(_number); + } + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + _state = 0; + return ERR_ID809; + } + _number++; + _state = 1; + return ret; +} + +uint8_t DFRobot_ID809::generate(uint8_t RamBufferID){ + char data[2] = {0}; + data[0] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GENERATE, (const char *)data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::merge(){ + char data[3] = {0}; + data[2] = _number; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MERGE, data, 3); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +pCmdPacketHeader_t DFRobot_ID809::pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len){ + pCmdPacketHeader_t header; + uint16_t cks=0; + uint16_t dataLen; + if(type == CMD_TYPE){ //Structure of command packet, fixed 26 bytes:10(frame header)+14(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+16+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_PREFIX_CODE; + for(int i=0;i<16;i++){ + header->payload[i] = 0; + } + dataLen = 16; //Length of data to be replicated + }else{ //Structure of command data packet, unfixed length:10(frame header)+LEN(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+len+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_DATA_PREFIX_CODE; + dataLen = len; //Length of data to be replicated + } + header->SID = 0; + header->DID = 0; + header->CMD = cmd; + header->LEN = len; + if(len){ + memcpy(header->payload, payload, len); + } + cks = getCmdCKS(header); + memcpy(&header->payload[dataLen],&cks,2); + _PacketSize = sizeof(sCmdPacketHeader_t) + dataLen +2; + return header; +} + + +void DFRobot_ID809::sendPacket(pCmdPacketHeader_t header){ + s->write((uint8_t *)header,_PacketSize); +} + +uint8_t DFRobot_ID809::responsePayload(void* buf){ + sRcmPacketHeader_t header; + uint16_t dataLen,dataCount,cks; + uint8_t ch,ret; + int16_t type; + type = readPrefix(&header); + if(type == 1){ + LDBG("--recv timeout---"); + _error = eErrorRecvTimeout; + return ERR_ID809; + } + pRcmPacketHeader_t packet; + if(type == RCM_TYPE){ //Structure of response packet, fixed 26 bytes: 10(frame header)+14(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+14+2); + dataLen = 14+2; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + }else{ //Structure of response data packet, unfixed length: 10(frame header)+(LEN-2)(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+header.LEN); + dataLen = header.LEN; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + } + memcpy(packet, &header, 10); + dataCount = readN(packet->payload, dataLen); + cks = packet->payload[dataLen-2]+(packet->payload[dataLen-1]<<8); + ret = (header.RET&0xFF); + _error = (eError_t)ret; + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else if(dataLen != dataCount){ + LDBG("--recvRspPacket length error---"); + _error = eErrorRecvLength; + ret = ERR_ID809; + }else if(getRcmCKS(packet) != cks){ + LDBG("--recvRspPacket cks error---"); + _error = eErrorRecvCks; + ret = ERR_ID809; + }else{ + LDBG("--recvRspPacket OK---"); + memcpy(buf, packet->payload, dataLen); + } + free(packet); + packet = NULL; + return ret; +} + +uint16_t DFRobot_ID809::readPrefix( pRcmPacketHeader_t header ){ + uint8_t ch,ret; + typedef enum{ + RECV_HEADER_INIT, + RECV_HEADER_AA, + RECV_HEADER_A5, + RECV_HEADER_OK + }eRecvHeaderState; + eRecvHeaderState state = RECV_HEADER_INIT; + while(state != RECV_HEADER_OK){ //Can judge the received command packet and command data packet prefix at the same time + if(readN(&ch, 1) != 1){ + ret = 1; + return ret; + } + if((ch == 0xAA) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_AA; + continue; + }else if((ch == 0xA5) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_A5; + continue; + }else if((ch == 0x55) && (state == RECV_HEADER_AA)){ + state = RECV_HEADER_OK; + ret = RCM_TYPE; + continue; + }else if((ch == 0x5A) && (state == RECV_HEADER_A5)){ + state = RECV_HEADER_OK; + ret = DATA_TYPE; + continue; + }else{ + state = RECV_HEADER_INIT; + if(ch == 0xAA){ + state = RECV_HEADER_AA; + }else if(ch == 0xA5){ + state = RECV_HEADER_A5; + } + } + } + if(ret == RCM_TYPE){ + header->PREFIX = RCM_PREFIX_CODE; + }else if(ret == DATA_TYPE){ + header->PREFIX = RCM_DATA_PREFIX_CODE; + } + readN(&header->SID, 1); + readN(&header->DID, 1); + readN(&header->RCM, 2); + readN(&header->LEN, 2); + readN(&header->RET, 2); + return ret; +} + +size_t DFRobot_ID809::readN(void* buffer, size_t len){ + size_t offset = 0,left = len; + uint8_t *buf = (uint8_t*)buffer; + long long curr = millis(); + while(left){ + if(s->available()){ + buf[offset++] = s->read(); + left--; + } + if(millis() - curr > 5000){ + LDBG("----------!!!!!!!!!recv timeout----------"); + break; + } + } + return offset; +} + +uint16_t DFRobot_ID809::getCmdCKS(pCmdPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->CMD&0xFF; + cks += packet->CMD>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint16_t i = 0; i < packet->LEN; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +uint16_t DFRobot_ID809::getRcmCKS(pRcmPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->RCM&0xFF; + cks += packet->RCM>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + cks += packet->RET&0xFF; + cks += packet->RET>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint16_t i = 0; i < packet->LEN-2; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +const DFRobot_ID809::sErrorDescription_t DFRobot_ID809::errorDescriptionsTable[]={ + {eErrorSuccess, "Command processed successfully"}, + {eErrorFail, "Command processing failed"}, + {eErrorVerify, "1:1 comparison failed"}, + {eErrorIdentify, "Comparison with all fingerprints failed"}, + {eErrorTmplEmpty, "No fingerprint in designated ID"}, + {eErrorTmplNotEmpty, "Designated ID has fingerprint"}, + {eErrorAllTmplEmpty, "Module unregistered fingerprint"}, + {eErrorEmptyIDNoexist, "No registerable ID here"}, + {eErrorBrokenIDNoexist, "No broken fingerprint"}, + {eErrorInvalidTmplData, "Invalid desingated fingerprint data"}, + {eErrorDuplicationID, "The fingerprint has been registered"}, + {eErrorBadQuality, "Poor quality fingerprint image"}, + {eErrorMergeFail, "Fingerprint synthesis failed"}, + {eErrorNotAuthorized, "Communication password not authorized"}, + {eErrorMemory, "External Flash burning error"}, + {eErrorInvalidTmplNo, "Invalid designated ID"}, + {eErrorInvalidParam, "Incorrect parameter"}, + {eErrorTimeOut, "Acquisition timeout"}, + {eErrorGenCount, "Invalid number of fingerprint synthesis"}, + {eErrorInvalidBufferID, "Incorrect Buffer ID value"}, + {eErrorFPNotDetected, "No fingerprint input into fingerprint reader"}, + {eErrorFPCancel, "Command cancelled"}, + {eErrorRecvLength, "Wrong data length"}, + {eErrorRecvCks, "Wrong data check code"}, + {eErrorGatherOut, "Exceed upper limit of acquisition times"}, + {eErrorRecvTimeout,"Data reading timeout"} +}; + +String DFRobot_ID809::getErrorDescription() +{ + for(int i=0;i<sizeof(errorDescriptionsTable)/sizeof(errorDescriptionsTable[0]);i++){ + if(_error == errorDescriptionsTable[i].error){ + return errorDescriptionsTable[i].description; + } + } + return ""; +} + + diff --git a/matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.h b/matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.h new file mode 100644 index 0000000..83ca50d --- /dev/null +++ b/matchFPandHash/lib/DFRobot_ID809/DFRobot_ID809.h @@ -0,0 +1,504 @@ +/*! + * @file DFRobot_ID809.h + * @brief Define basic structure of DFRobot_ID809 class + * @n This is an library for capacitive fingerprint module + * @n Main functions: fingerprint image capturing, fingerprint comparison, fingerprint deletion + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#ifndef _DFRobot_ID809_H +#define _DFRobot_ID809_H + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif +#include <Wire.h> + +#include <stdint.h> + +//Open this macro to see the detailed running process of the program + +//#define ENABLE_DBG +#ifdef ENABLE_DBG +#define LDBG(...) if(dbg) {dbg->print("["); dbg->print(__FUNCTION__); dbg->print("(): "); dbg->print(__LINE__); dbg->print(" ] "); dbg->println(__VA_ARGS__);} +#else +#define LDBG(...) +#endif + +extern Stream *dbg; + + /* + Frame struct of command packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t CMD; + uint16_t LEN; + uint8_t payload[0]; +}__attribute__ ((packed)) sCmdPacketHeader_t, *pCmdPacketHeader_t; + + /* + Frame struct of response packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t RCM; + uint16_t LEN; + uint16_t RET; + uint8_t payload[0]; +}__attribute__ ((packed)) sRcmPacketHeader_t, *pRcmPacketHeader_t; + + + + +class DFRobot_ID809{ +public: + +//#define FINGERPRINT_CAPACITY 80 //Fingerprint module capacity +#define MODULE_SN_SIZE 16 //Module SN length + + +#define DELALL 0xFF //Delete all fingerprints + +#define CMD_PREFIX_CODE 0xAA55 //Command packet prefix code +#define RCM_PREFIX_CODE 0x55AA //Response packet prefix code +#define CMD_DATA_PREFIX_CODE 0xA55A //Command data packet prefix code +#define RCM_DATA_PREFIX_CODE 0x5AA5 //Response data packet prefix code + +#define CMD_TYPE 0xF0 //Command packet type +#define RCM_TYPE 0xF0 //Response packet type +#define DATA_TYPE 0x0F //Data packet type + +#define CMD_TEST_CONNECTION 0X0001 //Test connection +#define CMD_SET_PARAM 0X0002 //Set parameter +#define CMD_GET_PARAM 0X0003 //Read parameter +#define CMD_DEVICE_INFO 0X0004 //Read device information +#define CMD_SET_MODULE_SN 0X0008 //Set module serial number +#define CMD_GET_MODULE_SN 0X0009 //Read module serial number +#define CMD_ENTER_STANDBY_STATE 0X000C //Enter sleep mode +#define CMD_GET_IMAGE 0X0020 //Capture fingerprint image +#define CMD_FINGER_DETECT 0X0021 //Detect fingerprint + #define CMD_UP_IMAGE_CODE 0X0022 //Upload fingerprint image to host + #define CMD_DOWN_IMAGE 0X0023 //Download fingerprint image to module +#define CMD_SLED_CTRL 0X0024 //Control collector backlight +#define CMD_STORE_CHAR 0X0040 //Save fingerprint template data into fingerprint library +#define CMD_LOAD_CHAR 0X0041 //Read fingerprint in module and save it in RAMBUFFER temporarily + #define CMD_UP_CHAR 0X0042 //Upload the fingerprint template saved in RAMBUFFER to host + #define CMD_DOWN_CHAR 0X0043 //Download fingerprint template to module designated RAMBUFFER +#define CMD_DEL_CHAR 0X0044 //Delete fingerprint in specific ID range +#define CMD_GET_EMPTY_ID 0X0045 //Get the first registerable ID in specific ID range +#define CMD_GET_STATUS 0X0046 //Check if the designated ID has been registered +#define CMD_GET_BROKEN_ID 0X0047 //Check whether there is damaged data in fingerprint library of specific range +#define CMD_GET_ENROLL_COUNT 0X0048 //Get the number of registered fingerprints in specific ID range +#define CMD_GET_ENROLLED_ID_LIST 0X0049 //Get registered ID list +#define CMD_GENERATE 0X0060 //Generate template from the fingerprint images saved in IMAGEBUFFER temporarily +#define CMD_MERGE 0X0061 //Synthesize fingerprint template data +#define CMD_MATCH 0X0062 //Compare templates in 2 designated RAMBUFFER +#define CMD_SEARCH 0X0063 //1:N Recognition in specific ID range +#define CMD_VERIFY 0X0064 //Compare specific RAMBUFFER template with specific ID template in fingerprint library + +#define ERR_SUCCESS 0x00 //Command processed successfully +#define ERR_ID809 0xFF //error + + +public: + + typedef enum{ + eBreathing = 1, //Breathing + eFastBlink, //Quick blink + eKeepsOn, //On + eNormalClose, //Off + eFadeIn, //Fade in + eFadeOut, //Fade out + eSlowBlink //Slow blink + }eLEDMode_t; + + typedef enum{ + eLEDGreen = 1, //green + eLEDRed, //red + eLEDYellow, //yellow + eLEDBlue, //blue + eLEDCyan, //cyan + eLEDMagenta, //magenta + eLEDWhite //white + }eLEDColor_t; + + typedef enum{ + e9600bps = 1, + e19200bps, + e38400bps, + e57600bps, + e115200bps + }eDeviceBaudrate_t; + + typedef enum{ + eErrorSuccess = 0x00, //Command processed successfully + eErrorFail = 0x01, //Command processing failed + eErrorVerify = 0x10, //1:1 Templates comparison in specific ID failed + eErrorIdentify = 0x11, //1:N comparison has been made, no same templates here + eErrorTmplEmpty = 0x12, //No registered template in the designated ID + eErrorTmplNotEmpty = 0x13, //Template already exists in the specified ID + eErrorAllTmplEmpty = 0x14, //No registered Template + eErrorEmptyIDNoexist = 0x15, //No registerable Template ID + eErrorBrokenIDNoexist = 0x16, //No damaged Template + eErrorInvalidTmplData = 0x17, //The designated Template Data is invalid + eErrorDuplicationID = 0x18, //The fingerprint has been registered + eErrorBadQuality = 0x19, //Poor quality fingerprint image + eErrorMergeFail = 0x1A, //Template synthesis failed + eErrorNotAuthorized = 0x1B, //Communication password not authorized + eErrorMemory = 0x1C, //Error in exernal Flash burning + eErrorInvalidTmplNo = 0x1D, //The designated template ID is invalid + eErrorInvalidParam = 0x22, //Incorrect parameter has been used + eErrorTimeOut = 0x23, //Acquisition timeout + eErrorGenCount = 0x25, //Invalid number of fingerprint synthesis + eErrorInvalidBufferID = 0x26, //Wrong Buffer ID value + eErrorFPNotDetected = 0x28, //No fingerprint input into fingerprint reader + eErrorFPCancel = 0x41, //Command cancelled + eErrorRecvLength = 0x42, //Wrong length of recieved data + eErrorRecvCks = 0x43, //Wrong check code + eErrorGatherOut = 0x45, //Exceed upper limit of acquisition times + eErrorRecvTimeout = 0x46 //Communication timeout + }eError_t; + + typedef struct{ + /**< Gesture enumeration variable X */ + eError_t error; + /**< Description about the gesture enumeration variable X */ + const char * description; + }sErrorDescription_t; + +public: + DFRobot_ID809(); + ~DFRobot_ID809(); + + /** + * @brief Init communication port + * @param Software serial or hardware serial + * @return true or false + */ + bool begin(Stream &s_); + + /** + * @brief Test whether the module connection is ok + * @return true or false + */ + bool isConnected(); + + /** + * @brief Set module ID + * @param ID:1-255 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDeviceID(uint8_t deviceID); + + /** + * @brief Set module security level + * @param security level:1-5 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSecurityLevel(uint8_t securityLevel); + + /** + * @brief Set module fingerprint replication check (Check whether the fingperint has been registered when saving it) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDuplicationCheck(uint8_t duplicationCheck); + + /** + * @brief Set module baud rate + * @param Baudrate:in typedef enum eDeviceBaudrate_t + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setBaudrate(eDeviceBaudrate_t baudrate); + + /** + * @brief Set module self-learning function (Update fingeprint when fingerprint comparison succeeds) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSelfLearn(uint8_t selfLearn); + + /** + * @brief Read module ID + * @return IDå·:1-255 or ERR_ID809 + */ + uint8_t getDeviceID(); + + /** + * @brief Read module security level + * @return Security level:1-5 or ERR_ID809 + */ + uint8_t getSecurityLevel(); + + /** + * @brief Read module fingerprint replication check status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getDuplicationCheck(); + + /** + * @brief Read module baud rate + * @return Baudrate:in typedef enum eDEVICE_BAUDRATE_t or ERR_ID809 + */ + uint8_t getBaudrate(); + + /** + * @brief Read module self-learning function status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getSelfLearn(); + uint8_t getTemplate(uint16_t id,uint8_t * temp); + uint8_t downLoadTemplate(uint16_t id,uint8_t * temp); + uint8_t getFingerImage(uint8_t *image); + uint8_t downLoadImage(uint16_t id,uint8_t * temp); + uint8_t receiveImageData(uint8_t *image); + uint8_t getQuarterFingerImage(uint8_t *image); + uint8_t contrastTemplate(uint8_t *temp); + /** + * @brief Read device number + * @return Device number + */ + String getDeviceInfo(); + + /** + * @brief Set serial number + * @param String pointer + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setModuleSN(const char* SN); + /** + * @brief Read serial number + * @return Serial number + */ + String getModuleSN(); + + /** + * @brief Set LED + * @param mode:in typedef enum eLEDMode_t + * @param color:in typedef enum eLEDColor_t + * @param blink Count: 00 represents blinking all the time + * @This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + * @return 0(succeed) or ERR_ID809 + */ + uint8_t ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount); + + /** + * @brief Detect if there is finger touched + * @return 1(Touched) or 0(No touch) + */ + uint8_t detectFinger(); + + /** + * @brief Get the first registerable ID + * @return Registerable ID or ERR_ID809 + */ + uint8_t getEmptyID(); + + /** + * @brief Check if the ID has been registered + * @return 0(Registered), 1(Unregistered) or ERR_ID809 + */ + uint8_t getStatusID(uint8_t ID); + + /** + * @brief Get the number of registered users + * @return Number of registered users or ERR_ID809 + */ + uint8_t getEnrollCount(); + + /** + * @brief Get registered user list + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getEnrolledIDList(uint8_t* list); + + /** + * @brief Fingerprint acquisition + * @return 0(succeed) or ERR_ID809 + */ + uint8_t collectionFingerprint(uint16_t timeout,int ramNumber = -1); + + /** + * @brief Save fingerprint + * @param Fingerprint ID + * @return 0(succeed) or ERR_ID809 + */ + uint8_t storeFingerprint(uint8_t ID); + + /** + * @brief Delete fingerprint + * @param Delete ID or DELALL(delete all) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t delFingerprint(uint8_t ID); + + /** + * @brief Match the fingerprint with all fingeprints + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t search(); + + /** + * @brief Match the fingerprint with specific fingerprint + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t verify(uint8_t ID); + + /** + * @brief Compare templates in two specific RamBuffers + * @param RamBuffer number + * @param RamBuffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t match(uint8_t RamBufferID0, uint8_t RamBufferID1); + + /** + * @brief Get the number of damaged fingerprints + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenQuantity(); + + /** + * @brief Get the first damaged fingerprint ID + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenID(); + + /** + * @brief Take out fingerprint template, temporarily save into RamBuffer + * @param Fingerprint ID + * @param RamBuffer number 0-2 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t loadFingerprint(uint8_t ID, uint8_t RamBufferID); + + /** + * @brief Enter Standby mode + * @return 0(succeed) or ERR_ID809 + */ + uint8_t enterStandbyState(); + + /** + * @brief Get error information + * @return Text description of error information + */ + String getErrorDescription(); + + bool setDbgSerial(Stream &s_){dbg = &s_; return true;} + uint16_t FINGERPRINT_CAPACITY = 80; +protected: + /** + * @brief Set parameter + * @param Data type+ data + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setParam(uint8_t* data); + + /** + * @brief Read parameter + * @param Data type + * @return data or ERR_ID809 + */ + uint8_t getParam(uint8_t* data); + + /** + * @brief Capture fingerprint image + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getImage(); + + /** + * @brief Take image as template + * @param Ram Buffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t generate(uint8_t RamBufferID); + + /** + * @brief Fingerprint synthesis + * @return 0(succeed) or ERR_ID809 + */ + uint8_t merge(); + + /** + * @brief Packing data frame + * @param Data type:CMD_TYPE or DATA_TYPE + * @param Command + * @param Data + * @param Length + * @return Data frame + */ + pCmdPacketHeader_t pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len); + + /** + * @brief Send data + * @param Data frame + */ + void sendPacket(pCmdPacketHeader_t header); + + /** + * @brief Read byte + * @param Pointer for saving data + * @param Length of data to be received + * @return Actual received data length + */ + size_t readN(void* buf_, size_t len); + + /** + * @brief Read frame header + * @param Frame header struct of response packet + * @return Response packet type:RCM_TYPE,DATA_TYPE or 1(reading timeout) + */ + uint16_t readPrefix( pRcmPacketHeader_t header ); + + /** + * @brief Read data + * @param Pointer for saving data + * @return 0(success) or ERR_ID809 + */ + uint8_t responsePayload(void* buf); + + /** + * @brief Get command packet CKS + * @param Command packet frame + * @return CKS + */ + uint16_t getCmdCKS(pCmdPacketHeader_t packet); + + /** + * @brief Get response packet CKS + * @param Response packet frame + * @return CKS + */ + uint16_t getRcmCKS(pRcmPacketHeader_t packet); + uint8_t store(uint8_t ID); + +private: + Stream *s; + uint8_t buf[20]; //For saving response packet data + pCmdPacketHeader_t sendHeader; + pRcmPacketHeader_t recHeader; + + static const sErrorDescription_t /*PROGMEM*/ errorDescriptionsTable[26]; //Error information list + + uint8_t _number = 0; //Fingerprint acquisistion times + uint8_t _state = 0; //Collect fingerprint state + eError_t _error; //Error code + uint16_t _PacketSize = 0; //Data packet length to be sent +}; + +#endif + diff --git a/matchFPandHash/platformio.ini b/matchFPandHash/platformio.ini new file mode 100644 index 0000000..7a3aa31 --- /dev/null +++ b/matchFPandHash/platformio.ini @@ -0,0 +1,13 @@ +[env:Teensy_FP] + +platform = teensy +framework = arduino +board = teensy31 + +build_flags = + -I lib/DFRobot_ID809 + +lib_deps = + intrbiz/crypto + + diff --git a/matchFPandHash/src/src.cpp b/matchFPandHash/src/src.cpp new file mode 100644 index 0000000..7afea72 --- /dev/null +++ b/matchFPandHash/src/src.cpp @@ -0,0 +1,178 @@ +#include <Arduino.h> +#include <Crypto.h> +#include <DFRobot_ID809.h> +#include <EEPROM.h> + +// use serial3 as interface with fingerprint +// sensor. + +#define FPSerial Serial3 + +// define buillt_in led + +#define BUILTIN_LED 13 + +// Collect the fingerprint 3 times + +#define COLLECT_NUMBER 3 + +/*------Global variables--------------*/ + +DFRobot_ID809 fingerprint; +uint8_t ID, i, ret; +byte hash[SHA256_SIZE]; +uint8_t temp[1008]; +// EEPROM OFFSET to store + +const uint16_t EEPROM_FP_HASH = 1696; + +/*---------Compute hash----------------*/ + +void compute_hash() { + + SHA256 hasher; + hasher.doUpdate(temp, sizeof(temp)); + hasher.doFinal(hash); + + Serial.println("-----------------------"); + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + if (hash[i] < 0x10) { + + Serial.print('0'); + } + + Serial.print(hash[i], HEX); + Serial.print(" "); + } + Serial.println("-----------------------"); +} + +/*-----Blink on board led -------------- */ + +void blink_led() { + digitalWrite(BUILTIN_LED, HIGH); + delay(500); + digitalWrite(BUILTIN_LED, LOW); + delay(500); +} + +/*-------- Save FingerPrint hash in EEPROM ------*/ + +void compareHash() { + uint16_t memoryAddress; + byte stored_hash[SHA256_SIZE]; + + memoryAddress = EEPROM_FP_HASH + ((ID - 1) * 32); + + Serial.println("---------------------------"); + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + stored_hash[i] = EEPROM.read(memoryAddress); + Serial.print(stored_hash[i], HEX); + Serial.print(" "); + memoryAddress++; + } + Serial.println("--------------------------"); + + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + if (stored_hash[i] != hash[i]) { + Serial.println("Hash not matched"); + return; + } + } + Serial.println("Hash matched"); +} + +/*---------Arduino setup function------*/ + +void setup() { + // config led_pin as output + pinMode(BUILTIN_LED, OUTPUT); + // use serial port to print the baud rate + Serial.begin(9600); + // config fingerprint sensor + FPSerial.begin(115200); + fingerprint.begin(FPSerial); + + while (fingerprint.isConnected() == false) { + Serial.println("Communication with the device failed"); + delay(1000); + } +} + +/*---------Register Finger print ------------*/ + +void matchFingerprint() { + + /*Set fingerprint LED ring mode, color, and number of blinks + Can be set as follows: + Parameter 1:<LEDMode> + eBreathing eFastBlink eKeepsOn eNormalClose + eFadeIn eFadeOut eSlowBlink + Parameter 2:<LEDColor> + eLEDGreen eLEDRed eLEDYellow eLEDBlue + eLEDCyan eLEDMagenta eLEDWhite + Parameter 3:<Number of blinks> 0 represents blinking all the time + This parameter will only be valid in mode eBreathing, eFastBlink, + eSlowBlink + */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eBreathing, + /*LEDColor = */ fingerprint.eLEDBlue, + /*blinkCount = */ 0); + + Serial.println("Plase press down your finger"); + + if ((fingerprint.collectionFingerprint(/*timeout = */ 0)) != ERR_ID809) { + /*Set fingerprint LED ring to quick blink in yellow 3 times */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eFastBlink, + /*LEDColor = */ fingerprint.eLEDYellow, + /*blinkCount = */ 3); + Serial.println("capturing succeeds"); + Serial.println("Please release your finger"); + + while (fingerprint.detectFinger()) + ; + + /*Compare the captured fingerprint with all the fingerprints + * inthe fingerprint library return fingerprint ID if succeed, + * return 0 when failed + * */ + ret = fingerprint.search(); + + if (ret != 0) { + + /*Set fingerprint LED ring to always ON in green */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eKeepsOn, + /*LEDColor = */ fingerprint.eLEDGreen, + /*blinkCount = */ 0); + Serial.print("Matching succeeds,ID="); + ID = ret; + Serial.println(ret); + fingerprint.getTemplate(ID, temp); + delay(100); + compute_hash(); + compareHash(); + + } else { + /*Set fingerprint LED ring to always ON in red*/ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eKeepsOn, + /*LEDColor = */ fingerprint.eLEDRed, + /*blinkCount = */ 0); + Serial.println("Matching fails"); + } + } else { + Serial.println("Capturing failes"); + /*Get error code information*/ + // desc = fingerprint.getErrorDescription(); + // Serial.println(desc); + } +} + +/*-----------Arduino loop function--------- */ + +void loop() { + blink_led(); + matchFingerprint(); +} diff --git a/readTemplate/lib/DFRobot_ID809/DFRobot_ID809.cpp b/readTemplate/lib/DFRobot_ID809/DFRobot_ID809.cpp new file mode 100644 index 0000000..d49f6f4 --- /dev/null +++ b/readTemplate/lib/DFRobot_ID809/DFRobot_ID809.cpp @@ -0,0 +1,1089 @@ +/*! + * @file DFRobot_ID809.cpp + * @brief Define the basic structure of DFRobot_ID809 class and the implementation of underlying methods + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#include <DFRobot_ID809.h> +#include <Arduino.h> +#include <string.h> +#include <stdio.h> +Stream *dbg=NULL; + +DFRobot_ID809::DFRobot_ID809() + :s(NULL){ + +} + +DFRobot_ID809::~DFRobot_ID809(){ + +} + +bool DFRobot_ID809::begin(Stream &s_){ + s = &s_; + String str = getDeviceInfo(); + //Serial.println(str[str.length()-1]); + if(str[str.length()-1] == '4'){ + + FINGERPRINT_CAPACITY = 80 ; + + //Serial.println(str[str.length()-1]); + }else if(str[str.length()-1] == '3'){ + //Serial.println(str[str.length()-1]); + FINGERPRINT_CAPACITY = 200 ; + + } + + if(s == NULL){ + return false; + } + return true; +} + +bool DFRobot_ID809::isConnected(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_TEST_CONNECTION, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + return true; + }else{ + return false; + } +} + +uint8_t DFRobot_ID809::setDeviceID(uint8_t deviceID){ + uint8_t data[5] = {0}; //data:1bytes Parameter Type+4bytes Parameter Value + data[1] = deviceID; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSecurityLevel(uint8_t securityLevel){ + uint8_t data[5] = {0}; + data[0] = 1; + data[1] = securityLevel; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setDuplicationCheck(uint8_t duplicationCheck){ + uint8_t data[5] = {0}; + data[0] = 2; + data[1] = duplicationCheck; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setBaudrate(eDeviceBaudrate_t baudrate){ + uint8_t data[5] = {0}; + data[0] = 3; + data[1] = baudrate; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::setSelfLearn(uint8_t selfLearn){ + uint8_t data[5] = {0}; + data[0] = 4; + data[1] = selfLearn; + uint8_t ret = setParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDeviceID(){ + uint8_t data[1]; //data:1byte Parameter Type + data[0] = 0; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSecurityLevel(){ + uint8_t data[1]; + data[0] = 1; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getDuplicationCheck(){ + uint8_t data[1]; + data[0] = 2; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getBaudrate(){ + uint8_t data[1]; + data[0] = 3; + uint8_t ret = getParam(data); + return ret; +} + +uint8_t DFRobot_ID809::getSelfLearn(){ + uint8_t data[1]; + data[0] = 4; + uint8_t ret = getParam(data); + return ret; +} + +String DFRobot_ID809::getDeviceInfo(){ + char *data; + uint8_t result; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEVICE_INFO, NULL, 0); + sendPacket(header); + free(header); + result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::setModuleSN(const char* SN){ + char data[2]; + data[0] = MODULE_SN_SIZE; + if(strlen(SN) > MODULE_SN_SIZE){ + LDBG("The serial number exceeds 15 characters"); + return ERR_ID809; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_MODULE_SN, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + header = pack(DATA_TYPE, CMD_SET_MODULE_SN, SN, MODULE_SN_SIZE); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getTemplate(uint16_t id,uint8_t * temp){ + char data[4]; + data[0] = id; + data[1] = 0; + data[2] = 0; + data[3] = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + data[0] = 0; + data[1] = 0; + header = pack(CMD_TYPE, CMD_UP_CHAR, data, 2); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + ret = responsePayload(temp); + + return ret; +} + +uint8_t DFRobot_ID809::downLoadTemplate(uint16_t id,uint8_t * temp){ + + char data[4]; + data[0] = 0xf2; + data[1] = 3; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_CHAR, data, 2); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(0x3f2 +1); + tempData[0] = 0; + tempData[1] = 0; + memcpy(tempData+2,temp,0x3f0); + + + header = pack(DATA_TYPE, CMD_DOWN_CHAR, tempData, 0x3f2); + + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + free(tempData); + + + return store(id); +} + +uint8_t DFRobot_ID809::contrastTemplate(uint8_t *temp){ + + char data[4]; + data[0] = 0xf2; + data[1] = 3; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_CHAR, data, 2); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(0x3f2 +1); + tempData[0] = 2; + tempData[1] = 0; + memcpy(tempData+2,temp,0x3f0); + + + header = pack(DATA_TYPE, CMD_DOWN_CHAR, tempData, 0x3f2); + + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret == ERR_SUCCESS) { + ret = buf[0]; + } + free(tempData); + data[0] = 0; + data[1] = 0; + data[2] = 2; + data[3] = 0; + header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ret; + } + return ret; + +} +uint8_t DFRobot_ID809::getFingerImage(uint8_t *image) +{ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + char data[1]; + data[0] = 0; + header = pack(CMD_TYPE, CMD_UP_IMAGE_CODE, data, 1); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500 +1); + for(uint8_t i=0;i<52;i++){ + + ret = responsePayload(tempData); + if(i == 51) + memcpy(image+i*496,tempData+2,304); + else + memcpy(image+i*496,tempData+2,496); + } + free(tempData); +} +uint8_t DFRobot_ID809::getQuarterFingerImage(uint8_t *image){ + + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + char data[1]; + data[0] = 1; + header = pack(CMD_TYPE, CMD_UP_IMAGE_CODE, data, 1); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500 +1); + for(uint8_t i=0;i<13;i++){ + + ret = responsePayload(tempData); + if(i == 12) + memcpy(image+i*496,tempData+2,448); + else + memcpy(image+i*496,tempData+2,496); + } + free(tempData); + +} +uint8_t DFRobot_ID809::downLoadImage(uint16_t id,uint8_t * temp) +{ + char data[4]; + data[0] = 0xa0; + data[1] = 0; + data[2] = 0xa0; + data[3] = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DOWN_IMAGE, data, 4); + sendPacket(header); + free(header); + + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + char *tempData= (char *)malloc(500); + for(uint8_t i =0 ;i<52;i++){ + tempData[0] = i; + tempData[1] = 0; + if(i == 51){ + memcpy(tempData+2,temp+i*496,304); + header = pack(DATA_TYPE, CMD_DOWN_IMAGE, tempData, 306); + }else{ + memcpy(tempData+2,temp+i*496,496); + header = pack(DATA_TYPE, CMD_DOWN_IMAGE, tempData, 498); + } + sendPacket(header); + + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + + } + free(tempData); + + data[0] = 0; + data[1] = 0; + header = pack(CMD_TYPE, CMD_GENERATE, data, 2); + sendPacket(header); + free(header); + + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + if(ret != ERR_SUCCESS) { + // return ERR_ID809; + } + return store(id); + +} + +uint8_t DFRobot_ID809::receiveImageData(uint8_t * image){ + + + + uint8_t ret = responsePayload(image); + if(ret != ERR_SUCCESS) { + return ERR_ID809; + } + +} +String DFRobot_ID809::getModuleSN(){ + char *data; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_MODULE_SN, NULL, 0); + sendPacket(header); + free(header); + uint8_t result = responsePayload(buf); + LDBG("result=");LDBG(result); + if(result != ERR_SUCCESS){ + return ""; + } + uint16_t dataLen = buf[0]+(buf[1]<<8)+1; + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + data[dataLen] = 0; + result = responsePayload(data); + LDBG("result=");LDBG(result); + String ret = String(data); + free(data); + return ret; +} + +uint8_t DFRobot_ID809::ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount){ + char data[4] = {0}; + if(FINGERPRINT_CAPACITY == 80){ + data[0] = mode; + data[2] = data[1] = color; + data[3] = blinkCount; + }else{ + if(mode == 1){ + data[0] = 2; + } else if(mode == 2){ + data[0] = 4; + } else if(mode == 3){ + data[0] = 1; + } else if(mode == 4){ + data[0] = 0; + } else if(mode == 5){ + data[0] = 3; + } + if(color == eLEDGreen){ + data[2] = data[1] = 0x84; + }else if(color == eLEDRed){ + data[2] = data[1] = 0x82; + }else if(color == eLEDYellow){ + data[2] = data[1] = 0x86; + }else if(color == eLEDBlue){ + data[2] = data[1] = 0x81; + }else if(color == eLEDCyan){ + data[2] = data[1] = 0x85; + }else if(color == eLEDMagenta){ + data[2] = data[1] = 0x83; + }else { + data[2] = data[1] = 0x87; + } + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SLED_CTRL, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::detectFinger(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_FINGER_DETECT, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEmptyID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; //80 fingerprints at most, default to full range + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_EMPTY_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getStatusID(uint8_t ID){ + char data[2] = {0}; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_STATUS, data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getEnrollCount(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLL_COUNT, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +#define getID(A, V) (A[0 + V/8] & (0x01 << (V & 0x07))) +uint8_t DFRobot_ID809::getEnrolledIDList(uint8_t* list) +{ + char *data; + uint8_t i = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_ENROLLED_ID_LIST, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + uint16_t dataLen = buf[0]+(buf[1]<<8); + if((data = (char *)malloc(dataLen)) == NULL){ + LDBG("no memory!!!\r\n"); + while(1); + } + ret = responsePayload(data); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else{ + for(uint16_t j = 0; j < (dataLen*8); j++){ + if(getID(data, j) != 0){ + list[i] = j; + i++; + } + } + } + free(data); + return ret; +} + +uint8_t DFRobot_ID809::storeFingerprint(uint8_t ID){ + char data[4] = {0}; + uint8_t ret; + ret = merge(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + return ERR_ID809; + } + _number = 0; + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; + +} +uint8_t DFRobot_ID809::store(uint8_t ID){ + + + char data[4] = {0}; + uint8_t ret; + LDBG("ret="); + LDBG(ret); + data[0] = ID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_STORE_CHAR, data, 4); + sendPacket(header); + free(header); + ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + return ret; +} +uint8_t DFRobot_ID809::delFingerprint(uint8_t ID) +{ + char data[4] = {0}; + if(ID == DELALL) { + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + } else { + data[0] = data[2] = ID; + } + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_DEL_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret="); + LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::search(){ + if(_state == 1){ + char data[6] = {0}; + data[2] = 1; + data[4] = FINGERPRINT_CAPACITY; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SEARCH, data, 6); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; + } + return 0; +} + +uint8_t DFRobot_ID809::verify(uint8_t ID){ + if(_state == 1){ + char data[4] = {0}; + data[0] = ID; + _number = 0; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_VERIFY, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; + } + return 0; +} + +uint8_t DFRobot_ID809::match(uint8_t RamBufferID0, uint8_t RamBufferID1){ + char data[4] = {0}; + data[0] = RamBufferID0; + data[2] = RamBufferID1; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MATCH, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + }else{ + ret = 0; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenQuantity(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getBrokenID(){ + char data[4] = {0}; + data[0] = 1; + data[2] = FINGERPRINT_CAPACITY; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_BROKEN_ID, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[2]; + } + return ret; +} + +uint8_t DFRobot_ID809::loadFingerprint(uint8_t ID, uint8_t RamBufferID){ + char data[4] = {0}; + data[0] = ID; + data[2] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_LOAD_CHAR, data, 4); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::enterStandbyState(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_ENTER_STANDBY_STATE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::setParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_SET_PARAM, (const char *)data, 5); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::getParam(uint8_t* data){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_PARAM, (const char *)data, 1); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + if(ret == ERR_SUCCESS){ + ret = buf[0]; + } + return ret; +} + +uint8_t DFRobot_ID809::getImage(){ + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GET_IMAGE, NULL, 0); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::collectionFingerprint(uint16_t timeout,int ramNumber){ //Collect fingerprint + uint16_t i = 0; + uint8_t ret; + if(ramNumber == -1){ + if(_number > 2){ + _error = eErrorGatherOut; + LDBG("Exceed upper limit of acquisition times "); + return ERR_ID809; + } + } + while(!detectFinger()){ + if(timeout != 0){ + delay(10); + if(++i > timeout*10){ + _error = eErrorTimeOut; + LDBG("Acquisition timeout "); + LDBG("ret=");LDBG(ret); + _state = 0; + return ERR_ID809; + } + } + } + ret = getImage(); + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + _state = 0; + return ERR_ID809; + } + if(ramNumber != -1){ + ret = generate(ramNumber); + } else{ + ret = generate(_number); + } + LDBG("ret=");LDBG(ret); + if(ret != ERR_SUCCESS){ + _state = 0; + return ERR_ID809; + } + _number++; + _state = 1; + return ret; +} + +uint8_t DFRobot_ID809::generate(uint8_t RamBufferID){ + char data[2] = {0}; + data[0] = RamBufferID; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_GENERATE, (const char *)data, 2); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +uint8_t DFRobot_ID809::merge(){ + char data[3] = {0}; + data[2] = _number; + pCmdPacketHeader_t header = pack(CMD_TYPE, CMD_MERGE, data, 3); + sendPacket(header); + free(header); + uint8_t ret = responsePayload(buf); + LDBG("ret=");LDBG(ret); + return ret; +} + +pCmdPacketHeader_t DFRobot_ID809::pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len){ + pCmdPacketHeader_t header; + uint16_t cks=0; + uint16_t dataLen; + if(type == CMD_TYPE){ //Structure of command packet, fixed 26 bytes:10(frame header)+14(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+16+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_PREFIX_CODE; + for(int i=0;i<16;i++){ + header->payload[i] = 0; + } + dataLen = 16; //Length of data to be replicated + }else{ //Structure of command data packet, unfixed length:10(frame header)+LEN(data)+2(CKS) + if((header = (pCmdPacketHeader_t)malloc(sizeof(sCmdPacketHeader_t)+len+2)) == NULL){ + return NULL; + } + header->PREFIX = CMD_DATA_PREFIX_CODE; + dataLen = len; //Length of data to be replicated + } + header->SID = 0; + header->DID = 0; + header->CMD = cmd; + header->LEN = len; + if(len){ + memcpy(header->payload, payload, len); + } + cks = getCmdCKS(header); + memcpy(&header->payload[dataLen],&cks,2); + _PacketSize = sizeof(sCmdPacketHeader_t) + dataLen +2; + return header; +} + + +void DFRobot_ID809::sendPacket(pCmdPacketHeader_t header){ + s->write((uint8_t *)header,_PacketSize); +} + +uint8_t DFRobot_ID809::responsePayload(void* buf){ + sRcmPacketHeader_t header; + uint16_t dataLen,dataCount,cks; + uint8_t ch,ret; + int16_t type; + type = readPrefix(&header); + if(type == 1){ + LDBG("--recv timeout---"); + _error = eErrorRecvTimeout; + return ERR_ID809; + } + pRcmPacketHeader_t packet; + if(type == RCM_TYPE){ //Structure of response packet, fixed 26 bytes: 10(frame header)+14(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+14+2); + dataLen = 14+2; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + }else{ //Structure of response data packet, unfixed length: 10(frame header)+(LEN-2)(data)+2(CKS) + packet = (pRcmPacketHeader_t)malloc(sizeof(sRcmPacketHeader_t)+header.LEN); + dataLen = header.LEN; //Length of data+CKS + if(packet == NULL){ + LDBG(""); + while(1); + } + } + memcpy(packet, &header, 10); + dataCount = readN(packet->payload, dataLen); + cks = packet->payload[dataLen-2]+(packet->payload[dataLen-1]<<8); + ret = (header.RET&0xFF); + _error = (eError_t)ret; + if(ret != ERR_SUCCESS){ + ret = ERR_ID809; + }else if(dataLen != dataCount){ + LDBG("--recvRspPacket length error---"); + _error = eErrorRecvLength; + ret = ERR_ID809; + }else if(getRcmCKS(packet) != cks){ + LDBG("--recvRspPacket cks error---"); + _error = eErrorRecvCks; + ret = ERR_ID809; + }else{ + LDBG("--recvRspPacket OK---"); + memcpy(buf, packet->payload, dataLen); + } + free(packet); + packet = NULL; + return ret; +} + +uint16_t DFRobot_ID809::readPrefix( pRcmPacketHeader_t header ){ + uint8_t ch,ret; + typedef enum{ + RECV_HEADER_INIT, + RECV_HEADER_AA, + RECV_HEADER_A5, + RECV_HEADER_OK + }eRecvHeaderState; + eRecvHeaderState state = RECV_HEADER_INIT; + while(state != RECV_HEADER_OK){ //Can judge the received command packet and command data packet prefix at the same time + if(readN(&ch, 1) != 1){ + ret = 1; + return ret; + } + if((ch == 0xAA) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_AA; + continue; + }else if((ch == 0xA5) && (state == RECV_HEADER_INIT)){ + state = RECV_HEADER_A5; + continue; + }else if((ch == 0x55) && (state == RECV_HEADER_AA)){ + state = RECV_HEADER_OK; + ret = RCM_TYPE; + continue; + }else if((ch == 0x5A) && (state == RECV_HEADER_A5)){ + state = RECV_HEADER_OK; + ret = DATA_TYPE; + continue; + }else{ + state = RECV_HEADER_INIT; + if(ch == 0xAA){ + state = RECV_HEADER_AA; + }else if(ch == 0xA5){ + state = RECV_HEADER_A5; + } + } + } + if(ret == RCM_TYPE){ + header->PREFIX = RCM_PREFIX_CODE; + }else if(ret == DATA_TYPE){ + header->PREFIX = RCM_DATA_PREFIX_CODE; + } + readN(&header->SID, 1); + readN(&header->DID, 1); + readN(&header->RCM, 2); + readN(&header->LEN, 2); + readN(&header->RET, 2); + return ret; +} + +size_t DFRobot_ID809::readN(void* buffer, size_t len){ + size_t offset = 0,left = len; + uint8_t *buf = (uint8_t*)buffer; + long long curr = millis(); + while(left){ + if(s->available()){ + buf[offset++] = s->read(); + left--; + } + if(millis() - curr > 5000){ + LDBG("----------!!!!!!!!!recv timeout----------"); + break; + } + } + return offset; +} + +uint16_t DFRobot_ID809::getCmdCKS(pCmdPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->CMD&0xFF; + cks += packet->CMD>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint16_t i = 0; i < packet->LEN; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +uint16_t DFRobot_ID809::getRcmCKS(pRcmPacketHeader_t packet){ + uint16_t cks = 0xFF; + cks += packet->SID; + cks += packet->DID; + cks += packet->RCM&0xFF; + cks += packet->RCM>>8; + cks += packet->LEN&0xFF; + cks += packet->LEN>>8; + cks += packet->RET&0xFF; + cks += packet->RET>>8; + if(packet->LEN > 0){ + uint8_t *p = packet->payload; + for(uint16_t i = 0; i < packet->LEN-2; i++){ + cks += p[i]; + } + } + return cks&0xFFFF; +} + +const DFRobot_ID809::sErrorDescription_t DFRobot_ID809::errorDescriptionsTable[]={ + {eErrorSuccess, "Command processed successfully"}, + {eErrorFail, "Command processing failed"}, + {eErrorVerify, "1:1 comparison failed"}, + {eErrorIdentify, "Comparison with all fingerprints failed"}, + {eErrorTmplEmpty, "No fingerprint in designated ID"}, + {eErrorTmplNotEmpty, "Designated ID has fingerprint"}, + {eErrorAllTmplEmpty, "Module unregistered fingerprint"}, + {eErrorEmptyIDNoexist, "No registerable ID here"}, + {eErrorBrokenIDNoexist, "No broken fingerprint"}, + {eErrorInvalidTmplData, "Invalid desingated fingerprint data"}, + {eErrorDuplicationID, "The fingerprint has been registered"}, + {eErrorBadQuality, "Poor quality fingerprint image"}, + {eErrorMergeFail, "Fingerprint synthesis failed"}, + {eErrorNotAuthorized, "Communication password not authorized"}, + {eErrorMemory, "External Flash burning error"}, + {eErrorInvalidTmplNo, "Invalid designated ID"}, + {eErrorInvalidParam, "Incorrect parameter"}, + {eErrorTimeOut, "Acquisition timeout"}, + {eErrorGenCount, "Invalid number of fingerprint synthesis"}, + {eErrorInvalidBufferID, "Incorrect Buffer ID value"}, + {eErrorFPNotDetected, "No fingerprint input into fingerprint reader"}, + {eErrorFPCancel, "Command cancelled"}, + {eErrorRecvLength, "Wrong data length"}, + {eErrorRecvCks, "Wrong data check code"}, + {eErrorGatherOut, "Exceed upper limit of acquisition times"}, + {eErrorRecvTimeout,"Data reading timeout"} +}; + +String DFRobot_ID809::getErrorDescription() +{ + for(int i=0;i<sizeof(errorDescriptionsTable)/sizeof(errorDescriptionsTable[0]);i++){ + if(_error == errorDescriptionsTable[i].error){ + return errorDescriptionsTable[i].description; + } + } + return ""; +} + + diff --git a/readTemplate/lib/DFRobot_ID809/DFRobot_ID809.h b/readTemplate/lib/DFRobot_ID809/DFRobot_ID809.h new file mode 100644 index 0000000..83ca50d --- /dev/null +++ b/readTemplate/lib/DFRobot_ID809/DFRobot_ID809.h @@ -0,0 +1,504 @@ +/*! + * @file DFRobot_ID809.h + * @brief Define basic structure of DFRobot_ID809 class + * @n This is an library for capacitive fingerprint module + * @n Main functions: fingerprint image capturing, fingerprint comparison, fingerprint deletion + * @copyright Copyright (c) 2010 DFRobot Co.Ltd (http://www.dfrobot.com) + * @licence The MIT License (MIT) + * @author [Eddard](eddard.liu@dfrobot.com) + * @version V1.0 + * @date 2020-03-19 + * @get from https://www.dfrobot.com + * @url https://github.com/cdjq/DFRobot_ID809 + */ + +#ifndef _DFRobot_ID809_H +#define _DFRobot_ID809_H + +#if ARDUINO >= 100 +#include "Arduino.h" +#else +#include "WProgram.h" +#endif +#include <Wire.h> + +#include <stdint.h> + +//Open this macro to see the detailed running process of the program + +//#define ENABLE_DBG +#ifdef ENABLE_DBG +#define LDBG(...) if(dbg) {dbg->print("["); dbg->print(__FUNCTION__); dbg->print("(): "); dbg->print(__LINE__); dbg->print(" ] "); dbg->println(__VA_ARGS__);} +#else +#define LDBG(...) +#endif + +extern Stream *dbg; + + /* + Frame struct of command packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t CMD; + uint16_t LEN; + uint8_t payload[0]; +}__attribute__ ((packed)) sCmdPacketHeader_t, *pCmdPacketHeader_t; + + /* + Frame struct of response packet + */ +typedef struct{ + uint16_t PREFIX; + uint8_t SID; + uint8_t DID; + uint16_t RCM; + uint16_t LEN; + uint16_t RET; + uint8_t payload[0]; +}__attribute__ ((packed)) sRcmPacketHeader_t, *pRcmPacketHeader_t; + + + + +class DFRobot_ID809{ +public: + +//#define FINGERPRINT_CAPACITY 80 //Fingerprint module capacity +#define MODULE_SN_SIZE 16 //Module SN length + + +#define DELALL 0xFF //Delete all fingerprints + +#define CMD_PREFIX_CODE 0xAA55 //Command packet prefix code +#define RCM_PREFIX_CODE 0x55AA //Response packet prefix code +#define CMD_DATA_PREFIX_CODE 0xA55A //Command data packet prefix code +#define RCM_DATA_PREFIX_CODE 0x5AA5 //Response data packet prefix code + +#define CMD_TYPE 0xF0 //Command packet type +#define RCM_TYPE 0xF0 //Response packet type +#define DATA_TYPE 0x0F //Data packet type + +#define CMD_TEST_CONNECTION 0X0001 //Test connection +#define CMD_SET_PARAM 0X0002 //Set parameter +#define CMD_GET_PARAM 0X0003 //Read parameter +#define CMD_DEVICE_INFO 0X0004 //Read device information +#define CMD_SET_MODULE_SN 0X0008 //Set module serial number +#define CMD_GET_MODULE_SN 0X0009 //Read module serial number +#define CMD_ENTER_STANDBY_STATE 0X000C //Enter sleep mode +#define CMD_GET_IMAGE 0X0020 //Capture fingerprint image +#define CMD_FINGER_DETECT 0X0021 //Detect fingerprint + #define CMD_UP_IMAGE_CODE 0X0022 //Upload fingerprint image to host + #define CMD_DOWN_IMAGE 0X0023 //Download fingerprint image to module +#define CMD_SLED_CTRL 0X0024 //Control collector backlight +#define CMD_STORE_CHAR 0X0040 //Save fingerprint template data into fingerprint library +#define CMD_LOAD_CHAR 0X0041 //Read fingerprint in module and save it in RAMBUFFER temporarily + #define CMD_UP_CHAR 0X0042 //Upload the fingerprint template saved in RAMBUFFER to host + #define CMD_DOWN_CHAR 0X0043 //Download fingerprint template to module designated RAMBUFFER +#define CMD_DEL_CHAR 0X0044 //Delete fingerprint in specific ID range +#define CMD_GET_EMPTY_ID 0X0045 //Get the first registerable ID in specific ID range +#define CMD_GET_STATUS 0X0046 //Check if the designated ID has been registered +#define CMD_GET_BROKEN_ID 0X0047 //Check whether there is damaged data in fingerprint library of specific range +#define CMD_GET_ENROLL_COUNT 0X0048 //Get the number of registered fingerprints in specific ID range +#define CMD_GET_ENROLLED_ID_LIST 0X0049 //Get registered ID list +#define CMD_GENERATE 0X0060 //Generate template from the fingerprint images saved in IMAGEBUFFER temporarily +#define CMD_MERGE 0X0061 //Synthesize fingerprint template data +#define CMD_MATCH 0X0062 //Compare templates in 2 designated RAMBUFFER +#define CMD_SEARCH 0X0063 //1:N Recognition in specific ID range +#define CMD_VERIFY 0X0064 //Compare specific RAMBUFFER template with specific ID template in fingerprint library + +#define ERR_SUCCESS 0x00 //Command processed successfully +#define ERR_ID809 0xFF //error + + +public: + + typedef enum{ + eBreathing = 1, //Breathing + eFastBlink, //Quick blink + eKeepsOn, //On + eNormalClose, //Off + eFadeIn, //Fade in + eFadeOut, //Fade out + eSlowBlink //Slow blink + }eLEDMode_t; + + typedef enum{ + eLEDGreen = 1, //green + eLEDRed, //red + eLEDYellow, //yellow + eLEDBlue, //blue + eLEDCyan, //cyan + eLEDMagenta, //magenta + eLEDWhite //white + }eLEDColor_t; + + typedef enum{ + e9600bps = 1, + e19200bps, + e38400bps, + e57600bps, + e115200bps + }eDeviceBaudrate_t; + + typedef enum{ + eErrorSuccess = 0x00, //Command processed successfully + eErrorFail = 0x01, //Command processing failed + eErrorVerify = 0x10, //1:1 Templates comparison in specific ID failed + eErrorIdentify = 0x11, //1:N comparison has been made, no same templates here + eErrorTmplEmpty = 0x12, //No registered template in the designated ID + eErrorTmplNotEmpty = 0x13, //Template already exists in the specified ID + eErrorAllTmplEmpty = 0x14, //No registered Template + eErrorEmptyIDNoexist = 0x15, //No registerable Template ID + eErrorBrokenIDNoexist = 0x16, //No damaged Template + eErrorInvalidTmplData = 0x17, //The designated Template Data is invalid + eErrorDuplicationID = 0x18, //The fingerprint has been registered + eErrorBadQuality = 0x19, //Poor quality fingerprint image + eErrorMergeFail = 0x1A, //Template synthesis failed + eErrorNotAuthorized = 0x1B, //Communication password not authorized + eErrorMemory = 0x1C, //Error in exernal Flash burning + eErrorInvalidTmplNo = 0x1D, //The designated template ID is invalid + eErrorInvalidParam = 0x22, //Incorrect parameter has been used + eErrorTimeOut = 0x23, //Acquisition timeout + eErrorGenCount = 0x25, //Invalid number of fingerprint synthesis + eErrorInvalidBufferID = 0x26, //Wrong Buffer ID value + eErrorFPNotDetected = 0x28, //No fingerprint input into fingerprint reader + eErrorFPCancel = 0x41, //Command cancelled + eErrorRecvLength = 0x42, //Wrong length of recieved data + eErrorRecvCks = 0x43, //Wrong check code + eErrorGatherOut = 0x45, //Exceed upper limit of acquisition times + eErrorRecvTimeout = 0x46 //Communication timeout + }eError_t; + + typedef struct{ + /**< Gesture enumeration variable X */ + eError_t error; + /**< Description about the gesture enumeration variable X */ + const char * description; + }sErrorDescription_t; + +public: + DFRobot_ID809(); + ~DFRobot_ID809(); + + /** + * @brief Init communication port + * @param Software serial or hardware serial + * @return true or false + */ + bool begin(Stream &s_); + + /** + * @brief Test whether the module connection is ok + * @return true or false + */ + bool isConnected(); + + /** + * @brief Set module ID + * @param ID:1-255 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDeviceID(uint8_t deviceID); + + /** + * @brief Set module security level + * @param security level:1-5 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSecurityLevel(uint8_t securityLevel); + + /** + * @brief Set module fingerprint replication check (Check whether the fingperint has been registered when saving it) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setDuplicationCheck(uint8_t duplicationCheck); + + /** + * @brief Set module baud rate + * @param Baudrate:in typedef enum eDeviceBaudrate_t + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setBaudrate(eDeviceBaudrate_t baudrate); + + /** + * @brief Set module self-learning function (Update fingeprint when fingerprint comparison succeeds) + * @param 1(ON) or 0(OFF) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setSelfLearn(uint8_t selfLearn); + + /** + * @brief Read module ID + * @return IDå·:1-255 or ERR_ID809 + */ + uint8_t getDeviceID(); + + /** + * @brief Read module security level + * @return Security level:1-5 or ERR_ID809 + */ + uint8_t getSecurityLevel(); + + /** + * @brief Read module fingerprint replication check status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getDuplicationCheck(); + + /** + * @brief Read module baud rate + * @return Baudrate:in typedef enum eDEVICE_BAUDRATE_t or ERR_ID809 + */ + uint8_t getBaudrate(); + + /** + * @brief Read module self-learning function status + * @return Status:1(ON), 0(OFF) or ERR_ID809 + */ + uint8_t getSelfLearn(); + uint8_t getTemplate(uint16_t id,uint8_t * temp); + uint8_t downLoadTemplate(uint16_t id,uint8_t * temp); + uint8_t getFingerImage(uint8_t *image); + uint8_t downLoadImage(uint16_t id,uint8_t * temp); + uint8_t receiveImageData(uint8_t *image); + uint8_t getQuarterFingerImage(uint8_t *image); + uint8_t contrastTemplate(uint8_t *temp); + /** + * @brief Read device number + * @return Device number + */ + String getDeviceInfo(); + + /** + * @brief Set serial number + * @param String pointer + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setModuleSN(const char* SN); + /** + * @brief Read serial number + * @return Serial number + */ + String getModuleSN(); + + /** + * @brief Set LED + * @param mode:in typedef enum eLEDMode_t + * @param color:in typedef enum eLEDColor_t + * @param blink Count: 00 represents blinking all the time + * @This parameter will only be valid in mode eBreathing, eFastBlink, eSlowBlink + * @return 0(succeed) or ERR_ID809 + */ + uint8_t ctrlLED(eLEDMode_t mode,eLEDColor_t color,uint8_t blinkCount); + + /** + * @brief Detect if there is finger touched + * @return 1(Touched) or 0(No touch) + */ + uint8_t detectFinger(); + + /** + * @brief Get the first registerable ID + * @return Registerable ID or ERR_ID809 + */ + uint8_t getEmptyID(); + + /** + * @brief Check if the ID has been registered + * @return 0(Registered), 1(Unregistered) or ERR_ID809 + */ + uint8_t getStatusID(uint8_t ID); + + /** + * @brief Get the number of registered users + * @return Number of registered users or ERR_ID809 + */ + uint8_t getEnrollCount(); + + /** + * @brief Get registered user list + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getEnrolledIDList(uint8_t* list); + + /** + * @brief Fingerprint acquisition + * @return 0(succeed) or ERR_ID809 + */ + uint8_t collectionFingerprint(uint16_t timeout,int ramNumber = -1); + + /** + * @brief Save fingerprint + * @param Fingerprint ID + * @return 0(succeed) or ERR_ID809 + */ + uint8_t storeFingerprint(uint8_t ID); + + /** + * @brief Delete fingerprint + * @param Delete ID or DELALL(delete all) + * @return 0(succeed) or ERR_ID809 + */ + uint8_t delFingerprint(uint8_t ID); + + /** + * @brief Match the fingerprint with all fingeprints + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t search(); + + /** + * @brief Match the fingerprint with specific fingerprint + * @return Successfully matched fingerprint ID, 0(Matching failed) or ERR_ID809 + */ + uint8_t verify(uint8_t ID); + + /** + * @brief Compare templates in two specific RamBuffers + * @param RamBuffer number + * @param RamBuffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t match(uint8_t RamBufferID0, uint8_t RamBufferID1); + + /** + * @brief Get the number of damaged fingerprints + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenQuantity(); + + /** + * @brief Get the first damaged fingerprint ID + * @return Damaged fingerprint ID or ERR_ID809 + */ + uint8_t getBrokenID(); + + /** + * @brief Take out fingerprint template, temporarily save into RamBuffer + * @param Fingerprint ID + * @param RamBuffer number 0-2 + * @return 0(succeed) or ERR_ID809 + */ + uint8_t loadFingerprint(uint8_t ID, uint8_t RamBufferID); + + /** + * @brief Enter Standby mode + * @return 0(succeed) or ERR_ID809 + */ + uint8_t enterStandbyState(); + + /** + * @brief Get error information + * @return Text description of error information + */ + String getErrorDescription(); + + bool setDbgSerial(Stream &s_){dbg = &s_; return true;} + uint16_t FINGERPRINT_CAPACITY = 80; +protected: + /** + * @brief Set parameter + * @param Data type+ data + * @return 0(succeed) or ERR_ID809 + */ + uint8_t setParam(uint8_t* data); + + /** + * @brief Read parameter + * @param Data type + * @return data or ERR_ID809 + */ + uint8_t getParam(uint8_t* data); + + /** + * @brief Capture fingerprint image + * @return 0(succeed) or ERR_ID809 + */ + uint8_t getImage(); + + /** + * @brief Take image as template + * @param Ram Buffer number + * @return 0(succeed) or ERR_ID809 + */ + uint8_t generate(uint8_t RamBufferID); + + /** + * @brief Fingerprint synthesis + * @return 0(succeed) or ERR_ID809 + */ + uint8_t merge(); + + /** + * @brief Packing data frame + * @param Data type:CMD_TYPE or DATA_TYPE + * @param Command + * @param Data + * @param Length + * @return Data frame + */ + pCmdPacketHeader_t pack(uint8_t type, uint16_t cmd, const char *payload, uint16_t len); + + /** + * @brief Send data + * @param Data frame + */ + void sendPacket(pCmdPacketHeader_t header); + + /** + * @brief Read byte + * @param Pointer for saving data + * @param Length of data to be received + * @return Actual received data length + */ + size_t readN(void* buf_, size_t len); + + /** + * @brief Read frame header + * @param Frame header struct of response packet + * @return Response packet type:RCM_TYPE,DATA_TYPE or 1(reading timeout) + */ + uint16_t readPrefix( pRcmPacketHeader_t header ); + + /** + * @brief Read data + * @param Pointer for saving data + * @return 0(success) or ERR_ID809 + */ + uint8_t responsePayload(void* buf); + + /** + * @brief Get command packet CKS + * @param Command packet frame + * @return CKS + */ + uint16_t getCmdCKS(pCmdPacketHeader_t packet); + + /** + * @brief Get response packet CKS + * @param Response packet frame + * @return CKS + */ + uint16_t getRcmCKS(pRcmPacketHeader_t packet); + uint8_t store(uint8_t ID); + +private: + Stream *s; + uint8_t buf[20]; //For saving response packet data + pCmdPacketHeader_t sendHeader; + pRcmPacketHeader_t recHeader; + + static const sErrorDescription_t /*PROGMEM*/ errorDescriptionsTable[26]; //Error information list + + uint8_t _number = 0; //Fingerprint acquisistion times + uint8_t _state = 0; //Collect fingerprint state + eError_t _error; //Error code + uint16_t _PacketSize = 0; //Data packet length to be sent +}; + +#endif + diff --git a/readTemplate/platformio.ini b/readTemplate/platformio.ini new file mode 100644 index 0000000..7a3aa31 --- /dev/null +++ b/readTemplate/platformio.ini @@ -0,0 +1,13 @@ +[env:Teensy_FP] + +platform = teensy +framework = arduino +board = teensy31 + +build_flags = + -I lib/DFRobot_ID809 + +lib_deps = + intrbiz/crypto + + diff --git a/readTemplate/src/src.cpp b/readTemplate/src/src.cpp new file mode 100644 index 0000000..d5adb90 --- /dev/null +++ b/readTemplate/src/src.cpp @@ -0,0 +1,192 @@ +#include <Arduino.h> +#include <Crypto.h> +#include <DFRobot_ID809.h> +#include <EEPROM.h> + +// use serial3 as interface with fingerprint +// sensor. + +#define FPSerial Serial3 + +// define buillt_in led + +#define BUILTIN_LED 13 + +// Collect the fingerprint 3 times + +#define COLLECT_NUMBER 3 + +/*------Global variables--------------*/ + +DFRobot_ID809 fingerprint; +uint8_t ID, i, ret; +byte hash[SHA256_SIZE]; +uint8_t temp[1008]; +// EEPROM OFFSET to store + +const uint16_t EEPROM_FP_HASH = 1696; + +/*---------Compute hash----------------*/ + +void compute_hash() { + + SHA256 hasher; + hasher.doUpdate(temp, sizeof(temp)); + hasher.doFinal(hash); + + Serial.println("-----------------------"); + Serial.println(); + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + if (hash[i] < 0x10) { + + Serial.print('0'); + } + + Serial.print(hash[i], HEX); + Serial.print(" "); + } + Serial.println(); + Serial.println("-----------------------"); +} + +/*-----Blink on board led -------------- */ + +void blink_led() { + digitalWrite(BUILTIN_LED, HIGH); + delay(500); + digitalWrite(BUILTIN_LED, LOW); + delay(500); +} + +/*-------- Save FingerPrint hash in EEPROM ------*/ + +void compareHash() { + uint16_t memoryAddress; + byte stored_hash[SHA256_SIZE]; + + memoryAddress = EEPROM_FP_HASH + ((ID - 1) * 32); + + Serial.println("---------------------------"); + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + stored_hash[i] = EEPROM.read(memoryAddress); + Serial.print(stored_hash[i], HEX); + Serial.print(" "); + memoryAddress++; + } + Serial.println("--------------------------"); + + for (uint8_t i = 0; i < SHA256_SIZE; i++) { + + if (stored_hash[i] != hash[i]) { + Serial.println("Hash not matched"); + return; + } + } + Serial.println("Hash mathed"); +} + +/*---------Arduino setup function------*/ + +void setup() { + // config led_pin as output + pinMode(BUILTIN_LED, OUTPUT); + // use serial port to print the baud rate + Serial.begin(9600); + // config fingerprint sensor + FPSerial.begin(115200); + fingerprint.begin(FPSerial); + + while (fingerprint.isConnected() == false) { + Serial.println("Communication with the device failed"); + delay(1000); + } +} + +/*---------Register Finger print ------------*/ + +void matchFingerprint() { + + /*Set fingerprint LED ring mode, color, and number of blinks + Can be set as follows: + Parameter 1:<LEDMode> + eBreathing eFastBlink eKeepsOn eNormalClose + eFadeIn eFadeOut eSlowBlink + Parameter 2:<LEDColor> + eLEDGreen eLEDRed eLEDYellow eLEDBlue + eLEDCyan eLEDMagenta eLEDWhite + Parameter 3:<Number of blinks> 0 represents blinking all the time + This parameter will only be valid in mode eBreathing, eFastBlink, + eSlowBlink + */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eBreathing, + /*LEDColor = */ fingerprint.eLEDBlue, + /*blinkCount = */ 0); + + Serial.println("Plase press down your finger"); + + if ((fingerprint.collectionFingerprint(/*timeout = */ 0)) != ERR_ID809) { + /*Set fingerprint LED ring to quick blink in yellow 3 times */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eFastBlink, + /*LEDColor = */ fingerprint.eLEDYellow, + /*blinkCount = */ 3); + Serial.println("capturing succeeds"); + Serial.println("Please release your finger"); + + while (fingerprint.detectFinger()) + ; + + /*Compare the captured fingerprint with all the fingerprints + * inthe fingerprint library return fingerprint ID if succeed, + * return 0 when failed + * */ + ret = fingerprint.search(); + + if (ret != 0) { + + /*Set fingerprint LED ring to always ON in green */ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eKeepsOn, + /*LEDColor = */ fingerprint.eLEDGreen, + /*blinkCount = */ 0); + Serial.print("Matching succeeds,ID="); + ID = ret; + Serial.println(ret); + fingerprint.getTemplate(ID, temp); + // delay(100); + // compute_hash(); + // compareHash(); + + // print template data + Serial.println("---------------------------------"); + Serial.println(); + for (uint16_t i = 0; i < 1008; i++) { + + Serial.print(temp[i], HEX); + Serial.print(" "); + } + Serial.println(); + Serial.println("-------------------------------"); + + compute_hash(); + } else { + /*Set fingerprint LED ring to always ON in red*/ + fingerprint.ctrlLED(/*LEDMode = */ fingerprint.eKeepsOn, + /*LEDColor = */ fingerprint.eLEDRed, + /*blinkCount = */ 0); + Serial.println("Matching fails"); + } + } else { + Serial.println("Capturing failes"); + /*Get error code information*/ + // desc = fingerprint.getErrorDescription(); + // Serial.println(desc); + } +} + +/*-----------Arduino loop function--------- */ + +void loop() { + blink_led(); + matchFingerprint(); +} -- GitLab