From b7639f9725f1883f7cb76582aa925da3db38ad04 Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 18:04:23 +0800 Subject: [PATCH 01/20] hack for other compatible fp sensors dirty hack for compatible fingerprint sensors with capacity greater than the default, since the function limits reading the templates to 162(?). an observation: each pass reads 256 templates (0-255) so for sensors with 1000 templates, 4 passes are required. but there must be a better way to do this. tested on this hardware: https://circuit-help.com.ph/product/fingerprint-sensor-2/ --- adafruit_fingerprint.py | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index f40f60b..5bd18d2 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -157,14 +157,20 @@ def delete_model(self, location): def read_templates(self): """Requests the sensor to list of all template locations in use and stores them in self.templates. Returns the packet error code or OK success""" - self._send_packet([_TEMPLATEREAD, 0x00]) - r = self._get_packet(44) self.templates = [] - for i in range(32): - byte = r[i+1] - for bit in range(8): - if byte & (1 << bit): - self.templates.append(i * 8 + bit) + r1 = [ 0x0c, ] + for j in range(4): + self._send_packet([_TEMPLATEREAD, j]) + r = self._get_packet(44) + if r[0] == OK: + for i in range(32): + byte = r[i+1] + for bit in range(8): + if byte & (1 << bit): + self.templates.append(i * 8 + bit + j * 256) + r1 = r + else: + r = r1 return r[0] def finger_fast_search(self): @@ -172,7 +178,8 @@ def finger_fast_search(self): last model generated. Stores the location and confidence in self.finger_id and self.confidence. Returns the packet error code or OK success""" # high speed search of slot #1 starting at page 0x0000 and page #0x00A3 - self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3]) + #self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3]) + self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE8]) r = self._get_packet(16) self.finger_id, self.confidence = struct.unpack('>HH', bytes(r[1:5])) return r[0] From 358c49afe1c7b64d701fc885609fb7a9632e56ea Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 18:41:15 +0800 Subject: [PATCH 02/20] added reset library functionality --- examples/fingerprint_simpletest.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/examples/fingerprint_simpletest.py b/examples/fingerprint_simpletest.py index d1fe831..f3a1d0d 100644 --- a/examples/fingerprint_simpletest.py +++ b/examples/fingerprint_simpletest.py @@ -7,11 +7,12 @@ led = DigitalInOut(board.D13) led.direction = Direction.OUTPUT -uart = busio.UART(board.TX, board.RX, baudrate=57600) +#uart = busio.UART(board.TX, board.RX, baudrate=57600) # If using with a computer such as Linux/RaspberryPi, Mac, Windows... #import serial #uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) +uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) finger = adafruit_fingerprint.Adafruit_Fingerprint(uart) @@ -152,10 +153,13 @@ def enroll_finger(location): 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): + #i = 0 + i = -1 + #while (i > 127) or (i < 1): + while (i > 999) or (i < 0): try: - i = int(input("Enter ID # from 1-127: ")) + #i = int(input("Enter ID # from 1-127: ")) + i = int(input("Enter ID # from 0-999: ")) except ValueError: pass return i @@ -166,9 +170,14 @@ def get_num(): 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: ", finger.template_count) + print("e) enroll print") print("e) enroll print") print("f) find print") print("d) delete print") + print("r) reset library") print("----------------") c = input("> ") @@ -184,3 +193,9 @@ def get_num(): print("Deleted!") else: print("Failed to delete") + if c == 'r': + finger._send_packet([adafruit_fingerprint._EMPTY]) + if finger._get_packet(12)[0] == adafruit_fingerprint.OK: + print("Library empty!") + else: + print("Failed to empty library") From 3ef239889191599c1459b0635184315fa45dd146 Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 19:03:11 +0800 Subject: [PATCH 03/20] fixed travis build failure --- adafruit_fingerprint.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 5bd18d2..9b40aa8 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -158,7 +158,7 @@ def read_templates(self): """Requests the sensor to list of all template locations in use and stores them in self.templates. Returns the packet error code or OK success""" self.templates = [] - r1 = [ 0x0c, ] + temp_r = [0x0c, ] for j in range(4): self._send_packet([_TEMPLATEREAD, j]) r = self._get_packet(44) @@ -168,9 +168,9 @@ def read_templates(self): for bit in range(8): if byte & (1 << bit): self.templates.append(i * 8 + bit + j * 256) - r1 = r + temp_r = r else: - r = r1 + r = temp_r return r[0] def finger_fast_search(self): From c874c423d759df5c848832db6c37a3d3f649690c Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 19:08:06 +0800 Subject: [PATCH 04/20] created an empty_lilbrary() function --- examples/fingerprint_simpletest.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/fingerprint_simpletest.py b/examples/fingerprint_simpletest.py index f3a1d0d..0c6b383 100644 --- a/examples/fingerprint_simpletest.py +++ b/examples/fingerprint_simpletest.py @@ -1,6 +1,6 @@ import time import board -import busio +#import busio from digitalio import DigitalInOut, Direction import adafruit_fingerprint @@ -10,7 +10,7 @@ #uart = busio.UART(board.TX, board.RX, baudrate=57600) # If using with a computer such as Linux/RaspberryPi, Mac, Windows... -#import serial +import serial #uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) @@ -194,8 +194,7 @@ def get_num(): else: print("Failed to delete") if c == 'r': - finger._send_packet([adafruit_fingerprint._EMPTY]) - if finger._get_packet(12)[0] == adafruit_fingerprint.OK: + if finger.empty_library() == adafruit_fingerprint.OK: print("Library empty!") else: print("Failed to empty library") From c17ed4138328365b8338f773c690b044bb24f741 Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 19:10:55 +0800 Subject: [PATCH 05/20] created an empty_library() function --- adafruit_fingerprint.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 9b40aa8..c3ec1a2 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -154,6 +154,13 @@ def delete_model(self, location): self._send_packet([_DELETE, location >> 8, location & 0xFF, 0x00, 0x01]) return self._get_packet(12)[0] + def empty_library(self): + """Requests the sensor to delete all models from flash memory. + Returns the packet error code or OK success""" + self._send_packet([_EMPTY]) + return self._get_packet(12)[0] + + def read_templates(self): """Requests the sensor to list of all template locations in use and stores them in self.templates. Returns the packet error code or OK success""" From 98cd938bda10dfeac2e124176387c396ca25f2f9 Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 19:15:51 +0800 Subject: [PATCH 06/20] Update adafruit_fingerprint.py --- adafruit_fingerprint.py | 1 - 1 file changed, 1 deletion(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index c3ec1a2..dfe1a9c 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -159,7 +159,6 @@ def empty_library(self): Returns the packet error code or OK success""" self._send_packet([_EMPTY]) return self._get_packet(12)[0] - def read_templates(self): """Requests the sensor to list of all template locations in use and From a04f55f8eb926338e2b7008b265ef9c7f12cebc5 Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 19:16:55 +0800 Subject: [PATCH 07/20] Update fingerprint_simpletest.py --- examples/fingerprint_simpletest.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/fingerprint_simpletest.py b/examples/fingerprint_simpletest.py index 0c6b383..7e2b688 100644 --- a/examples/fingerprint_simpletest.py +++ b/examples/fingerprint_simpletest.py @@ -1,6 +1,7 @@ import time import board #import busio +import serial from digitalio import DigitalInOut, Direction import adafruit_fingerprint @@ -10,7 +11,7 @@ #uart = busio.UART(board.TX, board.RX, baudrate=57600) # If using with a computer such as Linux/RaspberryPi, Mac, Windows... -import serial +#import serial #uart = serial.Serial("/dev/ttyUSB0", baudrate=57600, timeout=1) uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) From 2a94c93adceb8c94a306da20bdd646de3353c4ab Mon Sep 17 00:00:00 2001 From: stitchesnburns <47557392+stitchesnburns@users.noreply.github.com> Date: Tue, 12 Feb 2019 19:19:36 +0800 Subject: [PATCH 08/20] Update fingerprint_simpletest.py --- examples/fingerprint_simpletest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/fingerprint_simpletest.py b/examples/fingerprint_simpletest.py index 7e2b688..679087d 100644 --- a/examples/fingerprint_simpletest.py +++ b/examples/fingerprint_simpletest.py @@ -1,9 +1,9 @@ import time import board #import busio -import serial from digitalio import DigitalInOut, Direction import adafruit_fingerprint +import serial led = DigitalInOut(board.D13) led.direction = Direction.OUTPUT From 667b492763b06cbb250f0804a536839b782273bb Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Fri, 22 Feb 2019 17:06:18 +0800 Subject: [PATCH 09/20] implemented additional functionalities --- adafruit_fingerprint.py | 208 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 203 insertions(+), 5 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index dfe1a9c..23c0560 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -62,12 +62,17 @@ _STORE = const(0x06) _LOAD = const(0x07) _UPLOAD = const(0x08) +_DOWNLOAD = const(0x09) +_UPLOADIMAGE = const(0x0A) +_DOWNLOADIMAGE = const(0x0B) _DELETE = const(0x0C) _EMPTY = const(0x0D) +_READSYSPARA = const(0x0F) _HISPEEDSEARCH = const(0x1B) _VERIFYPASSWORD = const(0x13) _TEMPLATECOUNT = const(0x1D) _TEMPLATEREAD = const(0x1F) +_GETECHO = const(0x53) # Packet error code OK = const(0x0) @@ -92,6 +97,7 @@ INVALIDREG = const(0x1A) ADDRCODE = const(0x20) PASSVERIFY = const(0x21) +MODULEOK = const(0x55) class Adafruit_Fingerprint: """UART based fingerprint sensor.""" @@ -103,6 +109,11 @@ class Adafruit_Fingerprint: confidence = None templates = [] template_count = None + library_size = None + security_level = None + device_address = None + data_packet_size = None + baudrate = None def __init__(self, uart, passwd=(0, 0, 0, 0)): # Create object with UART for interface, and default 32-bit password @@ -111,6 +122,14 @@ def __init__(self, uart, passwd=(0, 0, 0, 0)): if self.verify_password() != OK: raise RuntimeError('Failed to find sensor, check wiring!') + def check_module(self): + """Checks the state of the fingerprint scanner module. + Returns OK or error.""" + self._send_packet([_GETECHO]) + if self._get_packet(12)[0] != MODULEOK: + raise RuntimeError('Something is wrong with the sensor.') + return True + def verify_password(self): """Checks if the password/connection is correct, returns True/False""" self._send_packet([_VERIFYPASSWORD] + list(self.password)) @@ -124,6 +143,19 @@ def count_templates(self): self.template_count = struct.unpack('>H', bytes(r[1:3]))[0] return r[0] + def read_sysparam(self): + """Returns the system parameters on success via attributes.""" + self._send_packet([_READSYSPARA]) + r = self._get_packet(28) + if r[0] != OK: + raise RuntimeError('Command failed.') + self.library_size = struct.unpack('>H', bytes(r[5:7]))[0] + self.security_level = struct.unpack('>H', bytes(r[7:9]))[0] + self.device_address = bytes(r[9:13]) + self.data_packet_size = struct.unpack('>H', bytes(r[13:15]))[0] + self.baudrate = struct.unpack('>H', bytes(r[15:17]))[0] + return r[0] + def get_image(self): """Requests the sensor to take an image and store it memory, returns the packet error code or OK success""" @@ -142,10 +174,10 @@ def create_model(self): self._send_packet([_REGMODEL]) return self._get_packet(12)[0] - def store_model(self, location): + def store_model(self, location, charbuf): """Requests the sensor store the model into flash memory and assign a location. Returns the packet error code or OK success""" - self._send_packet([_STORE, 1, location >> 8, location & 0xFF]) + self._send_packet([_STORE, charbuf, location >> 8, location & 0xFF]) return self._get_packet(12)[0] def delete_model(self, location): @@ -154,6 +186,48 @@ def delete_model(self, location): self._send_packet([_DELETE, location >> 8, location & 0xFF, 0x00, 0x01]) return self._get_packet(12)[0] + def load_model(self, location, charbuf): + """ + """ + self._send_packet([_LOAD, charbuf, location >> 8, location & 0xFF]) + return self._get_packet(12)[0] + + def get_fpdata(self, buffer='char', slot=1): + """Requests the sensor to transfer the fingerprint image or + template. Returns the data payload only.""" + if slot != 1 or slot != 2: + # raise error or use default value? + slot = 1 + if buffer == 'image': + self._send_packet([_UPLOADIMAGE]) + elif buffer == 'char': + self._send_packet([_UPLOAD, slot]) + else: + raise RuntimeError('Uknown buffer type') + if self._get_packet(12)[0] == 0: + res = self._get_data(9) + #print('datasize: ' + str(len(res))) + #print(res) + return res + + def send_fpdata(self, data, buffer='char', slot=1): + """ONGOING""" + print(slot) + if slot != 1 or slot != 2: + # raise error or use default value? + slot = 2 + if buffer == 'image': + self._send_packet([_DOWNLOADIMAGE]) + elif buffer == 'char': + self._send_packet([_DOWNLOAD, slot]) + else: + raise RuntimeError('Uknown buffer type') + if self._get_packet(12)[0] == 0: + self._send_data(data) + #print('datasize: ' + str(len(res))) + #print(res) + return True + def empty_library(self): """Requests the sensor to delete all models from flash memory. Returns the packet error code or OK success""" @@ -164,8 +238,9 @@ def read_templates(self): """Requests the sensor to list of all template locations in use and stores them in self.templates. Returns the packet error code or OK success""" self.templates = [] + self.read_sysparam() temp_r = [0x0c, ] - for j in range(4): + for j in range(int(self.library_size/250)): self._send_packet([_TEMPLATEREAD, j]) r = self._get_packet(44) if r[0] == OK: @@ -173,7 +248,7 @@ def read_templates(self): byte = r[i+1] for bit in range(8): if byte & (1 << bit): - self.templates.append(i * 8 + bit + j * 256) + self.templates.append((i * 8) + bit + (j * 256)) temp_r = r else: r = temp_r @@ -185,7 +260,8 @@ def finger_fast_search(self): and self.confidence. Returns the packet error code or OK success""" # high speed search of slot #1 starting at page 0x0000 and page #0x00A3 #self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3]) - self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE8]) + # or page #0x03E9 to accommodate modules with up to 1000 capacity + self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE9]) r = self._get_packet(16) self.finger_id, self.confidence = struct.unpack('>HH', bytes(r[1:5])) return r[0] @@ -214,10 +290,61 @@ def _get_packet(self, expected): if packet_type != _ACKPACKET: raise RuntimeError('Incorrect packet data') + # we should check the checksum + # but i don't know how + # not yet anyway + #packet_sum = struct.unpack('>H', res[9+(length-2):9+length])[0] + #print(packet_sum) + #print(packet_type + length + struct.unpack('>HHHH', res[9:9+(length-2)])) + reply = [i for i in res[9:9+(length-2)]] #print(reply) return reply + def _get_data(self, expected): + """ 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) + #print("Got", res) + if (not res) or (len(res) != expected): + raise RuntimeError('Failed to read data from sensor') + + # first two bytes are start code + start = struct.unpack('>H', res[0:2])[0] + #print(start) + if start != _STARTCODE: + raise RuntimeError('Incorrect packet data') + # next 4 bytes are address + addr = [i for i in res[2:6]] + #print(addr) + if addr != self.address: + raise RuntimeError('Incorrect address') + + packet_type, length = struct.unpack('>BH', res[6:9]) + #print(str(packet_type) + ' ' + str(length)) + + # todo: check checksum + + if packet_type != _DATAPACKET: + if packet_type != _ENDDATAPACKET: + raise RuntimeError('Incorrect packet data') + + if packet_type == _DATAPACKET: + res = self._uart.read(length-2) + # todo: we should really inspect the headers and checksum + reply = [i for i in res[0:length]] + self._uart.read(2) # disregard checksum but we really shouldn't + reply += self._get_data(9) + elif packet_type == _ENDDATAPACKET: + res = self._uart.read(length-2) + # todo: we should really inspect the headers and checksum + reply = [i for i in res[0:length]] + self._uart.read(2) # disregard checksum but we really shouldn't + print(len(reply)) + #print(reply) + return reply + def _send_packet(self, data): packet = [_STARTCODE >> 8, _STARTCODE & 0xFF] packet = packet + self.address @@ -235,3 +362,74 @@ def _send_packet(self, data): #print("Sending: ", [hex(i) for i in packet]) self._uart.write(bytearray(packet)) + + def _send_data(self, data): + """ONGOING""" + print(len(data)) + self.read_sysparam() + if self.data_packet_size == 0: + data_length = 32 + elif self.data_packet_size == 1: + data_length = 64 + elif self.data_packet_size == 2: + data_length = 128 + elif self.data_packet_size == 3: + data_length = 256 + + for i in range(int(len(data) / (data_length - 2))): + start = i * (data_length - 2) + end = (i + 1) * (data_length - 2) + #print(start) + #print(end) + #print(i) + + packet = [_STARTCODE >> 8, _STARTCODE & 0xFF] + packet = packet + self.address + packet.append(_DATAPACKET) + length = len(data[start:end]) + 2 + #print(length) + packet.append(length >> 8) + packet.append(length & 0xFF) + checksum = _DATAPACKET + (length >> 8) + (length & 0xFF) + + for j in range(len(data[start:end])): + packet.append(data[j]) + #packet.append(struct.pack('@B', data[j])) + checksum += data[j] + + packet.append(checksum >> 8) + packet.append(checksum & 0xFF) + + #print("Sending: ", [hex(i) for i in packet]) + #self._uart.write(bytearray(packet)) + self._uart.write(packet) + #print(i) + + i += 1 + start = i * (data_length - 2) + end = (i + 1) * (data_length - 2) + #print(start) + #print(end) + #print(i) + + packet = [_STARTCODE >> 8, _STARTCODE & 0xFF] + packet = packet + self.address + packet.append(_ENDDATAPACKET) + length = len(data[start:end]) + 2 + #print(length) + packet.append(length >> 8) + packet.append(length & 0xFF) + checksum = _DATAPACKET + (length >> 8) + (length & 0xFF) + + for j in range(len(data[start:end])): + packet.append(data[j]) + #packet.append(struct.pack('@B', data[j])) + checksum += data[j] + + packet.append(checksum >> 8) + packet.append(checksum & 0xFF) + + #print("Sending: ", [hex(i) for i in packet]) + #self._uart.write(bytearray(packet)) + self._uart.write(packet) + #print(i) From 4971ed218549b22b44fa7d5382de9d06d8624e69 Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Fri, 22 Feb 2019 17:20:24 +0800 Subject: [PATCH 10/20] some fixes --- adafruit_fingerprint.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 23c0560..4f8d57d 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -162,7 +162,7 @@ def get_image(self): self._send_packet([_GETIMAGE]) return self._get_packet(12)[0] - def image_2_tz(self, slot): + def image_2_tz(self, slot=1): """Requests the sensor convert the image to a template, returns the packet error code or OK success""" self._send_packet([_IMAGE2TZ, slot]) @@ -174,7 +174,7 @@ def create_model(self): self._send_packet([_REGMODEL]) return self._get_packet(12)[0] - def store_model(self, location, charbuf): + def store_model(self, location, charbuf=1): """Requests the sensor store the model into flash memory and assign a location. Returns the packet error code or OK success""" self._send_packet([_STORE, charbuf, location >> 8, location & 0xFF]) @@ -186,22 +186,23 @@ def delete_model(self, location): self._send_packet([_DELETE, location >> 8, location & 0xFF, 0x00, 0x01]) return self._get_packet(12)[0] - def load_model(self, location, charbuf): - """ + def load_model(self, location, charbuf=1): + """Requests the sensor to load a model from the given memory location + to the given charbuf. Returns the packet error code or success""" """ self._send_packet([_LOAD, charbuf, location >> 8, location & 0xFF]) return self._get_packet(12)[0] - def get_fpdata(self, buffer='char', slot=1): + def get_fpdata(self, buffer='char', charbuf=1): """Requests the sensor to transfer the fingerprint image or template. Returns the data payload only.""" - if slot != 1 or slot != 2: + if charbuf != 1 or charbuf != 2: # raise error or use default value? - slot = 1 + charbuf = 1 if buffer == 'image': self._send_packet([_UPLOADIMAGE]) elif buffer == 'char': - self._send_packet([_UPLOAD, slot]) + self._send_packet([_UPLOAD, charbuf]) else: raise RuntimeError('Uknown buffer type') if self._get_packet(12)[0] == 0: @@ -210,20 +211,19 @@ def get_fpdata(self, buffer='char', slot=1): #print(res) return res - def send_fpdata(self, data, buffer='char', slot=1): + def send_fpdata(self, data, buffer='char', charbuf=1): """ONGOING""" - print(slot) - if slot != 1 or slot != 2: + if charbuf != 1 or charbuf != 2: # raise error or use default value? - slot = 2 + charbuf = 2 if buffer == 'image': self._send_packet([_DOWNLOADIMAGE]) elif buffer == 'char': - self._send_packet([_DOWNLOAD, slot]) + self._send_packet([_DOWNLOAD, charbuf]) else: raise RuntimeError('Uknown buffer type') if self._get_packet(12)[0] == 0: - self._send_data(data) + self._send_data(data) #print('datasize: ' + str(len(res))) #print(res) return True @@ -364,7 +364,6 @@ def _send_packet(self, data): self._uart.write(bytearray(packet)) def _send_data(self, data): - """ONGOING""" print(len(data)) self.read_sysparam() if self.data_packet_size == 0: @@ -376,6 +375,7 @@ def _send_data(self, data): elif self.data_packet_size == 3: data_length = 256 + i = 0 for i in range(int(len(data) / (data_length - 2))): start = i * (data_length - 2) end = (i + 1) * (data_length - 2) From 9c4034d0accedadd771fd75a3dd9f2720156fa57 Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Fri, 22 Feb 2019 17:31:59 +0800 Subject: [PATCH 11/20] some more fixes --- adafruit_fingerprint.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 4f8d57d..fe9aecd 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -189,7 +189,6 @@ def delete_model(self, location): def load_model(self, location, charbuf=1): """Requests the sensor to load a model from the given memory location to the given charbuf. Returns the packet error code or success""" - """ self._send_packet([_LOAD, charbuf, location >> 8, location & 0xFF]) return self._get_packet(12)[0] @@ -212,7 +211,8 @@ def get_fpdata(self, buffer='char', charbuf=1): return res def send_fpdata(self, data, buffer='char', charbuf=1): - """ONGOING""" + """Requests the sensor to receive data, either a fingerprint image or + a character/template data. Data is the payload only.""" if charbuf != 1 or charbuf != 2: # raise error or use default value? charbuf = 2 From 1e343c3ce0829ed7941975e44f8d453d8cec201b Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Tue, 26 Feb 2019 11:29:51 +0800 Subject: [PATCH 12/20] finger_fast_search() based on module's capacity --- adafruit_fingerprint.py | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index fe9aecd..0ffbd52 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -174,10 +174,10 @@ def create_model(self): self._send_packet([_REGMODEL]) return self._get_packet(12)[0] - def store_model(self, location, charbuf=1): + def store_model(self, location, slot=1): """Requests the sensor store the model into flash memory and assign a location. Returns the packet error code or OK success""" - self._send_packet([_STORE, charbuf, location >> 8, location & 0xFF]) + self._send_packet([_STORE, slot, location >> 8, location & 0xFF]) return self._get_packet(12)[0] def delete_model(self, location): @@ -186,22 +186,22 @@ def delete_model(self, location): self._send_packet([_DELETE, location >> 8, location & 0xFF, 0x00, 0x01]) return self._get_packet(12)[0] - def load_model(self, location, charbuf=1): + def load_model(self, location, slot=1): """Requests the sensor to load a model from the given memory location - to the given charbuf. Returns the packet error code or success""" - self._send_packet([_LOAD, charbuf, location >> 8, location & 0xFF]) + to the given slot. Returns the packet error code or success""" + self._send_packet([_LOAD, slot, location >> 8, location & 0xFF]) return self._get_packet(12)[0] - def get_fpdata(self, buffer='char', charbuf=1): + def get_fpdata(self, buffer='char', slot=1): """Requests the sensor to transfer the fingerprint image or template. Returns the data payload only.""" - if charbuf != 1 or charbuf != 2: + if slot != 1 or slot != 2: # raise error or use default value? - charbuf = 1 + slot = 2 if buffer == 'image': self._send_packet([_UPLOADIMAGE]) elif buffer == 'char': - self._send_packet([_UPLOAD, charbuf]) + self._send_packet([_UPLOAD, slot]) else: raise RuntimeError('Uknown buffer type') if self._get_packet(12)[0] == 0: @@ -210,16 +210,16 @@ def get_fpdata(self, buffer='char', charbuf=1): #print(res) return res - def send_fpdata(self, data, buffer='char', charbuf=1): + def send_fpdata(self, data, buffer='char', slot=1): """Requests the sensor to receive data, either a fingerprint image or a character/template data. Data is the payload only.""" - if charbuf != 1 or charbuf != 2: + if slot != 1 or slot != 2: # raise error or use default value? - charbuf = 2 + slot = 2 if buffer == 'image': self._send_packet([_DOWNLOADIMAGE]) elif buffer == 'char': - self._send_packet([_DOWNLOAD, charbuf]) + self._send_packet([_DOWNLOAD, slot]) else: raise RuntimeError('Uknown buffer type') if self._get_packet(12)[0] == 0: @@ -240,7 +240,7 @@ def read_templates(self): self.templates = [] self.read_sysparam() temp_r = [0x0c, ] - for j in range(int(self.library_size/250)): + for j in range(int(self.library_size/256)): self._send_packet([_TEMPLATEREAD, j]) r = self._get_packet(44) if r[0] == OK: @@ -261,7 +261,12 @@ def finger_fast_search(self): # high speed search of slot #1 starting at page 0x0000 and page #0x00A3 #self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3]) # or page #0x03E9 to accommodate modules with up to 1000 capacity - self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE9]) + #self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE9]) + # or base the page on module's capacity + self.read_sysparam() + capacity = self.library_size + self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, capacity >> 8, + capacity & 0xFF]) r = self._get_packet(16) self.finger_id, self.confidence = struct.unpack('>HH', bytes(r[1:5])) return r[0] From ef52314dd22b35e244664158b340a37052befbe4 Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Mon, 4 Mar 2019 17:49:24 +0800 Subject: [PATCH 13/20] fixed read_templates() rounding up --- adafruit_fingerprint.py | 58 +++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 0ffbd52..0791b3f 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -206,8 +206,8 @@ def get_fpdata(self, buffer='char', slot=1): raise RuntimeError('Uknown buffer type') if self._get_packet(12)[0] == 0: res = self._get_data(9) - #print('datasize: ' + str(len(res))) - #print(res) + # print('datasize: ' + str(len(res))) + # print(res) return res def send_fpdata(self, data, buffer='char', slot=1): @@ -224,8 +224,8 @@ def send_fpdata(self, data, buffer='char', slot=1): raise RuntimeError('Uknown buffer type') if self._get_packet(12)[0] == 0: self._send_data(data) - #print('datasize: ' + str(len(res))) - #print(res) + # print('datasize: ' + str(len(res))) + # print(res) return True def empty_library(self): @@ -236,11 +236,13 @@ def empty_library(self): def read_templates(self): """Requests the sensor to list of all template locations in use and - stores them in self.templates. Returns the packet error code or OK success""" + stores them in self.templates. Returns the packet error code or + OK success""" + import math self.templates = [] self.read_sysparam() temp_r = [0x0c, ] - for j in range(int(self.library_size/256)): + for j in range(math.ceil(self.library_size/256)): self._send_packet([_TEMPLATEREAD, j]) r = self._get_packet(44) if r[0] == OK: @@ -311,18 +313,18 @@ def _get_data(self, expected): and _ENDDATAPACKET. Alternate method for getting data such as fingerprint image, etc. Returns the data payload.""" res = self._uart.read(expected) - #print("Got", res) + # print("Got", res) if (not res) or (len(res) != expected): raise RuntimeError('Failed to read data from sensor') # first two bytes are start code start = struct.unpack('>H', res[0:2])[0] - #print(start) + # print(start) if start != _STARTCODE: raise RuntimeError('Incorrect packet data') # next 4 bytes are address addr = [i for i in res[2:6]] - #print(addr) + # print(addr) if addr != self.address: raise RuntimeError('Incorrect address') @@ -339,15 +341,15 @@ def _get_data(self, expected): res = self._uart.read(length-2) # todo: we should really inspect the headers and checksum reply = [i for i in res[0:length]] - self._uart.read(2) # disregard checksum but we really shouldn't + self._uart.read(2) # disregard checksum but we really shouldn't reply += self._get_data(9) elif packet_type == _ENDDATAPACKET: res = self._uart.read(length-2) # todo: we should really inspect the headers and checksum reply = [i for i in res[0:length]] - self._uart.read(2) # disregard checksum but we really shouldn't + self._uart.read(2) # disregard checksum but we really shouldn't print(len(reply)) - #print(reply) + # print(reply) return reply def _send_packet(self, data): @@ -384,57 +386,57 @@ def _send_data(self, data): for i in range(int(len(data) / (data_length - 2))): start = i * (data_length - 2) end = (i + 1) * (data_length - 2) - #print(start) - #print(end) - #print(i) + # print(start) + # print(end) + # print(i) packet = [_STARTCODE >> 8, _STARTCODE & 0xFF] packet = packet + self.address packet.append(_DATAPACKET) length = len(data[start:end]) + 2 - #print(length) + # print(length) packet.append(length >> 8) packet.append(length & 0xFF) checksum = _DATAPACKET + (length >> 8) + (length & 0xFF) for j in range(len(data[start:end])): packet.append(data[j]) - #packet.append(struct.pack('@B', data[j])) + # packet.append(struct.pack('@B', data[j])) checksum += data[j] packet.append(checksum >> 8) packet.append(checksum & 0xFF) - #print("Sending: ", [hex(i) for i in packet]) - #self._uart.write(bytearray(packet)) + # print("Sending: ", [hex(i) for i in packet]) + # self._uart.write(bytearray(packet)) self._uart.write(packet) - #print(i) + # print(i) i += 1 start = i * (data_length - 2) end = (i + 1) * (data_length - 2) - #print(start) - #print(end) - #print(i) + # print(start) + # print(end) + # print(i) packet = [_STARTCODE >> 8, _STARTCODE & 0xFF] packet = packet + self.address packet.append(_ENDDATAPACKET) length = len(data[start:end]) + 2 - #print(length) + # print(length) packet.append(length >> 8) packet.append(length & 0xFF) checksum = _DATAPACKET + (length >> 8) + (length & 0xFF) for j in range(len(data[start:end])): packet.append(data[j]) - #packet.append(struct.pack('@B', data[j])) + # packet.append(struct.pack('@B', data[j])) checksum += data[j] packet.append(checksum >> 8) packet.append(checksum & 0xFF) - #print("Sending: ", [hex(i) for i in packet]) - #self._uart.write(bytearray(packet)) + # print("Sending: ", [hex(i) for i in packet]) + # self._uart.write(bytearray(packet)) self._uart.write(packet) - #print(i) + # print(i) From 9513b83ff44fe1df11b6df1b1542f1ea0e3bef4a Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Tue, 5 Mar 2019 18:50:47 +0800 Subject: [PATCH 14/20] changed 'buffer' variable to 'sensorbuffer' --- adafruit_fingerprint.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 0791b3f..802082f 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -192,36 +192,36 @@ def load_model(self, location, slot=1): self._send_packet([_LOAD, slot, location >> 8, location & 0xFF]) return self._get_packet(12)[0] - def get_fpdata(self, buffer='char', slot=1): + def get_fpdata(self, sensorbuffer='char', slot=1): """Requests the sensor to transfer the fingerprint image or template. Returns the data payload only.""" if slot != 1 or slot != 2: # raise error or use default value? slot = 2 - if buffer == 'image': + if sensorbuffer == 'image': self._send_packet([_UPLOADIMAGE]) - elif buffer == 'char': + elif sensorbuffer == 'char': self._send_packet([_UPLOAD, slot]) else: - raise RuntimeError('Uknown buffer type') + raise RuntimeError('Uknown sensor buffer type') if self._get_packet(12)[0] == 0: res = self._get_data(9) # print('datasize: ' + str(len(res))) # print(res) return res - def send_fpdata(self, data, buffer='char', slot=1): + def send_fpdata(self, data, sensorbuffer='char', slot=1): """Requests the sensor to receive data, either a fingerprint image or a character/template data. Data is the payload only.""" if slot != 1 or slot != 2: # raise error or use default value? slot = 2 - if buffer == 'image': + if sensorbuffer == 'image': self._send_packet([_DOWNLOADIMAGE]) - elif buffer == 'char': + elif sensorbuffer == 'char': self._send_packet([_DOWNLOAD, slot]) else: - raise RuntimeError('Uknown buffer type') + raise RuntimeError('Uknown sensor buffer type') if self._get_packet(12)[0] == 0: self._send_data(data) # print('datasize: ' + str(len(res))) From d117944af69c1cf15c69aa300402e96e75eb4fb2 Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Fri, 15 Mar 2019 14:55:31 +0800 Subject: [PATCH 15/20] fixed bug when sending last packet of data to fp sensor --- adafruit_fingerprint.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 802082f..b547ccb 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -426,7 +426,7 @@ def _send_data(self, data): # print(length) packet.append(length >> 8) packet.append(length & 0xFF) - checksum = _DATAPACKET + (length >> 8) + (length & 0xFF) + checksum = _ENDDATAPACKET + (length >> 8) + (length & 0xFF) for j in range(len(data[start:end])): packet.append(data[j]) From 8291727c3af0ab973968bf2dc5938e28301e2893 Mon Sep 17 00:00:00 2001 From: Emmanuel Balintec Date: Wed, 20 Mar 2019 09:19:40 +0800 Subject: [PATCH 16/20] code clean up --- adafruit_fingerprint.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index b547ccb..ee07119 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -271,6 +271,7 @@ def finger_fast_search(self): capacity & 0xFF]) r = self._get_packet(16) self.finger_id, self.confidence = struct.unpack('>HH', bytes(r[1:5])) + # print(r) return r[0] ################################################## @@ -313,7 +314,6 @@ def _get_data(self, expected): and _ENDDATAPACKET. Alternate method for getting data such as fingerprint image, etc. Returns the data payload.""" res = self._uart.read(expected) - # print("Got", res) if (not res) or (len(res) != expected): raise RuntimeError('Failed to read data from sensor') @@ -348,7 +348,7 @@ def _get_data(self, expected): # todo: we should really inspect the headers and checksum reply = [i for i in res[0:length]] self._uart.read(2) # disregard checksum but we really shouldn't - print(len(reply)) + # print(len(reply)) # print(reply) return reply @@ -401,14 +401,12 @@ def _send_data(self, data): for j in range(len(data[start:end])): packet.append(data[j]) - # packet.append(struct.pack('@B', data[j])) checksum += data[j] packet.append(checksum >> 8) packet.append(checksum & 0xFF) # print("Sending: ", [hex(i) for i in packet]) - # self._uart.write(bytearray(packet)) self._uart.write(packet) # print(i) @@ -430,13 +428,11 @@ def _send_data(self, data): for j in range(len(data[start:end])): packet.append(data[j]) - # packet.append(struct.pack('@B', data[j])) checksum += data[j] packet.append(checksum >> 8) packet.append(checksum & 0xFF) # print("Sending: ", [hex(i) for i in packet]) - # self._uart.write(bytearray(packet)) self._uart.write(packet) # print(i) From 263b43558fea3bcde1d8fd5eb0a03dd038acd2b9 Mon Sep 17 00:00:00 2001 From: stitchesnburns Date: Thu, 9 Jan 2020 17:24:39 +0800 Subject: [PATCH 17/20] Reverted default example --- examples/fingerprint_simpletest.py | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/examples/fingerprint_simpletest.py b/examples/fingerprint_simpletest.py index afaec94..9b597b3 100644 --- a/examples/fingerprint_simpletest.py +++ b/examples/fingerprint_simpletest.py @@ -1,19 +1,17 @@ import time import board -#import busio +import busio from digitalio import DigitalInOut, Direction import adafruit_fingerprint -import serial led = DigitalInOut(board.D13) led.direction = Direction.OUTPUT -#uart = busio.UART(board.TX, board.RX, baudrate=57600) +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/ttyAMA0", baudrate=57600, timeout=1) # If using with Linux/Raspberry Pi and hardware UART: #import serial @@ -158,13 +156,10 @@ def enroll_finger(location): def get_num(): """Use input() to get a valid number from 1 to 127. Retry till success!""" - #i = 0 - i = -1 - #while (i > 127) or (i < 1): - while (i > 999) or (i < 0): + i = 0 + while (i > 127) or (i < 1): try: - #i = int(input("Enter ID # from 1-127: ")) - i = int(input("Enter ID # from 0-999: ")) + i = int(input("Enter ID # from 1-127: ")) except ValueError: pass return i @@ -175,14 +170,9 @@ def get_num(): 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: ", finger.template_count) - print("e) enroll print") print("e) enroll print") print("f) find print") print("d) delete print") - print("r) reset library") print("----------------") c = input("> ") @@ -198,8 +188,3 @@ def get_num(): print("Deleted!") else: print("Failed to delete") - if c == 'r': - if finger.empty_library() == adafruit_fingerprint.OK: - print("Library empty!") - else: - print("Failed to empty library") From a03e236a0330a44aa1e76a31bf7a1eb5ccceb555 Mon Sep 17 00:00:00 2001 From: stitchesnburns Date: Thu, 9 Jan 2020 17:29:22 +0800 Subject: [PATCH 18/20] Added another example based on the default one --- examples/fingerprint_simpletest_rpi.py | 207 +++++++++++++++++++++++++ 1 file changed, 207 insertions(+) create mode 100644 examples/fingerprint_simpletest_rpi.py diff --git a/examples/fingerprint_simpletest_rpi.py b/examples/fingerprint_simpletest_rpi.py new file mode 100644 index 0000000..d698b97 --- /dev/null +++ b/examples/fingerprint_simpletest_rpi.py @@ -0,0 +1,207 @@ +import time +import board +import busio +from digitalio import DigitalInOut, Direction +import adafruit_fingerprint + +led = DigitalInOut(board.D13) +led.direction = Direction.OUTPUT + +#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) + +# If using with Linux/Raspberry Pi 3 with pi3-disable-bt +import serial +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_fast_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 + elif 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(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 + + +while True: + 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("r) reset library") + print("----------------") + c = input("> ") + + if c == 'e': + enroll_finger(get_num(finger.library_size)) + if c == 'f': + if get_fingerprint(): + print("Detected #", finger.finger_id, "with confidence", finger.confidence) + else: + print("Finger not found") + if c == 'd': + if finger.delete_model(get_num(finger.library_size)) == adafruit_fingerprint.OK: + print("Deleted!") + else: + print("Failed to delete") + if c == 'r': + if finger.empty_library() == adafruit_fingerprint.OK: + print("Library empty!") + else: + print("Failed to empty library") From 0e3ac3c60efeea19b67fe2f2f81cd67bb1a74c63 Mon Sep 17 00:00:00 2001 From: stitchesnburns Date: Thu, 9 Jan 2020 17:44:12 +0800 Subject: [PATCH 19/20] updated to comply with pylint --- examples/fingerprint_simpletest_rpi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/fingerprint_simpletest_rpi.py b/examples/fingerprint_simpletest_rpi.py index d698b97..9196d96 100644 --- a/examples/fingerprint_simpletest_rpi.py +++ b/examples/fingerprint_simpletest_rpi.py @@ -1,6 +1,7 @@ import time import board -import busio +#import busio +import serial from digitalio import DigitalInOut, Direction import adafruit_fingerprint @@ -18,7 +19,7 @@ #uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=1) # If using with Linux/Raspberry Pi 3 with pi3-disable-bt -import serial +#import serial uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) finger = adafruit_fingerprint.Adafruit_Fingerprint(uart) From ff628d14f478a2bfec3b88e3de6967ad711ba3b5 Mon Sep 17 00:00:00 2001 From: stitchesnburns Date: Tue, 14 Jan 2020 11:11:50 +0800 Subject: [PATCH 20/20] expanded the example to include saving fingerprint image --- examples/fingerprint_simpletest_rpi.py | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/examples/fingerprint_simpletest_rpi.py b/examples/fingerprint_simpletest_rpi.py index 9196d96..6d5ff6b 100644 --- a/examples/fingerprint_simpletest_rpi.py +++ b/examples/fingerprint_simpletest_rpi.py @@ -156,6 +156,41 @@ def enroll_finger(location): 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 + 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 + ################################################## @@ -185,7 +220,9 @@ def get_num(max_number): print("e) enroll print") print("f) find print") print("d) delete print") + print("s) save fingerprint image") print("r) reset library") + print("q) quit") print("----------------") c = input("> ") @@ -201,8 +238,16 @@ def get_num(max_number): print("Deleted!") else: print("Failed to delete") + if c == 's': + if save_fingerprint_image("fingerprint.png"): + print("Fingerprint image saved") + else: + print("Failed to save fingerprint image") if c == 'r': if finger.empty_library() == adafruit_fingerprint.OK: print("Library empty!") else: print("Failed to empty library") + if c == 'q': + print("Exiting fingerprint example program") + raise SystemExit