diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index b2f840f..ab9d85c 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -76,6 +76,7 @@ _TEMPLATECOUNT = const(0x1D) _TEMPLATEREAD = const(0x1F) _GETECHO = const(0x53) +_SETAURA = const(0x35) # Packet error code OK = const(0x0) @@ -301,10 +302,21 @@ def finger_search(self): # print(r) return r[0] + def set_led(self, color=1, mode=3, speed=0x80, cycles=0): + """LED function -- only for R503 Sensor. + Parameters: See User Manual for full details + color: 1=red, 2=blue, 3=purple + mode: 1-breathe, 2-flash, 3-on, 4-off, 5-fade_on, 6-fade-off + speed: animation speed 0-255 + cycles: numbe of time to repeat 0=infinite or 1-255 + Returns the packet error code or success""" + self._send_packet([_SETAURA, mode, speed, color, cycles]) + return self._get_packet(12)[0] + ################################################## def _get_packet(self, expected): - """ Helper to parse out a packet from the UART and check structure. + """Helper to parse out a packet from the UART and check structure. Returns just the data payload from the packet""" res = self._uart.read(expected) # print("Got", res) @@ -337,7 +349,7 @@ def _get_packet(self, expected): return reply def _get_data(self, expected): - """ Gets packet from serial and checks structure for _DATAPACKET + """Gets packet from serial and checks structure for _DATAPACKET and _ENDDATAPACKET. Alternate method for getting data such as fingerprint image, etc. Returns the data payload.""" res = self._uart.read(expected) diff --git a/examples/fingerprint_r503.py b/examples/fingerprint_r503.py new file mode 100644 index 0000000..4b180da --- /dev/null +++ b/examples/fingerprint_r503.py @@ -0,0 +1,211 @@ +import time +import board +import busio +import adafruit_fingerprint + +uart = busio.UART(board.TX, board.RX, baudrate=57600) + +# If using with a computer such as Linux/RaspberryPi, Mac, Windows with USB/serial converter: +# import serial +# uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) + +# If using with Linux/Raspberry Pi and hardware UART: +# import serial +# uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=1) + +finger = adafruit_fingerprint.Adafruit_Fingerprint(uart) + +################################################## + + +def get_fingerprint(): + """Get a finger print image, template it, and see if it matches!""" + print("Waiting for image...") + while finger.get_image() != adafruit_fingerprint.OK: + pass + print("Templating...") + if finger.image_2_tz(1) != adafruit_fingerprint.OK: + return False + print("Searching...") + if finger.finger_search() != adafruit_fingerprint.OK: + return False + return True + + +# pylint: disable=too-many-branches +def get_fingerprint_detail(): + """Get a finger print image, template it, and see if it matches! + This time, print out each error instead of just returning on failure""" + print("Getting image...", end="", flush=True) + i = finger.get_image() + if i == adafruit_fingerprint.OK: + print("Image taken") + else: + if i == adafruit_fingerprint.NOFINGER: + print("No finger detected") + elif i == adafruit_fingerprint.IMAGEFAIL: + print("Imaging error") + else: + print("Other error") + return False + + print("Templating...", end="", flush=True) + i = finger.image_2_tz(1) + if i == adafruit_fingerprint.OK: + print("Templated") + else: + if i == adafruit_fingerprint.IMAGEMESS: + print("Image too messy") + elif i == adafruit_fingerprint.FEATUREFAIL: + print("Could not identify features") + elif i == adafruit_fingerprint.INVALIDIMAGE: + print("Image invalid") + else: + print("Other error") + return False + + print("Searching...", end="", flush=True) + i = finger.finger_fast_search() + # pylint: disable=no-else-return + # This block needs to be refactored when it can be tested. + if i == adafruit_fingerprint.OK: + print("Found fingerprint!") + return True + else: + if i == adafruit_fingerprint.NOTFOUND: + print("No match found") + else: + print("Other error") + return False + + +# pylint: disable=too-many-statements +def enroll_finger(location): + """Take a 2 finger images and template it, then store in 'location'""" + for fingerimg in range(1, 3): + if fingerimg == 1: + print("Place finger on sensor...", end="", flush=True) + else: + print("Place same finger again...", end="", flush=True) + + while True: + i = finger.get_image() + if i == adafruit_fingerprint.OK: + print("Image taken") + break + if i == adafruit_fingerprint.NOFINGER: + print(".", end="", flush=True) + elif i == adafruit_fingerprint.IMAGEFAIL: + print("Imaging error") + return False + else: + print("Other error") + return False + + print("Templating...", end="", flush=True) + i = finger.image_2_tz(fingerimg) + if i == adafruit_fingerprint.OK: + print("Templated") + else: + if i == adafruit_fingerprint.IMAGEMESS: + print("Image too messy") + elif i == adafruit_fingerprint.FEATUREFAIL: + print("Could not identify features") + elif i == adafruit_fingerprint.INVALIDIMAGE: + print("Image invalid") + else: + print("Other error") + return False + + if fingerimg == 1: + print("Remove finger") + time.sleep(1) + while i != adafruit_fingerprint.NOFINGER: + i = finger.get_image() + + print("Creating model...", end="", flush=True) + i = finger.create_model() + if i == adafruit_fingerprint.OK: + print("Created") + else: + if i == adafruit_fingerprint.ENROLLMISMATCH: + print("Prints did not match") + else: + print("Other error") + return False + + print("Storing model #%d..." % location, end="", flush=True) + i = finger.store_model(location) + if i == adafruit_fingerprint.OK: + print("Stored") + else: + if i == adafruit_fingerprint.BADLOCATION: + print("Bad storage location") + elif i == adafruit_fingerprint.FLASHERR: + print("Flash storage error") + else: + print("Other error") + return False + + return True + + +################################################## + + +def get_num(): + """Use input() to get a valid number from 1 to 127. Retry till success!""" + i = 0 + while (i > 127) or (i < 1): + try: + i = int(input("Enter ID # from 1-127: ")) + except ValueError: + pass + return i + + +# initialize LED color +led_color = 1 +led_mode = 3 +while True: + # Turn on LED + finger.set_led(color=led_color, mode=led_mode) + print("----------------") + if finger.read_templates() != adafruit_fingerprint.OK: + raise RuntimeError("Failed to read templates") + print("Fingerprint templates:", finger.templates) + print("e) enroll print") + print("f) find print") + print("d) delete print") + print("l) set LED") + print("----------------") + c = input("> ") + + if c == "l": + c = input("color(r,b,p anything else=off)> ") + led_mode = 3 + if c == "r": + led_color = 1 + elif c == "b": + led_color = 2 + elif c == "p": + led_color = 3 + else: + led_color = 1 + led_mode = 4 + elif c == "e": + enroll_finger(get_num()) + elif c == "f": + # breathing LED + finger.set_led(color=3, mode=1) + if get_fingerprint(): + print("Detected #", finger.finger_id, "with confidence", finger.confidence) + else: + print("Finger not found") + elif c == "d": + if finger.delete_model(get_num()) == adafruit_fingerprint.OK: + print("Deleted!") + else: + print("Failed to delete") + else: + print("Invalid choice: Try again") diff --git a/examples/fingerprint_r503_rpi.py b/examples/fingerprint_r503_rpi.py new file mode 100644 index 0000000..f5d7b8a --- /dev/null +++ b/examples/fingerprint_r503_rpi.py @@ -0,0 +1,275 @@ +import time +import serial + +import adafruit_fingerprint + +# import board +# uart = busio.UART(board.TX, board.RX, baudrate=57600) + +# If using with a computer such as Linux/RaspberryPi, Mac, Windows with USB/serial converter: +uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) + +# If using with Linux/Raspberry Pi and hardware UART: +# uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=1) + +# If using with Linux/Raspberry Pi 3 with pi3-disable-bt +# uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) + +finger = adafruit_fingerprint.Adafruit_Fingerprint(uart) + +################################################## + + +def get_fingerprint(): + """Get a finger print image, template it, and see if it matches!""" + print("Waiting for image...") + while finger.get_image() != adafruit_fingerprint.OK: + pass + print("Templating...") + if finger.image_2_tz(1) != adafruit_fingerprint.OK: + return False + print("Searching...") + if finger.finger_search() != adafruit_fingerprint.OK: + return False + return True + + +# pylint: disable=too-many-branches +def get_fingerprint_detail(): + """Get a finger print image, template it, and see if it matches! + This time, print out each error instead of just returning on failure""" + print("Getting image...", end="", flush=True) + i = finger.get_image() + if i == adafruit_fingerprint.OK: + print("Image taken") + else: + if i == adafruit_fingerprint.NOFINGER: + print("No finger detected") + elif i == adafruit_fingerprint.IMAGEFAIL: + print("Imaging error") + else: + print("Other error") + return False + + print("Templating...", end="", flush=True) + i = finger.image_2_tz(1) + if i == adafruit_fingerprint.OK: + print("Templated") + else: + if i == adafruit_fingerprint.IMAGEMESS: + print("Image too messy") + elif i == adafruit_fingerprint.FEATUREFAIL: + print("Could not identify features") + elif i == adafruit_fingerprint.INVALIDIMAGE: + print("Image invalid") + else: + print("Other error") + return False + + print("Searching...", end="", flush=True) + i = finger.finger_fast_search() + # pylint: disable=no-else-return + # This block needs to be refactored when it can be tested. + if i == adafruit_fingerprint.OK: + print("Found fingerprint!") + return True + else: + if i == adafruit_fingerprint.NOTFOUND: + print("No match found") + else: + print("Other error") + return False + + +# pylint: disable=too-many-statements +def enroll_finger(location): + """Take a 2 finger images and template it, then store in 'location'""" + for fingerimg in range(1, 3): + if fingerimg == 1: + print("Place finger on sensor...", end="", flush=True) + else: + print("Place same finger again...", end="", flush=True) + + while True: + i = finger.get_image() + if i == adafruit_fingerprint.OK: + print("Image taken") + break + if i == adafruit_fingerprint.NOFINGER: + print(".", end="", flush=True) + elif i == adafruit_fingerprint.IMAGEFAIL: + print("Imaging error") + return False + else: + print("Other error") + return False + + print("Templating...", end="", flush=True) + i = finger.image_2_tz(fingerimg) + if i == adafruit_fingerprint.OK: + print("Templated") + else: + if i == adafruit_fingerprint.IMAGEMESS: + print("Image too messy") + elif i == adafruit_fingerprint.FEATUREFAIL: + print("Could not identify features") + elif i == adafruit_fingerprint.INVALIDIMAGE: + print("Image invalid") + else: + print("Other error") + return False + + if fingerimg == 1: + print("Remove finger") + time.sleep(1) + while i != adafruit_fingerprint.NOFINGER: + i = finger.get_image() + + print("Creating model...", end="", flush=True) + i = finger.create_model() + if i == adafruit_fingerprint.OK: + print("Created") + else: + if i == adafruit_fingerprint.ENROLLMISMATCH: + print("Prints did not match") + else: + print("Other error") + return False + + print("Storing model #%d..." % location, end="", flush=True) + i = finger.store_model(location) + if i == adafruit_fingerprint.OK: + print("Stored") + else: + if i == adafruit_fingerprint.BADLOCATION: + print("Bad storage location") + elif i == adafruit_fingerprint.FLASHERR: + print("Flash storage error") + else: + print("Other error") + return False + + return True + + +def save_fingerprint_image(filename): + """Scan fingerprint then save image to filename.""" + while finger.get_image(): + pass + + # let PIL take care of the image headers and file structure + from PIL import Image # pylint: disable=import-outside-toplevel + + img = Image.new("L", (256, 288), "white") + pixeldata = img.load() + mask = 0b00001111 + result = finger.get_fpdata(sensorbuffer="image") + + # this block "unpacks" the data received from the fingerprint + # module then copies the image data to the image placeholder "img" + # pixel by pixel. please refer to section 4.2.1 of the manual for + # more details. thanks to Bastian Raschke and Danylo Esterman. + # pylint: disable=invalid-name + x = 0 + # pylint: disable=invalid-name + y = 0 + # pylint: disable=consider-using-enumerate + for i in range(len(result)): + pixeldata[x, y] = (int(result[i]) >> 4) * 17 + x += 1 + pixeldata[x, y] = (int(result[i]) & mask) * 17 + if x == 255: + x = 0 + y += 1 + else: + x += 1 + + if not img.save(filename): + return True + return False + + +################################################## + + +def get_num(max_number): + """Use input() to get a valid number from 0 to the maximum size + of the library. Retry till success!""" + i = -1 + while (i > max_number - 1) or (i < 0): + try: + i = int(input("Enter ID # from 0-{}: ".format(max_number - 1))) + except ValueError: + pass + return i + + +# initialize LED color +led_color = 1 +led_mode = 3 +while True: + # Turn on LED + finger.set_led(color=led_color, mode=led_mode) + print("----------------") + if finger.read_templates() != adafruit_fingerprint.OK: + raise RuntimeError("Failed to read templates") + print("Fingerprint templates: ", finger.templates) + if finger.count_templates() != adafruit_fingerprint.OK: + raise RuntimeError("Failed to read templates") + print("Number of templates found: ", finger.template_count) + if finger.read_sysparam() != adafruit_fingerprint.OK: + raise RuntimeError("Failed to get system parameters") + print("Size of template library: ", finger.library_size) + print("e) enroll print") + print("f) find print") + print("d) delete print") + print("s) save fingerprint image") + print("r) reset library") + print("l) set LED") + print("q) quit") + print("----------------") + c = input("> ") + + if c == "l": + c = input("color(r,b,p anything else=off)> ") + led_mode = 3 + if c == "r": + led_color = 1 + elif c == "b": + led_color = 2 + elif c == "p": + led_color = 3 + else: + led_color = 1 + led_mode = 4 + elif c == "e": + enroll_finger(get_num(finger.library_size)) + elif c == "f": + # breathing LED + finger.set_led(color=3, mode=1) + if get_fingerprint(): + print("Detected #", finger.finger_id, "with confidence", finger.confidence) + else: + print("Finger not found") + elif c == "d": + if finger.delete_model(get_num(finger.library_size)) == adafruit_fingerprint.OK: + print("Deleted!") + else: + print("Failed to delete") + elif c == "s": + if save_fingerprint_image("fingerprint.png"): + print("Fingerprint image saved") + else: + print("Failed to save fingerprint image") + elif c == "r": + if finger.empty_library() == adafruit_fingerprint.OK: + print("Library empty!") + else: + print("Failed to empty library") + elif c == "q": + print("Exiting fingerprint example program") + # turn off LED + finger.set_led(mode=4) + raise SystemExit + else: + print("Invalid choice: Try again") diff --git a/examples/fingerprint_simpletest_rpi.py b/examples/fingerprint_simpletest_rpi.py index e41c8e1..59ce24b 100644 --- a/examples/fingerprint_simpletest_rpi.py +++ b/examples/fingerprint_simpletest_rpi.py @@ -1,27 +1,20 @@ import time import serial -import board -# import busio -from digitalio import DigitalInOut, Direction import adafruit_fingerprint -led = DigitalInOut(board.D13) -led.direction = Direction.OUTPUT +# import board # uart = busio.UART(board.TX, board.RX, baudrate=57600) # If using with a computer such as Linux/RaspberryPi, Mac, Windows with USB/serial converter: -# import serial -# uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) +uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) # If using with Linux/Raspberry Pi and hardware UART: -# import serial # uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=1) # If using with Linux/Raspberry Pi 3 with pi3-disable-bt -# import serial -uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) +# uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) finger = adafruit_fingerprint.Adafruit_Fingerprint(uart)