├── image ├── temp ├── r502.png ├── esp8266-3.png └── fingerprints.png ├── home_assistant ├── input_text.yaml ├── input_number.yaml ├── lovelace_standard ├── script.yaml ├── sensor.yaml ├── fingerprints_package.yaml └── lovelace.yaml ├── libraries └── Adafruit_Fingerprint_Sensor_Library │ ├── documentation │ ├── fingerprint_en.pdf │ ├── ZFM-20_Fingerprint_Module.pdf │ └── readme.txt │ ├── examples │ ├── blank │ │ └── blank.ino │ ├── Leo_passthru │ │ └── Leo_passthru.ino │ ├── emptyDatabase │ │ └── emptyDatabase.ino │ ├── changepassword │ │ └── changepassword.ino │ ├── delete │ │ └── delete.ino │ ├── ledcontrol │ │ └── ledcontrol.ino │ ├── show_fingerprint_templates │ │ └── show_fingerprint_templates.ino │ ├── fingerprint │ │ └── fingerprint.ino │ └── enroll │ │ └── enroll.ino │ ├── library.properties │ ├── license.txt │ ├── README.md │ ├── Adafruit_Fingerprint.h │ └── Adafruit_Fingerprint.cpp ├── README.md └── sketch └── fingerprints-mqtt └── fingerprints-mqtt.ino /image/temp: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /home_assistant/input_text.yaml: -------------------------------------------------------------------------------- 1 | input_text: 2 | id_name: 3 | name: name id 4 | initial: user name 5 | -------------------------------------------------------------------------------- /image/r502.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/HEAD/image/r502.png -------------------------------------------------------------------------------- /image/esp8266-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/HEAD/image/esp8266-3.png -------------------------------------------------------------------------------- /image/fingerprints.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/HEAD/image/fingerprints.png -------------------------------------------------------------------------------- /home_assistant/input_number.yaml: -------------------------------------------------------------------------------- 1 | input_number: 2 | fingerprint_learning_id: 3 | name: numero impronta 4 | initial: 0 5 | min: 0 6 | max: 127 7 | step: 1 8 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/documentation/fingerprint_en.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/HEAD/libraries/Adafruit_Fingerprint_Sensor_Library/documentation/fingerprint_en.pdf -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/documentation/ZFM-20_Fingerprint_Module.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/HEAD/libraries/Adafruit_Fingerprint_Sensor_Library/documentation/ZFM-20_Fingerprint_Module.pdf -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/blank/blank.ino: -------------------------------------------------------------------------------- 1 | // this sketch will allow you to bypass the Atmega chip 2 | // and connect the fingerprint sensor directly to the USB/Serial 3 | // chip converter. 4 | 5 | // Red connects to +5V 6 | // Black connects to Ground 7 | // White goes to Digital 0 8 | // Green goes to Digital 1 9 | 10 | void setup() {} 11 | void loop() {} 12 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/documentation/readme.txt: -------------------------------------------------------------------------------- 1 | The file ZFM-20_Fingerprint_Module.pdf is an automatic translation of the original Chinese datasheet, as performed by Google Translate. We provide it as a courtesy only, and have not reviewed the translation for accuracy or completeness. 2 | 3 | Original datasheet available here: 4 | http://www.adafruit.com/datasheets/DY001fingerprint.pdf 5 | 6 | ------- 7 | R.D. Lesniak, Oct. 31, 2012 -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit Fingerprint Sensor Library 2 | version=2.0.4 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Arduino library for interfacing to the fingerprint sensor in the Adafruit shop 6 | paragraph=Arduino library for interfacing to the fingerprint sensor in the Adafruit shop 7 | category=Sensors 8 | url=https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/Leo_passthru/Leo_passthru.ino: -------------------------------------------------------------------------------- 1 | //Leo_passthru 2 | // Allows Leonardo to pass serial data between fingerprint reader and Windows. 3 | // 4 | // Red connects to +5V 5 | // Black connects to Ground 6 | // Green goes to Digital 0 7 | // White goes to Digital 1 8 | 9 | void setup() { 10 | // put your setup code here, to run once: 11 | Serial1.begin(57600); 12 | Serial.begin(57600); 13 | } 14 | 15 | void loop() { 16 | 17 | while (Serial.available()) 18 | Serial1.write(Serial.read()); 19 | while (Serial1.available()) 20 | Serial.write(Serial1.read()); 21 | } -------------------------------------------------------------------------------- /home_assistant/lovelace_standard: -------------------------------------------------------------------------------- 1 | - title: '' 2 | #background: 'radial-gradient(#286a84, #212527)' 3 | # background: 'linear-gradient(to right, #ffffff 75%, #f6f5fa 75% 100%)' 4 | # s 5 | background: var(--simple-background) 6 | path: fingerprint2 7 | icon: 'mdi:fingerprint' 8 | badges: [] 9 | cards: 10 | - type: markdown 11 | content: > 12 | ## Fingerprits 13 | - type: markdown 14 | content: > 15 | **Recorded Fingerprits** 16 | --- 17 | 18 | *id:* __{{states('input_number.fingerprint_learning_id') | round}}__ __{{state_attr('saver.saver', 'variables')[states('input_number.fingerprint_learning_id') | round | string ] }}__ 19 | - type: entities 20 | #title: Fingerprints 21 | show_header_toggle: false 22 | entities: 23 | - entity: sensor.fingerprint_id 24 | - entity: sensor.fingerprint_person 25 | - entity: sensor.fingerprint_mode 26 | - type: divider 27 | - entity: input_number.fingerprint_learning_id 28 | - entity: input_text.id_name 29 | - entity: script.fingerprint_learning_mode 30 | - entity: script.fingerprint_delete_print 31 | - entity: script.fingerprint_rename 32 | -------------------------------------------------------------------------------- /home_assistant/script.yaml: -------------------------------------------------------------------------------- 1 | fingerprint_learning_mode: 2 | alias: Fingerprint learning mode 3 | sequence: 4 | - service: saver.set_variable 5 | data: 6 | name: "{{states('input_number.fingerprint_learning_id') | int}}" 7 | value: "{{states('input_text.id_name')}}" 8 | - data: 9 | payload_template: '{{states(''input_number.fingerprint_learning_id'') | int}}' 10 | topic: /fingerprint/mode/learning 11 | service: mqtt.publish 12 | - service: input_text.set_value 13 | data: 14 | entity_id: input_text.id_name 15 | value: "user name" 16 | - service: browser_mod.close_popup 17 | fingerprint_delete_print: 18 | alias: Fingerprint Delete Print 19 | sequence: 20 | - data: 21 | payload_template: '{{states(''input_number.fingerprint_learning_id'') | int}}' 22 | topic: /fingerprint/mode/delete 23 | service: mqtt.publish 24 | - service: saver.delete_variable 25 | data: 26 | name: "{{states('input_number.fingerprint_learning_id') | int}}" 27 | - service: browser_mod.close_popup 28 | fingerprint_rename: 29 | alias: Fingerprint learning mode 30 | sequence: 31 | - service: saver.set_variable 32 | data: 33 | name: "{{states('input_number.fingerprint_learning_id') | int}}" 34 | value: "{{states('input_text.id_name')}}" 35 | - service: input_text.set_value 36 | data: 37 | entity_id: input_text.id_name 38 | value: "user name" 39 | - service: browser_mod.close_popup -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/license.txt: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2012, Adafruit Industries 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 1. Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 3. Neither the name of the copyright holders nor the 14 | names of its contributors may be used to endorse or promote products 15 | derived from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 21 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 26 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/README.md: -------------------------------------------------------------------------------- 1 | # Adafruit-Fingerprint-Sensor-Library [![Build Status](https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit-Fingerprint-Sensor-Library/html/index.html) 2 | 3 | 4 | 5 | 6 | Secure your project with biometrics - this all-in-one optical fingerprint sensor will make adding fingerprint detection and verification super simple. These modules are typically used in safes - there's a high powered DSP chip that does the image rendering, calculation, feature-finding and searching. Connect to any microcontroller or system with TTL serial, and send packets of data to take photos, detect prints, hash and search. You can also enroll new fingers directly - up to 162 finger prints can be stored in the onboard FLASH memory. There's a red LED in the lens that lights up during a photo so you know its working. 7 | 8 | The Rugged Panel Mount Fingerprint Sensor with Bi-Color LED Ring even has an LED ring built around the detection pad, which can be set to red, blue or purple (as well as some fading/blinking effects) for a great user experience. 9 | 10 | 11 | Designed specifically to work with the Adafruit Fingerprint sensors 12 | * http://www.adafruit.com/products/751 13 | * https://www.adafruit.com/product/4651 14 | 15 | Pick one up today in the adafruit shop! 16 | 17 | These sensors use TTL Serial to communicate, 2 pins are required to interface 18 | 19 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 20 | 21 | Written by Limor Fried/Ladyada for Adafruit Industries. 22 | BSD license, check license.txt for more information 23 | All text above must be included in any redistribution 24 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/emptyDatabase/emptyDatabase.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is an example sketch for our optical Fingerprint sensor 3 | Designed specifically to work with the Adafruit Fingerprint sensor 4 | ----> http://www.adafruit.com/products/751 5 | These displays use TTL Serial to communicate, 2 pins are required to 6 | interface 7 | Adafruit invests time and resources providing this open source code, 8 | please support Adafruit and open-source hardware by purchasing 9 | products from Adafruit! 10 | Written by Limor Fried/Ladyada for Adafruit Industries. 11 | BSD license, all text above must be included in any redistribution 12 | ****************************************************/ 13 | 14 | #include 15 | 16 | 17 | #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) 18 | // For UNO and others without hardware serial, we must use software serial... 19 | // pin #2 is IN from sensor (GREEN wire) 20 | // pin #3 is OUT from arduino (WHITE wire) 21 | // Set up the serial port to use softwareserial.. 22 | SoftwareSerial mySerial(2, 3); 23 | 24 | #else 25 | // On Leonardo/M0/etc, others with hardware serial, use hardware serial! 26 | // #0 is green wire, #1 is white 27 | #define mySerial Serial1 28 | 29 | #endif 30 | 31 | 32 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 33 | 34 | void setup() 35 | { 36 | Serial.begin(9600); 37 | while (!Serial); // For Yun/Leo/Micro/Zero/... 38 | delay(100); 39 | 40 | Serial.println("\n\nDeleting all fingerprint templates!"); 41 | Serial.println("Press 'Y' key to continue"); 42 | 43 | while (1) { 44 | if (Serial.available() && (Serial.read() == 'Y')) { 45 | break; 46 | } 47 | } 48 | 49 | // set the data rate for the sensor serial port 50 | finger.begin(57600); 51 | 52 | if (finger.verifyPassword()) { 53 | Serial.println("Found fingerprint sensor!"); 54 | } else { 55 | Serial.println("Did not find fingerprint sensor :("); 56 | while (1); 57 | } 58 | 59 | finger.emptyDatabase(); 60 | 61 | Serial.println("Now database is empty :)"); 62 | } 63 | 64 | void loop() { 65 | } 66 | 67 | -------------------------------------------------------------------------------- /home_assistant/sensor.yaml: -------------------------------------------------------------------------------- 1 | - platform: mqtt 2 | name: "Fingerprint" 3 | state_topic: "/fingerprint/mode/status" 4 | value_template: "{{value_json.state}}" 5 | json_attributes_topic: "/fingerprint/mode/status" 6 | json_attributes_template: "{{value_json | tojson}}" 7 | - platform: template 8 | sensors: 9 | fingerprint_mode: 10 | friendly_name: "Fingerprint Sensor Mode" 11 | value_template: >- 12 | {{state_attr('sensor.fingerprint', 'mode')}} 13 | icon_template: >- 14 | {% if is_state('sensor.fingerprint_mode', 'reading') %} 15 | mdi:focus-field 16 | {% elif is_state('sensor.fingerprint_mode', 'learning') %} 17 | mdi:draw 18 | {% elif is_state('sensor.fingerprint_mode', 'deleting') %} 19 | mdi:trash-can-outline 20 | {% endif %} 21 | fingerprint_state: 22 | friendly_name: "Fingerprint State" 23 | value_template: >- 24 | {{states('sensor.fingerprint')}} 25 | icon_template: >- 26 | {% if is_state('sensor.fingerprint', 'Waiting') %} 27 | mdi:fingerprint 28 | {% elif is_state('sensor.fingerprint', 'Matched') %} 29 | mdi:shield-check 30 | {% elif is_state('sensor.fingerprint', 'Not matched') %} 31 | mdi:fingerprint-off 32 | {% endif %} 33 | fingerprint_id: 34 | friendly_name: "Fingerprint ID" 35 | value_template: >- 36 | {{state_attr('sensor.fingerprint', 'id')}} 37 | fingerprint_person: 38 | friendly_name: "Fingerprint Person" 39 | value_template: >- 40 | {% if states.sensor.fingerprint_id.state | int > 0.1 %} 41 | {{state_attr('saver.saver', 'variables')[states('sensor.fingerprint_id')] }} 42 | {% elif is_state('sensor.fingerprint', 'Waiting') %} 43 | 44 | {% elif is_state('sensor.fingerprint', 'Not matched') %} 45 | Not matched 46 | {% endif %} 47 | icon_template: >- 48 | {% if is_state('sensor.fingerprint', 'Waiting') %} 49 | mdi:human-male 50 | {% elif is_state('sensor.fingerprint', 'Matched') %} 51 | mdi:human-greeting 52 | {% elif is_state('sensor.fingerprint', 'Not matched') %} 53 | mdi:police-badge 54 | {% elif is_state('sensor.fingerprint', 'Deleted') %} 55 | mdi:trash-can-outline 56 | {% endif %} -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/changepassword/changepassword.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is an example sketch for our optical Fingerprint sensor 3 | Designed specifically to work with the Adafruit Fingerprint sensor 4 | ----> http://www.adafruit.com/products/751 5 | These displays use TTL Serial to communicate, 2 pins are required to 6 | interface 7 | Adafruit invests time and resources providing this open source code, 8 | please support Adafruit and open-source hardware by purchasing 9 | products from Adafruit! 10 | Written by Limor Fried/Ladyada for Adafruit Industries. 11 | BSD license, all text above must be included in any redistribution 12 | ****************************************************/ 13 | 14 | #include 15 | 16 | 17 | #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) 18 | // For UNO and others without hardware serial, we must use software serial... 19 | // pin #2 is IN from sensor (GREEN wire) 20 | // pin #3 is OUT from arduino (WHITE wire) 21 | // Set up the serial port to use softwareserial.. 22 | SoftwareSerial mySerial(2, 3); 23 | 24 | #else 25 | // On Leonardo/M0/etc, others with hardware serial, use hardware serial! 26 | // #0 is green wire, #1 is white 27 | #define mySerial Serial1 28 | 29 | #endif 30 | 31 | // Using sensor without password 32 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 33 | 34 | // Using sensor with password 35 | //Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial, 1337); 36 | 37 | void setup() 38 | { 39 | while (!Serial); // For Yun/Leo/Micro/Zero/... 40 | 41 | Serial.begin(9600); 42 | Serial.println("Adafruit fingerprint sensor, change password example"); 43 | 44 | // set the data rate for the sensor serial port 45 | finger.begin(19200); 46 | 47 | if (finger.verifyPassword()) { 48 | Serial.println("Found fingerprint sensor!"); 49 | } else { 50 | Serial.println("Did not find fingerprint sensor :("); 51 | while (1); 52 | } 53 | 54 | Serial.print("Set password... "); 55 | uint8_t p = finger.setPassword(1337); 56 | if (p == FINGERPRINT_OK) { 57 | Serial.println("OK"); // Password is set 58 | } else { 59 | Serial.println("ERROR"); // Failed to set password 60 | } 61 | } 62 | 63 | void loop() 64 | { 65 | 66 | } 67 | 68 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/delete/delete.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is an example sketch for our optical Fingerprint sensor 3 | 4 | Designed specifically to work with the Adafruit Fingerprint sensor 5 | ----> http://www.adafruit.com/products/751 6 | 7 | These displays use TTL Serial to communicate, 2 pins are required to 8 | interface 9 | Adafruit invests time and resources providing this open source code, 10 | please support Adafruit and open-source hardware by purchasing 11 | products from Adafruit! 12 | 13 | Written by Limor Fried/Ladyada for Adafruit Industries. 14 | BSD license, all text above must be included in any redistribution 15 | ****************************************************/ 16 | 17 | #include 18 | 19 | 20 | #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) 21 | // For UNO and others without hardware serial, we must use software serial... 22 | // pin #2 is IN from sensor (GREEN wire) 23 | // pin #3 is OUT from arduino (WHITE wire) 24 | // Set up the serial port to use softwareserial.. 25 | SoftwareSerial mySerial(2, 3); 26 | 27 | #else 28 | // On Leonardo/M0/etc, others with hardware serial, use hardware serial! 29 | // #0 is green wire, #1 is white 30 | #define mySerial Serial1 31 | 32 | #endif 33 | 34 | 35 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 36 | 37 | void setup() 38 | { 39 | Serial.begin(9600); 40 | while (!Serial); // For Yun/Leo/Micro/Zero/... 41 | delay(100); 42 | Serial.println("\n\nDelete Finger"); 43 | 44 | // set the data rate for the sensor serial port 45 | finger.begin(57600); 46 | 47 | if (finger.verifyPassword()) { 48 | Serial.println("Found fingerprint sensor!"); 49 | } else { 50 | Serial.println("Did not find fingerprint sensor :("); 51 | while (1); 52 | } 53 | } 54 | 55 | 56 | uint8_t readnumber(void) { 57 | uint8_t num = 0; 58 | 59 | while (num == 0) { 60 | while (! Serial.available()); 61 | num = Serial.parseInt(); 62 | } 63 | return num; 64 | } 65 | 66 | void loop() // run over and over again 67 | { 68 | Serial.println("Please type in the ID # (from 1 to 127) you want to delete..."); 69 | uint8_t id = readnumber(); 70 | if (id == 0) {// ID #0 not allowed, try again! 71 | return; 72 | } 73 | 74 | Serial.print("Deleting ID #"); 75 | Serial.println(id); 76 | 77 | deleteFingerprint(id); 78 | } 79 | 80 | uint8_t deleteFingerprint(uint8_t id) { 81 | uint8_t p = -1; 82 | 83 | p = finger.deleteModel(id); 84 | 85 | if (p == FINGERPRINT_OK) { 86 | Serial.println("Deleted!"); 87 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 88 | Serial.println("Communication error"); 89 | return p; 90 | } else if (p == FINGERPRINT_BADLOCATION) { 91 | Serial.println("Could not delete in that location"); 92 | return p; 93 | } else if (p == FINGERPRINT_FLASHERR) { 94 | Serial.println("Error writing to flash"); 95 | return p; 96 | } else { 97 | Serial.print("Unknown error: 0x"); Serial.println(p, HEX); 98 | return p; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/ledcontrol/ledcontrol.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is an example sketch for our optical Fingerprint sensor with LED ring 3 | 4 | These displays use TTL Serial to communicate, 2 pins are required to 5 | interface 6 | Adafruit invests time and resources providing this open source code, 7 | please support Adafruit and open-source hardware by purchasing 8 | products from Adafruit! 9 | 10 | Written by Limor Fried/Ladyada for Adafruit Industries. 11 | BSD license, all text above must be included in any redistribution 12 | ****************************************************/ 13 | 14 | 15 | #include 16 | 17 | 18 | 19 | #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) 20 | // For UNO and others without hardware serial, we must use software serial... 21 | // pin #2 is IN from sensor (GREEN wire) 22 | // pin #3 is OUT from arduino (WHITE wire) 23 | // Set up the serial port to use softwareserial.. 24 | SoftwareSerial mySerial(2, 3); 25 | 26 | #else 27 | // On Leonardo/M0/etc, others with hardware serial, use hardware serial! 28 | // #0 is green wire, #1 is white 29 | #define mySerial Serial1 30 | 31 | #endif 32 | 33 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 34 | 35 | void setup() 36 | { 37 | Serial.begin(9600); 38 | while (!Serial); // For Yun/Leo/Micro/Zero/... 39 | delay(100); 40 | Serial.println("\n\nAdafruit finger detect test"); 41 | 42 | // set the data rate for the sensor serial port 43 | finger.begin(57600); 44 | delay(5); 45 | if (finger.verifyPassword()) { 46 | Serial.println("Found fingerprint sensor!"); 47 | } else { 48 | Serial.println("Did not find fingerprint sensor :("); 49 | while (1) { delay(1); } 50 | } 51 | 52 | Serial.println(F("Reading sensor parameters")); 53 | finger.getParameters(); 54 | Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX); 55 | Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX); 56 | Serial.print(F("Capacity: ")); Serial.println(finger.capacity); 57 | Serial.print(F("Security level: ")); Serial.println(finger.security_level); 58 | Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX); 59 | Serial.print(F("Packet len: ")); Serial.println(finger.packet_len); 60 | Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate); 61 | 62 | 63 | } 64 | 65 | void loop() // run over and over again 66 | { 67 | // LED fully on 68 | finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_RED); 69 | delay(250); 70 | finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_BLUE); 71 | delay(250); 72 | finger.LEDcontrol(FINGERPRINT_LED_ON, 0, FINGERPRINT_LED_PURPLE); 73 | delay(250); 74 | 75 | // flash red LED 76 | finger.LEDcontrol(FINGERPRINT_LED_FLASHING, 25, FINGERPRINT_LED_RED, 10); 77 | delay(2000); 78 | // Breathe blue LED till we say to stop 79 | finger.LEDcontrol(FINGERPRINT_LED_BREATHING, 100, FINGERPRINT_LED_BLUE); 80 | delay(3000); 81 | finger.LEDcontrol(FINGERPRINT_LED_GRADUAL_ON, 200, FINGERPRINT_LED_PURPLE); 82 | delay(2000); 83 | finger.LEDcontrol(FINGERPRINT_LED_GRADUAL_OFF, 200, FINGERPRINT_LED_PURPLE); 84 | delay(2000); 85 | } 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [![buymeacoffee_badge](https://img.shields.io/badge/Donate-buymeacoffe-ff813f?style=flat)](https://www.buymeacoffee.com/madmicio) 3 | 4 | # Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant 5 | 6 | 7 | [![Watch the video](image/fingerprints.png)](https://www.youtube.com/watch?v=Ym1g--MMaKM) 8 | 9 | 10 | ## Hardware List 11 | 12 | - Capacitive fingerprints R502 - R503 13 | - Esp8266 (wemods D1 mini tested) 14 | 15 | ## Software List 16 | 17 | - idearduino sketch (download from reposity) 18 | - adafruit modified libray (download from reposity) 19 | - PubSubClient – provides the MQTT connectivity (install from idearduino library management) 20 | - ArduinoJSON – provides the framework for sending JSON message to Home Assistant (install from idearduino library management) 21 | 22 | ## Hardware connections 23 | 24 | ![all](image/esp8266-3.png) 25 | 26 | R503 - R502 cable colors 27 | 28 | Red: VCC 29 | 30 | Black: GND 31 | 32 | Yellow: TX 33 | 34 | Green: RX 35 | 36 | Blu: not used 37 | 38 | White: not used 39 | 40 | 41 | R502 connection pin: 42 | 43 | ![all](image/r502.png) 44 | 45 | 46 | ## GUIDE 47 | Install the necessary [libraries](https://github.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/tree/main/libraries/Adafruit_Fingerprint_Sensor_Library), 48 | download the [sketch](https://github.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/tree/main/sketch/fingerprints-mqtt) and open it with ide arduino. 49 | 50 | select your board, edit the file with wifi and mqtt credentials 51 | 52 | open the serial monitor. switch your board off and on again. 53 | 54 | if everything went well you will have this screen: 55 | 56 | 57 | 58 | ## Home Assistant Configuration 59 | 60 | install [SAVER](https://github.com/PiotrMachowski/Home-Assistant-custom-components-Saver) integration 61 | 62 | Saver is an extraordinary [Piotr Machowski](https://github.com/PiotrMachowski) project, a simple but very powerful tool. 63 | fills a big gap in Home assistant. 64 | 65 | the R503 - R 502 sensor stores the fingerprint image and associates it with an id 1-127 66 | 67 | in the saver project it is used to store the user name and associate it with the reader id. 68 | 69 | 70 | copy the [script](https://github.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/tree/main/home_assistant) code in your script-file or in your script section 71 | 72 | copy the [sensor](https://github.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/tree/main/home_assistant) code in your script-file or in your script section 73 | 74 | ## OR 75 | 76 | copy [fingerprints_package.yaml](https://github.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/tree/main/home_assistant) in your package folder 77 | 78 | ## Lovelace 79 | 80 | copy [lovelace](https://github.com/madmicio/Fingerprints-reader-R503---R502-esp8266-mqtt-Home-Assistant/tree/main/home_assistant) code in your config 81 | 82 | 83 | ## this project is totally inspired by [EVERYTHING SMART HOME ](https://everythingsmarthome.co.uk/howto/how-to-build-a-wifi-connected-fingerprint-sensor-with-home-assistant/) 84 | 85 | Buy Me A Coffee 86 | 87 | -------------------------------------------------------------------------------- /home_assistant/fingerprints_package.yaml: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Script 3 | ############################################################################### 4 | fingerprint_learning_mode: 5 | alias: Fingerprint learning mode 6 | sequence: 7 | - service: saver.set_variable 8 | data: 9 | name: "{{states('input_number.fingerprint_learning_id') | int}}" 10 | value: "{{states('input_text.id_name')}}" 11 | - data: 12 | payload_template: '{{states(''input_number.fingerprint_learning_id'') | int}}' 13 | topic: /fingerprint/mode/learning 14 | service: mqtt.publish 15 | - service: input_text.set_value 16 | data: 17 | entity_id: input_text.id_name 18 | value: "user name" 19 | - service: browser_mod.close_popup 20 | fingerprint_delete_print: 21 | alias: Fingerprint Delete Print 22 | sequence: 23 | - data: 24 | payload_template: '{{states(''input_number.fingerprint_learning_id'') | int}}' 25 | topic: /fingerprint/mode/delete 26 | service: mqtt.publish 27 | - service: saver.delete_variable 28 | data: 29 | name: "{{states('input_number.fingerprint_learning_id') | int}}" 30 | - service: browser_mod.close_popup 31 | fingerprint_rename: 32 | alias: Fingerprint learning mode 33 | sequence: 34 | - service: saver.set_variable 35 | data: 36 | name: "{{states('input_number.fingerprint_learning_id') | int}}" 37 | value: "{{states('input_text.id_name')}}" 38 | - service: input_text.set_value 39 | data: 40 | entity_id: input_text.id_name 41 | value: "user name" 42 | - service: browser_mod.close_popup 43 | ############################################################################### 44 | # Sensor 45 | ############################################################################### 46 | - platform: mqtt 47 | name: "Fingerprint" 48 | state_topic: "/fingerprint/mode/status" 49 | value_template: "{{value_json.state}}" 50 | json_attributes_topic: "/fingerprint/mode/status" 51 | json_attributes_template: "{{value_json | tojson}}" 52 | - platform: template 53 | sensors: 54 | fingerprint_mode: 55 | friendly_name: "Fingerprint Sensor Mode" 56 | value_template: >- 57 | {{state_attr('sensor.fingerprint', 'mode')}} 58 | icon_template: >- 59 | {% if is_state('sensor.fingerprint_mode', 'reading') %} 60 | mdi:focus-field 61 | {% elif is_state('sensor.fingerprint_mode', 'learning') %} 62 | mdi:draw 63 | {% elif is_state('sensor.fingerprint_mode', 'deleting') %} 64 | mdi:trash-can-outline 65 | {% endif %} 66 | fingerprint_state: 67 | friendly_name: "Fingerprint State" 68 | value_template: >- 69 | {{states('sensor.fingerprint')}} 70 | icon_template: >- 71 | {% if is_state('sensor.fingerprint', 'Waiting') %} 72 | mdi:fingerprint 73 | {% elif is_state('sensor.fingerprint', 'Matched') %} 74 | mdi:shield-check 75 | {% elif is_state('sensor.fingerprint', 'Not matched') %} 76 | mdi:fingerprint-off 77 | {% endif %} 78 | fingerprint_id: 79 | friendly_name: "Fingerprint ID" 80 | value_template: >- 81 | {{state_attr('sensor.fingerprint', 'id')}} 82 | fingerprint_person: 83 | friendly_name: "Fingerprint Person" 84 | value_template: >- 85 | {% if states.sensor.fingerprint_id.state | int > 0.1 %} 86 | {{state_attr('saver.saver', 'variables')[states('sensor.fingerprint_id')] }} 87 | {% elif is_state('sensor.fingerprint', 'Waiting') %} 88 | 89 | {% elif is_state('sensor.fingerprint', 'Not matched') %} 90 | Not matched 91 | {% endif %} 92 | icon_template: >- 93 | {% if is_state('sensor.fingerprint', 'Waiting') %} 94 | mdi:human-male 95 | {% elif is_state('sensor.fingerprint', 'Matched') %} 96 | mdi:human-greeting 97 | {% elif is_state('sensor.fingerprint', 'Not matched') %} 98 | mdi:police-badge 99 | {% elif is_state('sensor.fingerprint', 'Deleted') %} 100 | mdi:trash-can-outline 101 | {% endif %} 102 | ############################################################################### 103 | # input_text 104 | ############################################################################### 105 | input_text: 106 | id_name: 107 | name: name id 108 | initial: user name 109 | ############################################################################### 110 | # input_number 111 | ############################################################################### 112 | input_number: 113 | fingerprint_learning_id: 114 | name: numero impronta 115 | initial: 0 116 | min: 0 117 | max: 127 118 | step: 1 119 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/show_fingerprint_templates/show_fingerprint_templates.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is an example sketch for our optical Fingerprint sensor 3 | 4 | Adafruit invests time and resources providing this open source code, 5 | please support Adafruit and open-source hardware by purchasing 6 | products from Adafruit! 7 | 8 | Written by Limor Fried/Ladyada for Adafruit Industries. 9 | BSD license, all text above must be included in any redistribution 10 | ****************************************************/ 11 | 12 | 13 | #include 14 | 15 | #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) 16 | // For UNO and others without hardware serial, we must use software serial... 17 | // pin #2 is IN from sensor (GREEN wire) 18 | // pin #3 is OUT from arduino (WHITE wire) 19 | // Set up the serial port to use softwareserial.. 20 | SoftwareSerial mySerial(2, 3); 21 | 22 | #else 23 | // On Leonardo/M0/etc, others with hardware serial, use hardware serial! 24 | // #0 is green wire, #1 is white 25 | #define mySerial Serial1 26 | 27 | #endif 28 | 29 | 30 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 31 | 32 | int getFingerprintIDez(); 33 | 34 | void setup() 35 | { 36 | while(!Serial); 37 | Serial.begin(9600); 38 | Serial.println("Fingerprint template extractor"); 39 | 40 | // set the data rate for the sensor serial port 41 | finger.begin(57600); 42 | 43 | if (finger.verifyPassword()) { 44 | Serial.println("Found fingerprint sensor!"); 45 | } else { 46 | Serial.println("Did not find fingerprint sensor :("); 47 | while (1); 48 | } 49 | 50 | // Try to get the templates for fingers 1 through 10 51 | for (int finger = 1; finger < 10; finger++) { 52 | downloadFingerprintTemplate(finger); 53 | } 54 | } 55 | 56 | uint8_t downloadFingerprintTemplate(uint16_t id) 57 | { 58 | Serial.println("------------------------------------"); 59 | Serial.print("Attempting to load #"); Serial.println(id); 60 | uint8_t p = finger.loadModel(id); 61 | switch (p) { 62 | case FINGERPRINT_OK: 63 | Serial.print("Template "); Serial.print(id); Serial.println(" loaded"); 64 | break; 65 | case FINGERPRINT_PACKETRECIEVEERR: 66 | Serial.println("Communication error"); 67 | return p; 68 | default: 69 | Serial.print("Unknown error "); Serial.println(p); 70 | return p; 71 | } 72 | 73 | // OK success! 74 | 75 | Serial.print("Attempting to get #"); Serial.println(id); 76 | p = finger.getModel(); 77 | switch (p) { 78 | case FINGERPRINT_OK: 79 | Serial.print("Template "); Serial.print(id); Serial.println(" transferring:"); 80 | break; 81 | default: 82 | Serial.print("Unknown error "); Serial.println(p); 83 | return p; 84 | } 85 | 86 | // one data packet is 267 bytes. in one data packet, 11 bytes are 'usesless' :D 87 | uint8_t bytesReceived[534]; // 2 data packets 88 | memset(bytesReceived, 0xff, 534); 89 | 90 | uint32_t starttime = millis(); 91 | int i = 0; 92 | while (i < 534 && (millis() - starttime) < 20000) { 93 | if (mySerial.available()) { 94 | bytesReceived[i++] = mySerial.read(); 95 | } 96 | } 97 | Serial.print(i); Serial.println(" bytes read."); 98 | Serial.println("Decoding packet..."); 99 | 100 | uint8_t fingerTemplate[512]; // the real template 101 | memset(fingerTemplate, 0xff, 512); 102 | 103 | // filtering only the data packets 104 | int uindx = 9, index = 0; 105 | while (index < 534) { 106 | while (index < uindx) ++index; 107 | uindx += 256; 108 | while (index < uindx) { 109 | fingerTemplate[index++] = bytesReceived[index]; 110 | } 111 | uindx += 2; 112 | while (index < uindx) ++index; 113 | uindx = index + 9; 114 | } 115 | for (int i = 0; i < 512; ++i) { 116 | //Serial.print("0x"); 117 | printHex(fingerTemplate[i], 2); 118 | //Serial.print(", "); 119 | } 120 | Serial.println("\ndone."); 121 | 122 | /* 123 | uint8_t templateBuffer[256]; 124 | memset(templateBuffer, 0xff, 256); //zero out template buffer 125 | int index=0; 126 | uint32_t starttime = millis(); 127 | while ((index < 256) && ((millis() - starttime) < 1000)) 128 | { 129 | if (mySerial.available()) 130 | { 131 | templateBuffer[index] = mySerial.read(); 132 | index++; 133 | } 134 | } 135 | 136 | Serial.print(index); Serial.println(" bytes read"); 137 | 138 | //dump entire templateBuffer. This prints out 16 lines of 16 bytes 139 | for (int count= 0; count < 16; count++) 140 | { 141 | for (int i = 0; i < 16; i++) 142 | { 143 | Serial.print("0x"); 144 | Serial.print(templateBuffer[count*16+i], HEX); 145 | Serial.print(", "); 146 | } 147 | Serial.println(); 148 | }*/ 149 | } 150 | 151 | 152 | 153 | void printHex(int num, int precision) { 154 | char tmp[16]; 155 | char format[128]; 156 | 157 | sprintf(format, "%%.%dX", precision); 158 | 159 | sprintf(tmp, format, num); 160 | Serial.print(tmp); 161 | } 162 | 163 | void loop() 164 | {} 165 | 166 | 167 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/fingerprint/fingerprint.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is an example sketch for our optical Fingerprint sensor 3 | 4 | Designed specifically to work with the Adafruit BMP085 Breakout 5 | ----> http://www.adafruit.com/products/751 6 | 7 | These displays use TTL Serial to communicate, 2 pins are required to 8 | interface 9 | Adafruit invests time and resources providing this open source code, 10 | please support Adafruit and open-source hardware by purchasing 11 | products from Adafruit! 12 | 13 | Written by Limor Fried/Ladyada for Adafruit Industries. 14 | BSD license, all text above must be included in any redistribution 15 | ****************************************************/ 16 | 17 | 18 | #include 19 | 20 | 21 | #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) 22 | // For UNO and others without hardware serial, we must use software serial... 23 | // pin #2 is IN from sensor (GREEN wire) 24 | // pin #3 is OUT from arduino (WHITE wire) 25 | // Set up the serial port to use softwareserial.. 26 | SoftwareSerial mySerial(2, 3); 27 | 28 | #else 29 | // On Leonardo/M0/etc, others with hardware serial, use hardware serial! 30 | // #0 is green wire, #1 is white 31 | #define mySerial Serial1 32 | 33 | #endif 34 | 35 | 36 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 37 | 38 | void setup() 39 | { 40 | Serial.begin(9600); 41 | while (!Serial); // For Yun/Leo/Micro/Zero/... 42 | delay(100); 43 | Serial.println("\n\nAdafruit finger detect test"); 44 | 45 | // set the data rate for the sensor serial port 46 | finger.begin(57600); 47 | delay(5); 48 | if (finger.verifyPassword()) { 49 | Serial.println("Found fingerprint sensor!"); 50 | } else { 51 | Serial.println("Did not find fingerprint sensor :("); 52 | while (1) { delay(1); } 53 | } 54 | 55 | Serial.println(F("Reading sensor parameters")); 56 | finger.getParameters(); 57 | Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX); 58 | Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX); 59 | Serial.print(F("Capacity: ")); Serial.println(finger.capacity); 60 | Serial.print(F("Security level: ")); Serial.println(finger.security_level); 61 | Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX); 62 | Serial.print(F("Packet len: ")); Serial.println(finger.packet_len); 63 | Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate); 64 | 65 | finger.getTemplateCount(); 66 | 67 | if (finger.templateCount == 0) { 68 | Serial.print("Sensor doesn't contain any fingerprint data. Please run the 'enroll' example."); 69 | } 70 | else { 71 | Serial.println("Waiting for valid finger..."); 72 | Serial.print("Sensor contains "); Serial.print(finger.templateCount); Serial.println(" templates"); 73 | } 74 | } 75 | 76 | void loop() // run over and over again 77 | { 78 | getFingerprintID(); 79 | delay(50); //don't ned to run this at full speed. 80 | } 81 | 82 | uint8_t getFingerprintID() { 83 | uint8_t p = finger.getImage(); 84 | switch (p) { 85 | case FINGERPRINT_OK: 86 | Serial.println("Image taken"); 87 | break; 88 | case FINGERPRINT_NOFINGER: 89 | Serial.println("No finger detected"); 90 | return p; 91 | case FINGERPRINT_PACKETRECIEVEERR: 92 | Serial.println("Communication error"); 93 | return p; 94 | case FINGERPRINT_IMAGEFAIL: 95 | Serial.println("Imaging error"); 96 | return p; 97 | default: 98 | Serial.println("Unknown error"); 99 | return p; 100 | } 101 | 102 | // OK success! 103 | 104 | p = finger.image2Tz(); 105 | switch (p) { 106 | case FINGERPRINT_OK: 107 | Serial.println("Image converted"); 108 | break; 109 | case FINGERPRINT_IMAGEMESS: 110 | Serial.println("Image too messy"); 111 | return p; 112 | case FINGERPRINT_PACKETRECIEVEERR: 113 | Serial.println("Communication error"); 114 | return p; 115 | case FINGERPRINT_FEATUREFAIL: 116 | Serial.println("Could not find fingerprint features"); 117 | return p; 118 | case FINGERPRINT_INVALIDIMAGE: 119 | Serial.println("Could not find fingerprint features"); 120 | return p; 121 | default: 122 | Serial.println("Unknown error"); 123 | return p; 124 | } 125 | 126 | // OK converted! 127 | p = finger.fingerSearch(); 128 | if (p == FINGERPRINT_OK) { 129 | Serial.println("Found a print match!"); 130 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 131 | Serial.println("Communication error"); 132 | return p; 133 | } else if (p == FINGERPRINT_NOTFOUND) { 134 | Serial.println("Did not find a match"); 135 | return p; 136 | } else { 137 | Serial.println("Unknown error"); 138 | return p; 139 | } 140 | 141 | // found a match! 142 | Serial.print("Found ID #"); Serial.print(finger.fingerID); 143 | Serial.print(" with confidence of "); Serial.println(finger.confidence); 144 | 145 | return finger.fingerID; 146 | } 147 | 148 | // returns -1 if failed, otherwise returns ID # 149 | int getFingerprintIDez() { 150 | uint8_t p = finger.getImage(); 151 | if (p != FINGERPRINT_OK) return -1; 152 | 153 | p = finger.image2Tz(); 154 | if (p != FINGERPRINT_OK) return -1; 155 | 156 | p = finger.fingerFastSearch(); 157 | if (p != FINGERPRINT_OK) return -1; 158 | 159 | // found a match! 160 | Serial.print("Found ID #"); Serial.print(finger.fingerID); 161 | Serial.print(" with confidence of "); Serial.println(finger.confidence); 162 | return finger.fingerID; 163 | } 164 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/examples/enroll/enroll.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | This is an example sketch for our optical Fingerprint sensor 3 | 4 | Designed specifically to work with the Adafruit BMP085 Breakout 5 | ----> http://www.adafruit.com/products/751 6 | 7 | These displays use TTL Serial to communicate, 2 pins are required to 8 | interface 9 | Adafruit invests time and resources providing this open source code, 10 | please support Adafruit and open-source hardware by purchasing 11 | products from Adafruit! 12 | 13 | Written by Limor Fried/Ladyada for Adafruit Industries. 14 | BSD license, all text above must be included in any redistribution 15 | ****************************************************/ 16 | 17 | #include 18 | 19 | 20 | #if (defined(__AVR__) || defined(ESP8266)) && !defined(__AVR_ATmega2560__) 21 | // For UNO and others without hardware serial, we must use software serial... 22 | // pin #2 is IN from sensor (GREEN wire) 23 | // pin #3 is OUT from arduino (WHITE wire) 24 | // Set up the serial port to use softwareserial.. 25 | SoftwareSerial mySerial(2, 3); 26 | 27 | #else 28 | // On Leonardo/M0/etc, others with hardware serial, use hardware serial! 29 | // #0 is green wire, #1 is white 30 | #define mySerial Serial1 31 | 32 | #endif 33 | 34 | 35 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 36 | 37 | uint8_t id; 38 | 39 | void setup() 40 | { 41 | Serial.begin(9600); 42 | while (!Serial); // For Yun/Leo/Micro/Zero/... 43 | delay(100); 44 | Serial.println("\n\nAdafruit Fingerprint sensor enrollment"); 45 | 46 | // set the data rate for the sensor serial port 47 | finger.begin(57600); 48 | 49 | if (finger.verifyPassword()) { 50 | Serial.println("Found fingerprint sensor!"); 51 | } else { 52 | Serial.println("Did not find fingerprint sensor :("); 53 | while (1) { delay(1); } 54 | } 55 | 56 | Serial.println(F("Reading sensor parameters")); 57 | finger.getParameters(); 58 | Serial.print(F("Status: 0x")); Serial.println(finger.status_reg, HEX); 59 | Serial.print(F("Sys ID: 0x")); Serial.println(finger.system_id, HEX); 60 | Serial.print(F("Capacity: ")); Serial.println(finger.capacity); 61 | Serial.print(F("Security level: ")); Serial.println(finger.security_level); 62 | Serial.print(F("Device address: ")); Serial.println(finger.device_addr, HEX); 63 | Serial.print(F("Packet len: ")); Serial.println(finger.packet_len); 64 | Serial.print(F("Baud rate: ")); Serial.println(finger.baud_rate); 65 | } 66 | 67 | uint8_t readnumber(void) { 68 | uint8_t num = 0; 69 | 70 | while (num == 0) { 71 | while (! Serial.available()); 72 | num = Serial.parseInt(); 73 | } 74 | return num; 75 | } 76 | 77 | void loop() // run over and over again 78 | { 79 | Serial.println("Ready to enroll a fingerprint!"); 80 | Serial.println("Please type in the ID # (from 1 to 127) you want to save this finger as..."); 81 | id = readnumber(); 82 | if (id == 0) {// ID #0 not allowed, try again! 83 | return; 84 | } 85 | Serial.print("Enrolling ID #"); 86 | Serial.println(id); 87 | 88 | while (! getFingerprintEnroll() ); 89 | } 90 | 91 | uint8_t getFingerprintEnroll() { 92 | 93 | int p = -1; 94 | Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id); 95 | while (p != FINGERPRINT_OK) { 96 | p = finger.getImage(); 97 | switch (p) { 98 | case FINGERPRINT_OK: 99 | Serial.println("Image taken"); 100 | break; 101 | case FINGERPRINT_NOFINGER: 102 | Serial.println("."); 103 | break; 104 | case FINGERPRINT_PACKETRECIEVEERR: 105 | Serial.println("Communication error"); 106 | break; 107 | case FINGERPRINT_IMAGEFAIL: 108 | Serial.println("Imaging error"); 109 | break; 110 | default: 111 | Serial.println("Unknown error"); 112 | break; 113 | } 114 | } 115 | 116 | // OK success! 117 | 118 | p = finger.image2Tz(1); 119 | switch (p) { 120 | case FINGERPRINT_OK: 121 | Serial.println("Image converted"); 122 | break; 123 | case FINGERPRINT_IMAGEMESS: 124 | Serial.println("Image too messy"); 125 | return p; 126 | case FINGERPRINT_PACKETRECIEVEERR: 127 | Serial.println("Communication error"); 128 | return p; 129 | case FINGERPRINT_FEATUREFAIL: 130 | Serial.println("Could not find fingerprint features"); 131 | return p; 132 | case FINGERPRINT_INVALIDIMAGE: 133 | Serial.println("Could not find fingerprint features"); 134 | return p; 135 | default: 136 | Serial.println("Unknown error"); 137 | return p; 138 | } 139 | 140 | Serial.println("Remove finger"); 141 | delay(2000); 142 | p = 0; 143 | while (p != FINGERPRINT_NOFINGER) { 144 | p = finger.getImage(); 145 | } 146 | Serial.print("ID "); Serial.println(id); 147 | p = -1; 148 | Serial.println("Place same finger again"); 149 | while (p != FINGERPRINT_OK) { 150 | p = finger.getImage(); 151 | switch (p) { 152 | case FINGERPRINT_OK: 153 | Serial.println("Image taken"); 154 | break; 155 | case FINGERPRINT_NOFINGER: 156 | Serial.print("."); 157 | break; 158 | case FINGERPRINT_PACKETRECIEVEERR: 159 | Serial.println("Communication error"); 160 | break; 161 | case FINGERPRINT_IMAGEFAIL: 162 | Serial.println("Imaging error"); 163 | break; 164 | default: 165 | Serial.println("Unknown error"); 166 | break; 167 | } 168 | } 169 | 170 | // OK success! 171 | 172 | p = finger.image2Tz(2); 173 | switch (p) { 174 | case FINGERPRINT_OK: 175 | Serial.println("Image converted"); 176 | break; 177 | case FINGERPRINT_IMAGEMESS: 178 | Serial.println("Image too messy"); 179 | return p; 180 | case FINGERPRINT_PACKETRECIEVEERR: 181 | Serial.println("Communication error"); 182 | return p; 183 | case FINGERPRINT_FEATUREFAIL: 184 | Serial.println("Could not find fingerprint features"); 185 | return p; 186 | case FINGERPRINT_INVALIDIMAGE: 187 | Serial.println("Could not find fingerprint features"); 188 | return p; 189 | default: 190 | Serial.println("Unknown error"); 191 | return p; 192 | } 193 | 194 | // OK converted! 195 | Serial.print("Creating model for #"); Serial.println(id); 196 | 197 | p = finger.createModel(); 198 | if (p == FINGERPRINT_OK) { 199 | Serial.println("Prints matched!"); 200 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 201 | Serial.println("Communication error"); 202 | return p; 203 | } else if (p == FINGERPRINT_ENROLLMISMATCH) { 204 | Serial.println("Fingerprints did not match"); 205 | return p; 206 | } else { 207 | Serial.println("Unknown error"); 208 | return p; 209 | } 210 | 211 | Serial.print("ID "); Serial.println(id); 212 | p = finger.storeModel(id); 213 | if (p == FINGERPRINT_OK) { 214 | Serial.println("Stored!"); 215 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 216 | Serial.println("Communication error"); 217 | return p; 218 | } else if (p == FINGERPRINT_BADLOCATION) { 219 | Serial.println("Could not store in that location"); 220 | return p; 221 | } else if (p == FINGERPRINT_FLASHERR) { 222 | Serial.println("Error writing to flash"); 223 | return p; 224 | } else { 225 | Serial.println("Unknown error"); 226 | return p; 227 | } 228 | 229 | return true; 230 | } 231 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/Adafruit_Fingerprint.h: -------------------------------------------------------------------------------- 1 | #ifndef ADAFRUIT_FINGERPRINT_H 2 | #define ADAFRUIT_FINGERPRINT_H 3 | 4 | /*! 5 | * @file Adafruit_Fingerprint.h 6 | */ 7 | 8 | #include "Arduino.h" 9 | #if defined(__AVR__) || defined(ESP8266) 10 | #include 11 | #elif defined(FREEDOM_E300_HIFIVE1) 12 | #include 13 | #define SoftwareSerial SoftwareSerial32 14 | #endif 15 | 16 | #define FINGERPRINT_OK 0x00 //!< Command execution is complete 17 | #define FINGERPRINT_PACKETRECIEVEERR 0x01 //!< Error when receiving data package 18 | #define FINGERPRINT_NOFINGER 0x02 //!< No finger on the sensor 19 | #define FINGERPRINT_IMAGEFAIL 0x03 //!< Failed to enroll the finger 20 | #define FINGERPRINT_IMAGEMESS \ 21 | 0x06 //!< Failed to generate character file due to overly disorderly 22 | //!< fingerprint image 23 | #define FINGERPRINT_FEATUREFAIL \ 24 | 0x07 //!< Failed to generate character file due to the lack of character point 25 | //!< or small fingerprint image 26 | #define FINGERPRINT_NOMATCH 0x08 //!< Finger doesn't match 27 | #define FINGERPRINT_NOTFOUND 0x09 //!< Failed to find matching finger 28 | #define FINGERPRINT_ENROLLMISMATCH \ 29 | 0x0A //!< Failed to combine the character files 30 | #define FINGERPRINT_BADLOCATION \ 31 | 0x0B //!< Addressed PageID is beyond the finger library 32 | #define FINGERPRINT_DBRANGEFAIL \ 33 | 0x0C //!< Error when reading template from library or invalid template 34 | #define FINGERPRINT_UPLOADFEATUREFAIL 0x0D //!< Error when uploading template 35 | #define FINGERPRINT_PACKETRESPONSEFAIL \ 36 | 0x0E //!< Module failed to receive the following data packages 37 | #define FINGERPRINT_UPLOADFAIL 0x0F //!< Error when uploading image 38 | #define FINGERPRINT_DELETEFAIL 0x10 //!< Failed to delete the template 39 | #define FINGERPRINT_DBCLEARFAIL 0x11 //!< Failed to clear finger library 40 | #define FINGERPRINT_PASSFAIL \ 41 | 0x13 //!< Find whether the fingerprint passed or failed 42 | #define FINGERPRINT_INVALIDIMAGE \ 43 | 0x15 //!< Failed to generate image because of lac of valid primary image 44 | #define FINGERPRINT_FLASHERR 0x18 //!< Error when writing flash 45 | #define FINGERPRINT_INVALIDREG 0x1A //!< Invalid register number 46 | #define FINGERPRINT_ADDRCODE 0x20 //!< Address code 47 | #define FINGERPRINT_PASSVERIFY 0x21 //!< Verify the fingerprint passed 48 | #define FINGERPRINT_LED_CONTROL 0x35 49 | 50 | #define FINGERPRINT_STARTCODE \ 51 | 0xEF01 //!< Fixed falue of EF01H; High byte transferred first 52 | 53 | #define FINGERPRINT_COMMANDPACKET 0x1 //!< Command packet 54 | #define FINGERPRINT_DATAPACKET \ 55 | 0x2 //!< Data packet, must follow command packet or acknowledge packet 56 | #define FINGERPRINT_ACKPACKET 0x7 //!< Acknowledge packet 57 | #define FINGERPRINT_ENDDATAPACKET 0x8 //!< End of data packet 58 | 59 | #define FINGERPRINT_TIMEOUT 0xFF //!< Timeout was reached 60 | #define FINGERPRINT_BADPACKET 0xFE //!< Bad packet was sent 61 | 62 | #define FINGERPRINT_GETIMAGE 0x01 //!< Collect finger image 63 | #define FINGERPRINT_IMAGE2TZ 0x02 //!< Generate character file from image 64 | #define FINGERPRINT_SEARCH 0x04 //!< Search for fingerprint in slot 65 | #define FINGERPRINT_REGMODEL \ 66 | 0x05 //!< Combine character files and generate template 67 | #define FINGERPRINT_STORE 0x06 //!< Store template 68 | #define FINGERPRINT_LOAD 0x07 //!< Read/load template 69 | #define FINGERPRINT_UPLOAD 0x08 //!< Upload template 70 | #define FINGERPRINT_DELETE 0x0C //!< Delete templates 71 | #define FINGERPRINT_EMPTY 0x0D //!< Empty library 72 | #define FINGERPRINT_READSYSPARAM 0x0F //!< Read system parameters 73 | #define FINGERPRINT_SETPASSWORD 0x12 //!< Sets passwords 74 | #define FINGERPRINT_VERIFYPASSWORD 0x13 //!< Verifies the password 75 | #define FINGERPRINT_HISPEEDSEARCH \ 76 | 0x1B //!< Asks the sensor to search for a matching fingerprint template to the 77 | //!< last model generated 78 | #define FINGERPRINT_TEMPLATECOUNT 0x1D //!< Read finger template numbers 79 | #define FINGERPRINT_AURALEDCONFIG 0x35 //!< Aura LED control 80 | #define FINGERPRINT_LEDON 0x50 //!< Turn on the onboard LED 81 | #define FINGERPRINT_LEDOFF 0x51 //!< Turn off the onboard LED 82 | 83 | #define FINGERPRINT_LED_BREATHING 0x01 //!< Breathing light 84 | #define FINGERPRINT_LED_FLASHING 0x02 //!< Flashing light 85 | #define FINGERPRINT_LED_ON 0x03 //!< Always on 86 | #define FINGERPRINT_LED_OFF 0x04 //!< Always off 87 | #define FINGERPRINT_LED_GRADUAL_ON 0x05 //!< Gradually on 88 | #define FINGERPRINT_LED_GRADUAL_OFF 0x06 //!< Gradually off 89 | #define FINGERPRINT_LED_RED 0x01 //!< Red LED 90 | #define FINGERPRINT_LED_BLUE 0x02 //!< Blue LED 91 | #define FINGERPRINT_LED_PURPLE 0x03 //!< Purple LED 92 | 93 | //#define FINGERPRINT_DEBUG 94 | 95 | #define DEFAULTTIMEOUT 1000 //!< UART reading timeout in milliseconds 96 | 97 | ///! Helper class to craft UART packets 98 | struct Adafruit_Fingerprint_Packet { 99 | 100 | /**************************************************************************/ 101 | /*! 102 | @brief Create a new UART-borne packet 103 | @param type Command, data, ack type packet 104 | @param length Size of payload 105 | @param data Pointer to bytes of size length we will memcopy into the 106 | internal buffer 107 | */ 108 | /**************************************************************************/ 109 | 110 | Adafruit_Fingerprint_Packet(uint8_t type, uint16_t length, uint8_t *data) { 111 | this->start_code = FINGERPRINT_STARTCODE; 112 | this->type = type; 113 | this->length = length; 114 | address[0] = 0xFF; 115 | address[1] = 0xFF; 116 | address[2] = 0xFF; 117 | address[3] = 0xFF; 118 | if (length < 64) 119 | memcpy(this->data, data, length); 120 | else 121 | memcpy(this->data, data, 64); 122 | } 123 | uint16_t start_code; ///< "Wakeup" code for packet detection 124 | uint8_t address[4]; ///< 32-bit Fingerprint sensor address 125 | uint8_t type; ///< Type of packet 126 | uint16_t length; ///< Length of packet 127 | uint8_t data[64]; ///< The raw buffer for packet payload 128 | }; 129 | 130 | ///! Helper class to communicate with and keep state for fingerprint sensors 131 | class Adafruit_Fingerprint { 132 | public: 133 | #if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1) 134 | Adafruit_Fingerprint(SoftwareSerial *ss, uint32_t password = 0x0); 135 | #endif 136 | Adafruit_Fingerprint(HardwareSerial *hs, uint32_t password = 0x0); 137 | Adafruit_Fingerprint(Stream *serial, uint32_t password = 0x0); 138 | 139 | void begin(uint32_t baud); 140 | 141 | boolean verifyPassword(void); 142 | uint8_t getParameters(void); 143 | 144 | uint8_t getImage(void); 145 | uint8_t image2Tz(uint8_t slot = 1); 146 | uint8_t createModel(void); 147 | 148 | uint8_t emptyDatabase(void); 149 | uint8_t storeModel(uint16_t id); 150 | uint8_t loadModel(uint16_t id); 151 | uint8_t getModel(void); 152 | uint8_t deleteModel(uint16_t id); 153 | uint8_t fingerFastSearch(void); 154 | uint8_t fingerSearch(uint8_t slot = 1); 155 | uint8_t getTemplateCount(void); 156 | uint8_t setPassword(uint32_t password); 157 | uint8_t LEDcontrol(bool on); 158 | uint16_t led_control(uint8_t control_code, uint8_t speed, uint8_t color_idx, uint8_t times); 159 | uint8_t LEDcontrol(uint8_t control, uint8_t speed, uint8_t coloridx, 160 | uint8_t count = 0); 161 | 162 | void writeStructuredPacket(const Adafruit_Fingerprint_Packet &p); 163 | uint8_t getStructuredPacket(Adafruit_Fingerprint_Packet *p, 164 | uint16_t timeout = DEFAULTTIMEOUT); 165 | 166 | /// The matching location that is set by fingerFastSearch() 167 | uint16_t fingerID; 168 | /// The confidence of the fingerFastSearch() match, higher numbers are more 169 | /// confidents 170 | uint16_t confidence; 171 | /// The number of stored templates in the sensor, set by getTemplateCount() 172 | uint16_t templateCount; 173 | 174 | uint16_t status_reg = 0x0; ///< The status register (set by getParameters) 175 | uint16_t system_id = 0x0; ///< The system identifier (set by getParameters) 176 | uint16_t capacity = 64; ///< The fingerprint capacity (set by getParameters) 177 | uint16_t security_level = 0; ///< The security level (set by getParameters) 178 | uint32_t device_addr = 179 | 0xFFFFFFFF; ///< The device address (set by getParameters) 180 | uint16_t packet_len = 64; ///< The max packet length (set by getParameters) 181 | uint16_t baud_rate = 57600; ///< The UART baud rate (set by getParameters) 182 | 183 | private: 184 | uint8_t checkPassword(void); 185 | uint32_t thePassword; 186 | uint32_t theAddress; 187 | uint8_t recvPacket[20]; 188 | 189 | Stream *mySerial; 190 | #if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1) 191 | SoftwareSerial *swSerial; 192 | #endif 193 | HardwareSerial *hwSerial; 194 | }; 195 | 196 | #endif 197 | -------------------------------------------------------------------------------- /home_assistant/lovelace.yaml: -------------------------------------------------------------------------------- 1 | - title: '' 2 | background: var(--simple-background) 3 | path: fingerprint 4 | icon: 'mdi:fingerprint' 5 | badges: [] 6 | cards: 7 | - type: vertical-stack 8 | cards: 9 | - type: markdown 10 | content: > 11 | - type: 'custom:gap-card' 12 | height: 10 13 | - type: horizontal-stack 14 | cards: 15 | - type: 'custom:button-card' 16 | name: > 17 | [[[ 18 | return states['sensor.fingerprint_id'].state; 19 | ]]] 20 | label: Fingerprint ID 21 | show_label: true 22 | styles: 23 | card: 24 | - height: 70px 25 | - width: 150px 26 | name: 27 | - font-size: 26px 28 | - type: 'custom:button-card' 29 | label: Fingerprint Mode 30 | entity: sensor.fingerprint_mode 31 | show_state: true 32 | show_name: false 33 | show_label: true 34 | layout: icon_label 35 | styles: 36 | card: 37 | - height: 70px 38 | - type: 'custom:gap-card' 39 | height: 8 40 | - type: 'custom:button-card' 41 | label: > 42 | [[[ 43 | return states['sensor.fingerprint_person'].state; 44 | ]]] 45 | entity: sensor.fingerprint_state 46 | show_state: true 47 | show_name: false 48 | show_label: true 49 | layout: icon_label 50 | styles: 51 | card: 52 | - height: 100px 53 | state: 54 | - value: 'Matched' 55 | color: white 56 | styles: 57 | card: 58 | - background-color: green 59 | label: 60 | - color: white 61 | - font-size: 30px 62 | state: 63 | - color: white 64 | - value: 'Not matched' 65 | color: white 66 | styles: 67 | card: 68 | - background-color: red 69 | label: 70 | - color: white 71 | - font-size: 30px 72 | state: 73 | - color: white 74 | - value: 'Deleted' 75 | color: white 76 | icon: mdi:trash-can-outline 77 | styles: 78 | card: 79 | - background-color: red 80 | label: 81 | - color: white 82 | - font-size: 30px 83 | state: 84 | - color: white 85 | - operator: default 86 | styles: 87 | card: 88 | state: 89 | - animation: blink 2s ease infinite 90 | - type: 'custom:gap-card' 91 | height: 70 92 | - type: horizontal-stack 93 | cards: 94 | - type: 'custom:button-card' 95 | name: Learn 96 | icon: mdi:fingerprint 97 | size: 35px 98 | tap_action: 99 | action: call-service 100 | service: browser_mod.popup 101 | service_data: 102 | card: 103 | type: custom:mod-card 104 | style: | 105 | ha-card { 106 | border: 2px solid green; 107 | margin: 5px; 108 | padding: 15px; 109 | border-radius: 5px; 110 | } 111 | card: 112 | type: vertical-stack 113 | cards: 114 | - type: 'custom:button-card' 115 | color_type: label-card 116 | name: Fingerprint Slots 117 | color: green 118 | - type: 'custom:gap-card' 119 | height: 5 120 | - type: horizontal-stack 121 | cards: 122 | - type: 'custom:button-card' 123 | icon: mdi:minus 124 | size: 30px 125 | tap_action: 126 | action: call-service 127 | service: input_number.decrement 128 | service_data: 129 | entity_id: input_number.fingerprint_learning_id 130 | styles: 131 | card: 132 | - height: 60px 133 | - width: 60px 134 | - type: markdown 135 | content: > 136 | *id:* __{{states('input_number.fingerprint_learning_id') | round}}__ __{{state_attr('saver.saver', 'variables')[states('input_number.fingerprint_learning_id') | round | string ] }}__ 137 | - type: 'custom:button-card' 138 | icon: mdi:plus 139 | size: 30px 140 | tap_action: 141 | action: call-service 142 | service: input_number.increment 143 | service_data: 144 | entity_id: input_number.fingerprint_learning_id 145 | styles: 146 | card: 147 | - height: 60px 148 | - width: 60px 149 | - entities: 150 | - entity: input_text.id_name 151 | type: entities 152 | - type: horizontal-stack 153 | cards: 154 | - type: 'custom:button-card' 155 | name: ok 156 | tap_action: 157 | action: call-service 158 | service: script.turn_on 159 | service_data: 160 | entity_id: script.fingerprint_learning_mode 161 | styles: 162 | card: 163 | - height: 50px 164 | - type: 'custom:button-card' 165 | name: cancel 166 | tap_action: 167 | action: call-service 168 | service: browser_mod.close_popup 169 | styles: 170 | card: 171 | - height: 50px 172 | deviceID: 173 | - this 174 | title: ' ' 175 | large: false 176 | hide_header: true 177 | - type: 'custom:button-card' 178 | name: Delete 179 | icon: mdi:fingerprint-off 180 | size: 35px 181 | tap_action: 182 | action: call-service 183 | service: browser_mod.popup 184 | service_data: 185 | card: 186 | type: custom:mod-card 187 | style: | 188 | ha-card { 189 | border: 2px solid red; 190 | margin: 5px; 191 | padding: 15px; 192 | border-radius: 5px; 193 | } 194 | card: 195 | type: vertical-stack 196 | cards: 197 | - type: 'custom:button-card' 198 | color_type: label-card 199 | color: red 200 | name: Delete Fingerprint 201 | styles: 202 | card: 203 | - animation: blink 2s ease infinite 204 | - type: 'custom:gap-card' 205 | height: 5 206 | - type: horizontal-stack 207 | cards: 208 | - type: 'custom:button-card' 209 | icon: mdi:minus 210 | size: 30px 211 | tap_action: 212 | action: call-service 213 | service: input_number.decrement 214 | service_data: 215 | entity_id: input_number.fingerprint_learning_id 216 | styles: 217 | card: 218 | - height: 60px 219 | - width: 60px 220 | - type: markdown 221 | content: > 222 | *id:* __{{states('input_number.fingerprint_learning_id') | round}}__ __{{state_attr('saver.saver', 'variables')[states('input_number.fingerprint_learning_id') | round | string ] }}__ 223 | - type: 'custom:button-card' 224 | icon: mdi:plus 225 | size: 30px 226 | tap_action: 227 | action: call-service 228 | service: input_number.increment 229 | service_data: 230 | entity_id: input_number.fingerprint_learning_id 231 | styles: 232 | card: 233 | - height: 60px 234 | - width: 60px 235 | - type: horizontal-stack 236 | cards: 237 | - type: 'custom:button-card' 238 | name: ok 239 | tap_action: 240 | action: call-service 241 | service: script.turn_on 242 | service_data: 243 | entity_id: script.fingerprint_delete_print 244 | styles: 245 | card: 246 | - height: 50px 247 | - type: 'custom:button-card' 248 | name: cancel 249 | tap_action: 250 | action: call-service 251 | service: browser_mod.close_popup 252 | styles: 253 | card: 254 | - height: 50px 255 | deviceID: 256 | - this 257 | title: ' ' 258 | large: false 259 | hide_header: true 260 | 261 | - type: 'custom:button-card' 262 | name: Rename 263 | icon: mdi:form-textbox 264 | size: 35px 265 | tap_action: 266 | action: call-service 267 | service: browser_mod.popup 268 | service_data: 269 | card: 270 | type: custom:mod-card 271 | style: | 272 | ha-card { 273 | border: 2px solid gray; 274 | margin: 5px; 275 | padding: 15px; 276 | border-radius: 5px; 277 | } 278 | card: 279 | type: vertical-stack 280 | cards: 281 | - type: 'custom:button-card' 282 | color_type: label-card 283 | name: Rename Fingerprint 284 | - type: 'custom:gap-card' 285 | height: 5 286 | - type: horizontal-stack 287 | cards: 288 | - type: 'custom:button-card' 289 | icon: mdi:minus 290 | size: 30px 291 | tap_action: 292 | action: call-service 293 | service: input_number.decrement 294 | service_data: 295 | entity_id: input_number.fingerprint_learning_id 296 | styles: 297 | card: 298 | - height: 60px 299 | - width: 60px 300 | - type: markdown 301 | content: > 302 | *id:* __{{states('input_number.fingerprint_learning_id') | round}}__ __{{state_attr('saver.saver', 'variables')[states('input_number.fingerprint_learning_id') | round | string ] }}__ 303 | - type: 'custom:button-card' 304 | icon: mdi:plus 305 | size: 30px 306 | tap_action: 307 | action: call-service 308 | service: input_number.increment 309 | service_data: 310 | entity_id: input_number.fingerprint_learning_id 311 | styles: 312 | card: 313 | - height: 60px 314 | - width: 60px 315 | - entities: 316 | - entity: input_text.id_name 317 | type: entities 318 | - type: horizontal-stack 319 | cards: 320 | - type: 'custom:button-card' 321 | name: ok 322 | tap_action: 323 | action: call-service 324 | service: script.turn_on 325 | service_data: 326 | entity_id: script.fingerprint_rename 327 | styles: 328 | card: 329 | - height: 50px 330 | - type: 'custom:button-card' 331 | name: cancel 332 | tap_action: 333 | action: call-service 334 | service: browser_mod.close_popup 335 | styles: 336 | card: 337 | - height: 50px 338 | deviceID: 339 | - this 340 | title: ' ' 341 | large: false 342 | hide_header: true 343 | -------------------------------------------------------------------------------- /sketch/fingerprints-mqtt/fingerprints-mqtt.ino: -------------------------------------------------------------------------------- 1 | /************************************* 2 | * https://everythingsmarthome.co.uk 3 | * 4 | * This is an MQTT connected fingerprint sensor which can 5 | * used to connect to your home automation software of choice. 6 | * 7 | * You can add and remove fingerprints using MQTT topics by 8 | * sending the ID through the topic. 9 | * 10 | * Simply configure the Wifi and MQTT parameters below to get 11 | * started! 12 | * 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | // Wifi Settings 21 | #define SSID "WiFi SSID" 22 | #define PASSWORD "WiFi Password" 23 | 24 | // MQTT Settings 25 | #define HOSTNAME "fingerprint-sensor" 26 | #define MQTT_SERVER "192.168.1.xxx" 27 | #define STATE_TOPIC "/fingerprint/mode/status" 28 | #define MODE_LEARNING "/fingerprint/mode/learning" 29 | #define MODE_READING "/fingerprint/mode/reading" 30 | #define MODE_DELETE "/fingerprint/mode/delete" 31 | #define AVAILABILITY_TOPIC "/fingerprint/available" 32 | #define mqtt_username "username" 33 | #define mqtt_password "Password" 34 | 35 | #define MQTT_INTERVAL 5000 //MQTT rate limiting when no finger present, in ms 36 | 37 | #define SENSOR_TX 12 //GPIO Pin for RX 38 | #define SENSOR_RX 14 //GPIO Pin for TX 39 | 40 | SoftwareSerial mySerial(SENSOR_TX, SENSOR_RX); 41 | Adafruit_Fingerprint finger = Adafruit_Fingerprint(&mySerial); 42 | 43 | WiFiClient wifiClient; // Initiate WiFi library 44 | PubSubClient client(wifiClient); // Initiate PubSubClient library 45 | 46 | uint8_t id = 0; //Stores the current fingerprint ID 47 | uint8_t lastID = 0; //Stores the last matched ID 48 | uint8_t lastConfidenceScore = 0; //Stores the last matched confidence score 49 | boolean modeLearning = false; 50 | boolean modeReading = true; 51 | boolean modeDelete = false; 52 | unsigned long lastMQTTmsg = 0; //Stores millis since last MQTT message 53 | 54 | //Declare JSON variables 55 | DynamicJsonDocument mqttMessage(100); 56 | char mqttBuffer[100]; 57 | 58 | void setup() 59 | { 60 | Serial.begin(57600); 61 | while (!Serial); 62 | delay(100); 63 | Serial.println("\n\nWelcome to the MQTT Fingerprint Sensor program!"); 64 | 65 | // set the data rate for the sensor serial port 66 | finger.begin(57600); 67 | delay(5); 68 | if (finger.verifyPassword()) { 69 | Serial.println("Found fingerprint sensor!"); 70 | } else { 71 | Serial.println("Did not find fingerprint sensor :("); 72 | finger.led_control(1,100,2,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255) 73 | while (1) { 74 | delay(1); 75 | } 76 | } 77 | 78 | WiFi.mode(WIFI_STA); 79 | WiFi.begin(SSID, PASSWORD); 80 | Serial.print("Connecting..."); 81 | 82 | while (WiFi.status() != WL_CONNECTED) { // Wait till Wifi connected 83 | delay(500); 84 | Serial.print("."); 85 | } 86 | Serial.println(); 87 | 88 | Serial.print("Connected, IP address: "); 89 | Serial.println(WiFi.localIP()); // Print IP address 90 | 91 | client.setServer(MQTT_SERVER, 1883); // Set MQTT server and port number 92 | client.setCallback(callback); 93 | } 94 | 95 | void loop() { 96 | if (!client.connected()) { 97 | reconnect(); //Just incase we get disconnected from MQTT server 98 | } 99 | if (modeReading == true && modeLearning == false) { 100 | uint8_t result = getFingerprintID(); 101 | if (result == FINGERPRINT_OK) { 102 | mqttMessage["mode"] = "reading"; 103 | mqttMessage["id"] = lastID; 104 | mqttMessage["state"] = "Matched"; 105 | mqttMessage["confidence"] = lastConfidenceScore; 106 | size_t mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 107 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 108 | lastMQTTmsg = millis(); 109 | delay(500); 110 | } else if (result == FINGERPRINT_NOTFOUND) { 111 | mqttMessage["mode"] = "reading"; 112 | mqttMessage["match"] = false; 113 | mqttMessage["id"] = id; 114 | mqttMessage["state"] = "Not matched"; 115 | size_t mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 116 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 117 | lastMQTTmsg = millis(); 118 | delay(500); 119 | } else if (result == FINGERPRINT_NOFINGER) { 120 | if ((millis() - lastMQTTmsg) > MQTT_INTERVAL){ 121 | mqttMessage["mode"] = "reading"; 122 | mqttMessage["id"] = id; 123 | mqttMessage["state"] = "Waiting"; 124 | size_t mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 125 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 126 | lastMQTTmsg = millis(); 127 | } 128 | if ((millis() - lastMQTTmsg) < 0){ 129 | lastMQTTmsg = millis(); //Just in case millis ever rolls over 130 | } 131 | } else { 132 | 133 | } 134 | } 135 | client.loop(); 136 | delay(100); //don't need to run this at full speed. 137 | } 138 | 139 | uint8_t getFingerprintID() { 140 | uint8_t p = finger.getImage(); 141 | switch (p) { 142 | case FINGERPRINT_OK: 143 | Serial.println("Image taken"); 144 | // finger.led_control(1,10,3,6); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 145 | break; 146 | case FINGERPRINT_NOFINGER: 147 | //Serial.println("No finger detected"); 148 | //finger.led_control(1,20,2,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 149 | return p; 150 | case FINGERPRINT_PACKETRECIEVEERR: 151 | Serial.println("Communication error"); 152 | return p; 153 | case FINGERPRINT_IMAGEFAIL: 154 | Serial.println("Imaging error"); 155 | return p; 156 | default: 157 | Serial.println("Unknown error"); 158 | return p; 159 | } 160 | 161 | // OK success! 162 | 163 | p = finger.image2Tz(); 164 | switch (p) { 165 | case FINGERPRINT_OK: 166 | Serial.println("Image converted"); 167 | break; 168 | case FINGERPRINT_IMAGEMESS: 169 | Serial.println("Image too messy"); 170 | return p; 171 | case FINGERPRINT_PACKETRECIEVEERR: 172 | Serial.println("Communication error"); 173 | return p; 174 | case FINGERPRINT_FEATUREFAIL: 175 | Serial.println("Could not find fingerprint features"); 176 | return p; 177 | case FINGERPRINT_INVALIDIMAGE: 178 | Serial.println("Could not find fingerprint features"); 179 | return p; 180 | default: 181 | Serial.println("Unknown error"); 182 | return p; 183 | } 184 | 185 | // OK converted! 186 | p = finger.fingerSearch(); 187 | if (p == FINGERPRINT_OK) { 188 | Serial.println("Found a print match!"); 189 | lastID = finger.fingerID; 190 | lastConfidenceScore = finger.confidence; 191 | finger.led_control(1,200,2,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 192 | return p; 193 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 194 | Serial.println("Communication error"); 195 | return p; 196 | } else if (p == FINGERPRINT_NOTFOUND) { 197 | Serial.println("Did not find a match"); 198 | finger.led_control(1,200,1,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 199 | return p; 200 | } else { 201 | Serial.println("Unknown error"); 202 | return p; 203 | } 204 | 205 | // found a match! 206 | Serial.print("Found ID #"); Serial.print(finger.fingerID); 207 | Serial.print(" with confidence of "); Serial.println(finger.confidence); 208 | 209 | return finger.fingerID; 210 | } 211 | 212 | uint8_t getFingerprintEnroll() { 213 | int p = -1; 214 | mqttMessage["mode"] = "learning"; 215 | mqttMessage["id"] = id; 216 | mqttMessage["state"] = "Place finger.."; 217 | size_t mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 218 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 219 | Serial.print("Waiting for valid finger to enroll as #"); Serial.println(id); 220 | while (p != FINGERPRINT_OK) { 221 | p = finger.getImage(); 222 | switch (p) { 223 | case FINGERPRINT_OK: 224 | Serial.println("Image taken"); 225 | finger.led_control(1,100,2,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 226 | break; 227 | case FINGERPRINT_NOFINGER: 228 | Serial.print("."); 229 | finger.led_control(1,15,3,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 230 | break; 231 | case FINGERPRINT_PACKETRECIEVEERR: 232 | Serial.println("Communication error"); 233 | break; 234 | case FINGERPRINT_IMAGEFAIL: 235 | Serial.println("Imaging error"); 236 | break; 237 | default: 238 | Serial.println("Unknown error"); 239 | break; 240 | } 241 | } 242 | 243 | // OK success! 244 | 245 | p = finger.image2Tz(1); 246 | switch (p) { 247 | case FINGERPRINT_OK: 248 | Serial.println("Image converted"); 249 | break; 250 | case FINGERPRINT_IMAGEMESS: 251 | Serial.println("Image too messy"); 252 | return p; 253 | case FINGERPRINT_PACKETRECIEVEERR: 254 | Serial.println("Communication error"); 255 | return p; 256 | case FINGERPRINT_FEATUREFAIL: 257 | Serial.println("Could not find fingerprint features"); 258 | return p; 259 | case FINGERPRINT_INVALIDIMAGE: 260 | Serial.println("Could not find fingerprint features"); 261 | return p; 262 | default: 263 | Serial.println("Unknown error"); 264 | return p; 265 | } 266 | 267 | mqttMessage["mode"] = "learning"; 268 | mqttMessage["id"] = id; 269 | mqttMessage["state"] = "Remove finger.."; 270 | mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 271 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 272 | Serial.println("Remove finger"); 273 | delay(2000); 274 | p = 0; 275 | while (p != FINGERPRINT_NOFINGER) { 276 | p = finger.getImage(); 277 | } 278 | Serial.print("ID "); Serial.println(id); 279 | p = -1; 280 | mqttMessage["mode"] = "learning"; 281 | mqttMessage["id"] = id; 282 | mqttMessage["state"] = "Place same finger.."; 283 | mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 284 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 285 | Serial.println("Place same finger again"); 286 | while (p != FINGERPRINT_OK) { 287 | p = finger.getImage(); 288 | switch (p) { 289 | case FINGERPRINT_OK: 290 | Serial.println("Image taken"); 291 | finger.led_control(1,150,2,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 292 | break; 293 | case FINGERPRINT_NOFINGER: 294 | Serial.print("."); 295 | finger.led_control(1,15,3,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 296 | break; 297 | case FINGERPRINT_PACKETRECIEVEERR: 298 | Serial.println("Communication error"); 299 | break; 300 | case FINGERPRINT_IMAGEFAIL: 301 | Serial.println("Imaging error"); 302 | break; 303 | default: 304 | Serial.println("Unknown error"); 305 | break; 306 | } 307 | } 308 | 309 | // OK success! 310 | 311 | p = finger.image2Tz(2); 312 | switch (p) { 313 | case FINGERPRINT_OK: 314 | Serial.println("Image converted"); 315 | break; 316 | case FINGERPRINT_IMAGEMESS: 317 | Serial.println("Image too messy"); 318 | return p; 319 | case FINGERPRINT_PACKETRECIEVEERR: 320 | Serial.println("Communication error"); 321 | return p; 322 | case FINGERPRINT_FEATUREFAIL: 323 | Serial.println("Could not find fingerprint features"); 324 | return p; 325 | case FINGERPRINT_INVALIDIMAGE: 326 | Serial.println("Could not find fingerprint features"); 327 | return p; 328 | default: 329 | Serial.println("Unknown error"); 330 | return p; 331 | } 332 | 333 | // OK converted! 334 | Serial.print("Creating model for #"); Serial.println(id); 335 | 336 | p = finger.createModel(); 337 | if (p == FINGERPRINT_OK) { 338 | Serial.println("Prints matched!"); 339 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 340 | Serial.println("Communication error"); 341 | return p; 342 | } else if (p == FINGERPRINT_ENROLLMISMATCH) { 343 | Serial.println("Fingerprints did not match"); 344 | return p; 345 | } else { 346 | Serial.println("Unknown error"); 347 | return p; 348 | } 349 | 350 | Serial.print("ID "); Serial.println(id); 351 | p = finger.storeModel(id); 352 | if (p == FINGERPRINT_OK) { 353 | mqttMessage["mode"] = "learning"; 354 | mqttMessage["id"] = id; 355 | mqttMessage["state"] = "Success, stored!"; 356 | mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 357 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 358 | Serial.println("Stored!"); 359 | return true; 360 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 361 | Serial.println("Communication error"); 362 | return p; 363 | } else if (p == FINGERPRINT_BADLOCATION) { 364 | Serial.println("Could not store in that location"); 365 | return p; 366 | } else if (p == FINGERPRINT_FLASHERR) { 367 | Serial.println("Error writing to flash"); 368 | return p; 369 | } else { 370 | Serial.println("Unknown error"); 371 | return p; 372 | } 373 | } 374 | 375 | uint8_t deleteFingerprint() { 376 | uint8_t p = -1; 377 | 378 | p = finger.deleteModel(id); 379 | 380 | if (p == FINGERPRINT_OK) { 381 | Serial.println("Deleted"); 382 | mqttMessage["mode"] = "deleting"; 383 | mqttMessage["id"] = id; 384 | mqttMessage["state"] = "Deleted"; 385 | size_t mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 386 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 387 | finger.led_control(1,150,1,1); // code(1-6),speed(1-255),color(1-R/2-B/3_P),time(1-255 388 | return true; 389 | } else if (p == FINGERPRINT_PACKETRECIEVEERR) { 390 | Serial.println("Communication error"); 391 | return p; 392 | } else if (p == FINGERPRINT_BADLOCATION) { 393 | Serial.println("Could not delete in that location"); 394 | return p; 395 | } else if (p == FINGERPRINT_FLASHERR) { 396 | Serial.println("Error writing to flash"); 397 | return p; 398 | } else { 399 | Serial.print("Unknown error: 0x"); Serial.println(p, HEX); 400 | return p; 401 | } 402 | } 403 | 404 | void reconnect() { 405 | while (!client.connected()) { // Loop until connected to MQTT server 406 | Serial.print("Attempting MQTT connection..."); 407 | if (client.connect(HOSTNAME, mqtt_username, mqtt_password, AVAILABILITY_TOPIC, 1, true, "offline")) { //Connect to MQTT server 408 | Serial.println("connected"); 409 | client.publish(AVAILABILITY_TOPIC, "online"); // Once connected, publish online to the availability topic 410 | client.subscribe(MODE_LEARNING); //Subscribe to Learning Mode Topic 411 | client.subscribe(MODE_READING); 412 | client.subscribe(MODE_DELETE); 413 | } else { 414 | Serial.print("failed, rc="); 415 | Serial.print(client.state()); 416 | Serial.println(" try again in 5 seconds"); 417 | delay(5000); // Will attempt connection again in 5 seconds 418 | } 419 | } 420 | } 421 | 422 | void callback(char* topic, byte* payload, unsigned int length) { //The MQTT callback which listens for incoming messages on the subscribed topics 423 | if (strcmp(topic, MODE_LEARNING) == 0) { 424 | char charArray[3]; 425 | for (int i = 0; i < length; i++) { 426 | //Serial.print((char)payload[i]); 427 | charArray[i] = payload[i]; 428 | } 429 | id = atoi(charArray); 430 | if (id > 0 && id < 128) { 431 | Serial.println("Entering Learning mode"); 432 | mqttMessage["mode"] = "learning"; 433 | mqttMessage["id"] = id; 434 | size_t mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 435 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 436 | while (!getFingerprintEnroll()); 437 | Serial.println("Exiting Learning mode"); 438 | modeLearning = false; 439 | modeReading = true; 440 | modeDelete = false; 441 | id = 0; 442 | } else { 443 | Serial.println("No"); 444 | } 445 | Serial.println(); 446 | } 447 | 448 | if (strcmp(topic, MODE_DELETE) == 0) { 449 | char charArray[3]; 450 | for (int i = 0; i < length; i++) { 451 | //Serial.print((char)payload[i]); 452 | charArray[i] = payload[i]; 453 | } 454 | id = atoi(charArray); 455 | if (id > 0 && id < 128) { 456 | mqttMessage["mode"] = "deleting"; 457 | mqttMessage["id"] = id; 458 | size_t mqttMessageSize = serializeJson(mqttMessage, mqttBuffer); 459 | client.publish(STATE_TOPIC, mqttBuffer, mqttMessageSize); 460 | Serial.println("Entering delete mode"); 461 | while (! deleteFingerprint()); 462 | Serial.println("Exiting delete mode"); 463 | delay(2000); //Make the mqttMessage readable in HA 464 | modeLearning = false; 465 | modeReading = true; 466 | modeDelete = false; 467 | id = 0; 468 | } 469 | Serial.println(); 470 | } 471 | } 472 | -------------------------------------------------------------------------------- /libraries/Adafruit_Fingerprint_Sensor_Library/Adafruit_Fingerprint.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_Fingerprint.cpp 3 | * 4 | * @mainpage Adafruit Fingerprint Sensor Library 5 | * 6 | * @section intro_sec Introduction 7 | * 8 | * This is a library for our optical Fingerprint sensor 9 | * 10 | * Designed specifically to work with the Adafruit Fingerprint sensor 11 | * ----> http://www.adafruit.com/products/751 12 | * 13 | * These displays use TTL Serial to communicate, 2 pins are required to 14 | * interface 15 | * Adafruit invests time and resources providing this open source code, 16 | * please support Adafruit and open-source hardware by purchasing 17 | * products from Adafruit! 18 | * 19 | * @section author Author 20 | * 21 | * Written by Limor Fried/Ladyada for Adafruit Industries. 22 | * 23 | * @section license License 24 | * 25 | * BSD license, all text above must be included in any redistribution 26 | * 27 | */ 28 | 29 | #include "Adafruit_Fingerprint.h" 30 | 31 | //#define FINGERPRINT_DEBUG 32 | 33 | /*! 34 | * @brief Gets the command packet 35 | */ 36 | #define GET_CMD_PACKET(...) \ 37 | uint8_t data[] = {__VA_ARGS__}; \ 38 | Adafruit_Fingerprint_Packet packet(FINGERPRINT_COMMANDPACKET, sizeof(data), \ 39 | data); \ 40 | writeStructuredPacket(packet); \ 41 | if (getStructuredPacket(&packet) != FINGERPRINT_OK) \ 42 | return FINGERPRINT_PACKETRECIEVEERR; \ 43 | if (packet.type != FINGERPRINT_ACKPACKET) \ 44 | return FINGERPRINT_PACKETRECIEVEERR; 45 | 46 | /*! 47 | * @brief Sends the command packet 48 | */ 49 | #define SEND_CMD_PACKET(...) \ 50 | GET_CMD_PACKET(__VA_ARGS__); \ 51 | return packet.data[0]; 52 | 53 | /*************************************************************************** 54 | PUBLIC FUNCTIONS 55 | ***************************************************************************/ 56 | 57 | #if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1) 58 | /**************************************************************************/ 59 | /*! 60 | @brief Instantiates sensor with Software Serial 61 | @param ss Pointer to SoftwareSerial object 62 | @param password 32-bit integer password (default is 0) 63 | */ 64 | /**************************************************************************/ 65 | Adafruit_Fingerprint::Adafruit_Fingerprint(SoftwareSerial *ss, 66 | uint32_t password) { 67 | thePassword = password; 68 | theAddress = 0xFFFFFFFF; 69 | 70 | hwSerial = NULL; 71 | swSerial = ss; 72 | mySerial = swSerial; 73 | } 74 | #endif 75 | 76 | /**************************************************************************/ 77 | /*! 78 | @brief Instantiates sensor with Hardware Serial 79 | @param hs Pointer to HardwareSerial object 80 | @param password 32-bit integer password (default is 0) 81 | 82 | */ 83 | /**************************************************************************/ 84 | Adafruit_Fingerprint::Adafruit_Fingerprint(HardwareSerial *hs, 85 | uint32_t password) { 86 | thePassword = password; 87 | theAddress = 0xFFFFFFFF; 88 | 89 | #if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1) 90 | swSerial = NULL; 91 | #endif 92 | hwSerial = hs; 93 | mySerial = hwSerial; 94 | } 95 | 96 | /**************************************************************************/ 97 | /*! 98 | @brief Instantiates sensor with a stream for Serial 99 | @param serial Pointer to a Stream object 100 | @param password 32-bit integer password (default is 0) 101 | 102 | */ 103 | /**************************************************************************/ 104 | 105 | Adafruit_Fingerprint::Adafruit_Fingerprint(Stream *serial, uint32_t password) { 106 | 107 | thePassword = password; 108 | theAddress = 0xFFFFFFFF; 109 | 110 | hwSerial = NULL; 111 | #if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1) 112 | swSerial = NULL; 113 | #endif 114 | mySerial = serial; 115 | } 116 | 117 | /**************************************************************************/ 118 | /*! 119 | @brief Initializes serial interface and baud rate 120 | @param baudrate Sensor's UART baud rate (usually 57600, 9600 or 115200) 121 | */ 122 | /**************************************************************************/ 123 | void Adafruit_Fingerprint::begin(uint32_t baudrate) { 124 | delay(1000); // one second delay to let the sensor 'boot up' 125 | 126 | if (hwSerial) 127 | hwSerial->begin(baudrate); 128 | #if defined(__AVR__) || defined(ESP8266) || defined(FREEDOM_E300_HIFIVE1) 129 | if (swSerial) 130 | swSerial->begin(baudrate); 131 | #endif 132 | } 133 | 134 | /**************************************************************************/ 135 | /*! 136 | @brief Verifies the sensors' access password (default password is 137 | 0x0000000). A good way to also check if the sensors is active and responding 138 | @returns True if password is correct 139 | */ 140 | /**************************************************************************/ 141 | boolean Adafruit_Fingerprint::verifyPassword(void) { 142 | return checkPassword() == FINGERPRINT_OK; 143 | } 144 | 145 | uint8_t Adafruit_Fingerprint::checkPassword(void) { 146 | GET_CMD_PACKET(FINGERPRINT_VERIFYPASSWORD, (uint8_t)(thePassword >> 24), 147 | (uint8_t)(thePassword >> 16), (uint8_t)(thePassword >> 8), 148 | (uint8_t)(thePassword & 0xFF)); 149 | if (packet.data[0] == FINGERPRINT_OK) 150 | return FINGERPRINT_OK; 151 | else 152 | return FINGERPRINT_PACKETRECIEVEERR; 153 | } 154 | 155 | /**************************************************************************/ 156 | /*! 157 | @brief Get the sensors parameters, fills in the member variables 158 | status_reg, system_id, capacity, security_level, device_addr, packet_len 159 | and baud_rate 160 | @returns True if password is correct 161 | */ 162 | /**************************************************************************/ 163 | uint8_t Adafruit_Fingerprint::getParameters(void) { 164 | GET_CMD_PACKET(FINGERPRINT_READSYSPARAM); 165 | 166 | status_reg = ((uint16_t)packet.data[1] << 8) | packet.data[2]; 167 | system_id = ((uint16_t)packet.data[3] << 8) | packet.data[4]; 168 | capacity = ((uint16_t)packet.data[5] << 8) | packet.data[6]; 169 | security_level = ((uint16_t)packet.data[7] << 8) | packet.data[8]; 170 | device_addr = ((uint32_t)packet.data[9] << 24) | 171 | ((uint32_t)packet.data[10] << 16) | 172 | ((uint32_t)packet.data[11] << 8) | (uint32_t)packet.data[12]; 173 | packet_len = ((uint16_t)packet.data[13] << 8) | packet.data[14]; 174 | if (packet_len == 0) { 175 | packet_len = 32; 176 | } else if (packet_len == 1) { 177 | packet_len = 64; 178 | } else if (packet_len == 2) { 179 | packet_len = 128; 180 | } else if (packet_len == 3) { 181 | packet_len = 256; 182 | } 183 | baud_rate = (((uint16_t)packet.data[15] << 8) | packet.data[16]) * 9600; 184 | 185 | return packet.data[0]; 186 | } 187 | 188 | /**************************************************************************/ 189 | /*! 190 | @brief Ask the sensor to take an image of the finger pressed on surface 191 | @returns FINGERPRINT_OK on success 192 | @returns FINGERPRINT_NOFINGER if no finger detected 193 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 194 | @returns FINGERPRINT_IMAGEFAIL on imaging error 195 | */ 196 | /**************************************************************************/ 197 | uint8_t Adafruit_Fingerprint::getImage(void) { 198 | SEND_CMD_PACKET(FINGERPRINT_GETIMAGE); 199 | } 200 | 201 | /**************************************************************************/ 202 | /*! 203 | @brief Ask the sensor to convert image to feature template 204 | @param slot Location to place feature template (put one in 1 and another in 205 | 2 for verification to create model) 206 | @returns FINGERPRINT_OK on success 207 | @returns FINGERPRINT_IMAGEMESS if image is too messy 208 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 209 | @returns FINGERPRINT_FEATUREFAIL on failure to identify 210 | fingerprint features 211 | @returns FINGERPRINT_INVALIDIMAGE on failure to identify 212 | fingerprint features 213 | */ 214 | uint8_t Adafruit_Fingerprint::image2Tz(uint8_t slot) { 215 | SEND_CMD_PACKET(FINGERPRINT_IMAGE2TZ, slot); 216 | } 217 | 218 | /**************************************************************************/ 219 | /*! 220 | @brief Ask the sensor to take two print feature template and create a 221 | model 222 | @returns FINGERPRINT_OK on success 223 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 224 | @returns FINGERPRINT_ENROLLMISMATCH on mismatch of fingerprints 225 | */ 226 | uint8_t Adafruit_Fingerprint::createModel(void) { 227 | SEND_CMD_PACKET(FINGERPRINT_REGMODEL); 228 | } 229 | 230 | /**************************************************************************/ 231 | /*! 232 | @brief Ask the sensor to store the calculated model for later matching 233 | @param location The model location # 234 | @returns FINGERPRINT_OK on success 235 | @returns FINGERPRINT_BADLOCATION if the location is invalid 236 | @returns FINGERPRINT_FLASHERR if the model couldn't be written 237 | to flash memory 238 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 239 | */ 240 | uint8_t Adafruit_Fingerprint::storeModel(uint16_t location) { 241 | SEND_CMD_PACKET(FINGERPRINT_STORE, 0x01, (uint8_t)(location >> 8), 242 | (uint8_t)(location & 0xFF)); 243 | } 244 | 245 | /**************************************************************************/ 246 | /*! 247 | @brief Ask the sensor to load a fingerprint model from flash into buffer 1 248 | @param location The model location # 249 | @returns FINGERPRINT_OK on success 250 | @returns FINGERPRINT_BADLOCATION if the location is invalid 251 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 252 | */ 253 | uint8_t Adafruit_Fingerprint::loadModel(uint16_t location) { 254 | SEND_CMD_PACKET(FINGERPRINT_LOAD, 0x01, (uint8_t)(location >> 8), 255 | (uint8_t)(location & 0xFF)); 256 | } 257 | 258 | /**************************************************************************/ 259 | /*! 260 | @brief Ask the sensor to transfer 256-byte fingerprint template from the 261 | buffer to the UART 262 | @returns FINGERPRINT_OK on success 263 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 264 | */ 265 | uint8_t Adafruit_Fingerprint::getModel(void) { 266 | SEND_CMD_PACKET(FINGERPRINT_UPLOAD, 0x01); 267 | } 268 | 269 | /**************************************************************************/ 270 | /*! 271 | @brief Ask the sensor to delete a model in memory 272 | @param location The model location # 273 | @returns FINGERPRINT_OK on success 274 | @returns FINGERPRINT_BADLOCATION if the location is invalid 275 | @returns FINGERPRINT_FLASHERR if the model couldn't be written 276 | to flash memory 277 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 278 | */ 279 | uint8_t Adafruit_Fingerprint::deleteModel(uint16_t location) { 280 | SEND_CMD_PACKET(FINGERPRINT_DELETE, (uint8_t)(location >> 8), 281 | (uint8_t)(location & 0xFF), 0x00, 0x01); 282 | } 283 | 284 | /**************************************************************************/ 285 | /*! 286 | @brief Ask the sensor to delete ALL models in memory 287 | @returns FINGERPRINT_OK on success 288 | @returns FINGERPRINT_BADLOCATION if the location is invalid 289 | @returns FINGERPRINT_FLASHERR if the model couldn't be written 290 | to flash memory 291 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 292 | */ 293 | uint8_t Adafruit_Fingerprint::emptyDatabase(void) { 294 | SEND_CMD_PACKET(FINGERPRINT_EMPTY); 295 | } 296 | 297 | /**************************************************************************/ 298 | /*! 299 | @brief Ask the sensor to search the current slot 1 fingerprint features to 300 | match saved templates. The matching location is stored in fingerID and 301 | the matching confidence in confidence 302 | @returns FINGERPRINT_OK on fingerprint match success 303 | @returns FINGERPRINT_NOTFOUND no match made 304 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 305 | */ 306 | /**************************************************************************/ 307 | uint8_t Adafruit_Fingerprint::fingerFastSearch(void) { 308 | // high speed search of slot #1 starting at page 0x0000 and page #0x00A3 309 | GET_CMD_PACKET(FINGERPRINT_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3); 310 | fingerID = 0xFFFF; 311 | confidence = 0xFFFF; 312 | 313 | fingerID = packet.data[1]; 314 | fingerID <<= 8; 315 | fingerID |= packet.data[2]; 316 | 317 | confidence = packet.data[3]; 318 | confidence <<= 8; 319 | confidence |= packet.data[4]; 320 | 321 | return packet.data[0]; 322 | } 323 | 324 | /**************************************************************************/ 325 | /* tested with R503 modules only */ 326 | uint16_t Adafruit_Fingerprint::led_control(uint8_t control_code, uint8_t speed, uint8_t color_idx, uint8_t times) { 327 | SEND_CMD_PACKET(FINGERPRINT_LED_CONTROL, control_code, speed, color_idx, times); 328 | 329 | return packet.data[0]; 330 | } 331 | 332 | /**************************************************************************/ 333 | /*! 334 | @brief Control the built in LED 335 | @param on True if you want LED on, False to turn LED off 336 | @returns FINGERPRINT_OK on success 337 | */ 338 | /**************************************************************************/ 339 | uint8_t Adafruit_Fingerprint::LEDcontrol(bool on) { 340 | if (on) { 341 | SEND_CMD_PACKET(FINGERPRINT_LEDON); 342 | } else { 343 | SEND_CMD_PACKET(FINGERPRINT_LEDOFF); 344 | } 345 | } 346 | 347 | /**************************************************************************/ 348 | /*! 349 | @brief Control the built in Aura LED (if exists). Check datasheet/manual 350 | for different colors and control codes available 351 | @param control The control code (e.g. breathing, full on) 352 | @param speed How fast to go through the breathing/blinking cycles 353 | @param coloridx What color to light the indicator 354 | @param count How many repeats of blinks/breathing cycles 355 | @returns FINGERPRINT_OK on fingerprint match success 356 | @returns FINGERPRINT_NOTFOUND no match made 357 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 358 | */ 359 | /**************************************************************************/ 360 | uint8_t Adafruit_Fingerprint::LEDcontrol(uint8_t control, uint8_t speed, 361 | uint8_t coloridx, uint8_t count) { 362 | SEND_CMD_PACKET(FINGERPRINT_AURALEDCONFIG, control, speed, coloridx, count); 363 | } 364 | 365 | /**************************************************************************/ 366 | /*! 367 | @brief Ask the sensor to search the current slot fingerprint features to 368 | match saved templates. The matching location is stored in fingerID and 369 | the matching confidence in confidence 370 | @param slot The slot to use for the print search, defaults to 1 371 | @returns FINGERPRINT_OK on fingerprint match success 372 | @returns FINGERPRINT_NOTFOUND no match made 373 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 374 | */ 375 | /**************************************************************************/ 376 | uint8_t Adafruit_Fingerprint::fingerSearch(uint8_t slot) { 377 | // search of slot starting thru the capacity 378 | GET_CMD_PACKET(FINGERPRINT_SEARCH, slot, 0x00, 0x00, capacity >> 8, 379 | capacity & 0xFF); 380 | 381 | fingerID = 0xFFFF; 382 | confidence = 0xFFFF; 383 | 384 | fingerID = packet.data[1]; 385 | fingerID <<= 8; 386 | fingerID |= packet.data[2]; 387 | 388 | confidence = packet.data[3]; 389 | confidence <<= 8; 390 | confidence |= packet.data[4]; 391 | 392 | return packet.data[0]; 393 | } 394 | 395 | /**************************************************************************/ 396 | /*! 397 | @brief Ask the sensor for the number of templates stored in memory. The 398 | number is stored in templateCount on success. 399 | @returns FINGERPRINT_OK on success 400 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 401 | */ 402 | /**************************************************************************/ 403 | uint8_t Adafruit_Fingerprint::getTemplateCount(void) { 404 | GET_CMD_PACKET(FINGERPRINT_TEMPLATECOUNT); 405 | 406 | templateCount = packet.data[1]; 407 | templateCount <<= 8; 408 | templateCount |= packet.data[2]; 409 | 410 | return packet.data[0]; 411 | } 412 | 413 | /**************************************************************************/ 414 | /*! 415 | @brief Set the password on the sensor (future communication will require 416 | password verification so don't forget it!!!) 417 | @param password 32-bit password code 418 | @returns FINGERPRINT_OK on success 419 | @returns FINGERPRINT_PACKETRECIEVEERR on communication error 420 | */ 421 | /**************************************************************************/ 422 | uint8_t Adafruit_Fingerprint::setPassword(uint32_t password) { 423 | SEND_CMD_PACKET(FINGERPRINT_SETPASSWORD, (password >> 24), (password >> 16), 424 | (password >> 8), password); 425 | } 426 | 427 | /**************************************************************************/ 428 | /*! 429 | @brief Helper function to process a packet and send it over UART to the 430 | sensor 431 | @param packet A structure containing the bytes to transmit 432 | */ 433 | /**************************************************************************/ 434 | 435 | void Adafruit_Fingerprint::writeStructuredPacket( 436 | const Adafruit_Fingerprint_Packet &packet) { 437 | 438 | mySerial->write((uint8_t)(packet.start_code >> 8)); 439 | mySerial->write((uint8_t)(packet.start_code & 0xFF)); 440 | mySerial->write(packet.address[0]); 441 | mySerial->write(packet.address[1]); 442 | mySerial->write(packet.address[2]); 443 | mySerial->write(packet.address[3]); 444 | mySerial->write(packet.type); 445 | 446 | uint16_t wire_length = packet.length + 2; 447 | mySerial->write((uint8_t)(wire_length >> 8)); 448 | mySerial->write((uint8_t)(wire_length & 0xFF)); 449 | 450 | #ifdef FINGERPRINT_DEBUG 451 | Serial.print("-> 0x"); 452 | Serial.print((uint8_t)(packet.start_code >> 8), HEX); 453 | Serial.print(", 0x"); 454 | Serial.print((uint8_t)(packet.start_code & 0xFF), HEX); 455 | Serial.print(", 0x"); 456 | Serial.print(packet.address[0], HEX); 457 | Serial.print(", 0x"); 458 | Serial.print(packet.address[1], HEX); 459 | Serial.print(", 0x"); 460 | Serial.print(packet.address[2], HEX); 461 | Serial.print(", 0x"); 462 | Serial.print(packet.address[3], HEX); 463 | Serial.print(", 0x"); 464 | Serial.print(packet.type, HEX); 465 | Serial.print(", 0x"); 466 | Serial.print((uint8_t)(wire_length >> 8), HEX); 467 | Serial.print(", 0x"); 468 | Serial.print((uint8_t)(wire_length & 0xFF), HEX); 469 | #endif 470 | 471 | uint16_t sum = ((wire_length) >> 8) + ((wire_length)&0xFF) + packet.type; 472 | for (uint8_t i = 0; i < packet.length; i++) { 473 | mySerial->write(packet.data[i]); 474 | sum += packet.data[i]; 475 | #ifdef FINGERPRINT_DEBUG 476 | Serial.print(", 0x"); 477 | Serial.print(packet.data[i], HEX); 478 | #endif 479 | } 480 | 481 | mySerial->write((uint8_t)(sum >> 8)); 482 | mySerial->write((uint8_t)(sum & 0xFF)); 483 | 484 | #ifdef FINGERPRINT_DEBUG 485 | Serial.print(", 0x"); 486 | Serial.print((uint8_t)(sum >> 8), HEX); 487 | Serial.print(", 0x"); 488 | Serial.println((uint8_t)(sum & 0xFF), HEX); 489 | #endif 490 | 491 | return; 492 | } 493 | 494 | /**************************************************************************/ 495 | /*! 496 | @brief Helper function to receive data over UART from the sensor and 497 | process it into a packet 498 | @param packet A structure containing the bytes received 499 | @param timeout how many milliseconds we're willing to wait 500 | @returns FINGERPRINT_OK on success 501 | @returns FINGERPRINT_TIMEOUT or 502 | FINGERPRINT_BADPACKET on failure 503 | */ 504 | /**************************************************************************/ 505 | uint8_t 506 | Adafruit_Fingerprint::getStructuredPacket(Adafruit_Fingerprint_Packet *packet, 507 | uint16_t timeout) { 508 | uint8_t byte; 509 | uint16_t idx = 0, timer = 0; 510 | 511 | #ifdef FINGERPRINT_DEBUG 512 | Serial.print("<- "); 513 | #endif 514 | 515 | while (true) { 516 | while (!mySerial->available()) { 517 | delay(1); 518 | timer++; 519 | if (timer >= timeout) { 520 | #ifdef FINGERPRINT_DEBUG 521 | Serial.println("Timed out"); 522 | #endif 523 | return FINGERPRINT_TIMEOUT; 524 | } 525 | } 526 | byte = mySerial->read(); 527 | #ifdef FINGERPRINT_DEBUG 528 | Serial.print("0x"); 529 | Serial.print(byte, HEX); 530 | Serial.print(", "); 531 | #endif 532 | switch (idx) { 533 | case 0: 534 | if (byte != (FINGERPRINT_STARTCODE >> 8)) 535 | continue; 536 | packet->start_code = (uint16_t)byte << 8; 537 | break; 538 | case 1: 539 | packet->start_code |= byte; 540 | if (packet->start_code != FINGERPRINT_STARTCODE) 541 | return FINGERPRINT_BADPACKET; 542 | break; 543 | case 2: 544 | case 3: 545 | case 4: 546 | case 5: 547 | packet->address[idx - 2] = byte; 548 | break; 549 | case 6: 550 | packet->type = byte; 551 | break; 552 | case 7: 553 | packet->length = (uint16_t)byte << 8; 554 | break; 555 | case 8: 556 | packet->length |= byte; 557 | break; 558 | default: 559 | packet->data[idx - 9] = byte; 560 | if ((idx - 8) == packet->length) { 561 | #ifdef FINGERPRINT_DEBUG 562 | Serial.println(" OK "); 563 | #endif 564 | return FINGERPRINT_OK; 565 | } 566 | break; 567 | } 568 | idx++; 569 | } 570 | // Shouldn't get here so... 571 | return FINGERPRINT_BADPACKET; 572 | } 573 | --------------------------------------------------------------------------------