From fdcaf765031fd38559789e67f3eab6e35b1c4242 Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Mon, 15 Feb 2021 16:38:08 -0500 Subject: [PATCH 1/8] additional support for template comparasion bugfixes for send/get data packet new example for template upload/download --- adafruit_fingerprint.py | 159 ++++++++++------ examples/fingerprint_template_file_compare.py | 175 ++++++++++++++++++ 2 files changed, 278 insertions(+), 56 deletions(-) create mode 100644 examples/fingerprint_template_file_compare.py diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index ff1a3dd..9e9af73 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -25,7 +25,12 @@ https://github.com/adafruit/circuitpython/releases """ -from micropython import const +try: + from micropython import const +except: + def const(x): + "Emulate making a constant" + return x try: import struct @@ -43,6 +48,7 @@ _GETIMAGE = const(0x01) _IMAGE2TZ = const(0x02) +_COMPARE = const(0x03) _FINGERPRINTSEARCH = const(0x04) _REGMODEL = const(0x05) _STORE = const(0x06) @@ -53,11 +59,13 @@ _DOWNLOADIMAGE = const(0x0B) _DELETE = const(0x0C) _EMPTY = const(0x0D) +_SETSYSPARA = const(0x0E) _READSYSPARA = const(0x0F) _HISPEEDSEARCH = const(0x1B) _VERIFYPASSWORD = const(0x13) _TEMPLATECOUNT = const(0x1D) _TEMPLATEREAD = const(0x1F) +_SOFTRESET = const(0x3D) _GETECHO = const(0x53) _SETAURA = const(0x35) @@ -90,6 +98,7 @@ class Adafruit_Fingerprint: """UART based fingerprint sensor.""" + _debug = False _uart = None password = None @@ -112,6 +121,8 @@ def __init__(self, uart, passwd=(0, 0, 0, 0)): self._uart = uart if self.verify_password() != OK: raise RuntimeError("Failed to find sensor, check wiring!") + if self.read_sysparam() != OK: + raise RuntimeError("Failed to read system parameters!") def check_module(self): """Checks the state of the fingerprint scanner module. @@ -149,6 +160,20 @@ def read_sysparam(self): self.baudrate = struct.unpack(">H", bytes(r[15:17]))[0] return r[0] + def set_sysparam(self, param_num, param_val): + """Set the system parameters (param_num)""" + self._send_packet([_SETSYSPARA, param_num, param_val]) + r = self._get_packet(12) + if r[0] != OK: + raise RuntimeError("Command failed.") + if param_num == 4: + self.baudrate = param_val + elif param_num == 5: + self.security_level = param_val + elif param_num == 6: + self.data_packet_size = param_val + 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""" @@ -188,7 +213,7 @@ def load_model(self, location, 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: + if slot != 1 and slot != 2: # raise error or use default value? slot = 2 if sensorbuffer == "image": @@ -199,14 +224,14 @@ def get_fpdata(self, sensorbuffer="char", slot=1): 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) + self._print_debug("get_fpdata data size:", str(len(res))) + self._print_debug("get_fdata res:", res, data_type="hex") return res 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: + if slot != 1 and slot != 2: # raise error or use default value? slot = 2 if sensorbuffer == "image": @@ -217,8 +242,8 @@ def send_fpdata(self, data, sensorbuffer="char", slot=1): raise RuntimeError("Uknown sensor buffer type") if self._get_packet(12)[0] == 0: self._send_data(data) - # print('datasize: ' + str(len(res))) - # print(res) + self._print_debug("send_fpdata data size:", str(len(data))) + self._print_debug("sent_fdata data:", data, data_type="hex") return True def empty_library(self): @@ -268,9 +293,14 @@ def finger_fast_search(self): ) r = self._get_packet(16) self.finger_id, self.confidence = struct.unpack(">HH", bytes(r[1:5])) - # print(r) + self._print_debug("finger_fast_search packet:", r, data_type="hex") return r[0] + def close_uart(self): + """close serial port""" + self._uart.close() + return + def finger_search(self): """Asks the sensor to search for a matching fingerprint starting at slot 1. Stores the location and confidence in self.finger_id @@ -282,7 +312,17 @@ def finger_search(self): ) r = self._get_packet(16) self.finger_id, self.confidence = struct.unpack(">HH", bytes(r[1:5])) - # print(r) + self._print_debug("finger_search packet:", r, data_type="hex") + return r[0] + + def compare_templates(self): + """Compares two fingerprint templates in char buffers 1 and 2. Stores the confidence score + in self.finger_id and self.confidence. Returns the packet error code or + OK success""" + self._send_packet( [_COMPARE] ) + r = self._get_packet(14) + self.confidence = struct.unpack(">H", bytes(r[1:3])) + self._print_debug("compare_templates confidence:", self.confidence) return r[0] def set_led(self, color=1, mode=3, speed=0x80, cycles=0): @@ -302,7 +342,7 @@ def _get_packet(self, expected): """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) + self._print_debug("_get_packet received data:", res, data_type="hex") if (not res) or (len(res) != expected): raise RuntimeError("Failed to read data from sensor") @@ -328,7 +368,7 @@ def _get_packet(self, expected): # print(packet_type + length + struct.unpack('>HHHH', res[9:9+(length-2)])) reply = list(i for i in res[9 : 9 + (length - 2)]) - # print(reply) + self._print_debug("_get_packet reply:", reply, data_type="hex") return reply def _get_data(self, expected): @@ -336,22 +376,24 @@ 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) + self._print_debug("_get_data received data:", res, data_type="hex") 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) + self._print_debug("_get_data received start pos:", start) if start != _STARTCODE: raise RuntimeError("Incorrect packet data") # next 4 bytes are address addr = list(i for i in res[2:6]) - # print(addr) + self._print_debug("_get_data received address:", addr) if addr != self.address: raise RuntimeError("Incorrect address") packet_type, length = struct.unpack(">BH", res[6:9]) - # print(str(packet_type) + ' ' + str(length)) + self._print_debug("_get_data received packet_type:", packet_type) + self._print_debug("_get_data received length:", length) # todo: check checksum @@ -363,15 +405,19 @@ def _get_data(self, expected): res = self._uart.read(length - 2) # todo: we should really inspect the headers and checksum reply = list(i for i in res[0:length]) - self._uart.read(2) # disregard checksum but we really shouldn't + received_checksum = struct.unpack(">H", self._uart.read(2)) + self._print_debug("_get_data received checksum:", received_checksum) + 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 = list(i for i in res[0:length]) - self._uart.read(2) # disregard checksum but we really shouldn't - # print(len(reply)) - # print(reply) + received_checksum = struct.unpack(">H", self._uart.read(2)) + self._print_debug("_get_data received checksum:", received_checksum) + + self._print_debug("_get_data reply length:", len(reply)) + self._print_debug("_get_data reply:", reply, data_type="hex") return reply def _send_packet(self, data): @@ -389,12 +435,14 @@ def _send_packet(self, data): packet.append(checksum >> 8) packet.append(checksum & 0xFF) - # print("Sending: ", [hex(i) for i in packet]) + self._print_debug("_send_packet length:", len(packet)) + self._print_debug("_send_packet data:", packet, data_type="hex") self._uart.write(bytearray(packet)) def _send_data(self, data): - print(len(data)) - self.read_sysparam() + self._print_debug("_send_data length:", len(data)) + self._print_debug("_send_data data:", data, data_type="hex") + #self.read_sysparam() #moved this to init if self.data_packet_size == 0: data_length = 32 elif self.data_packet_size == 1: @@ -403,58 +451,57 @@ def _send_data(self, data): data_length = 128 elif self.data_packet_size == 3: data_length = 256 - + self._print_debug("_send_data sensor data length:", data_length) i = 0 - 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) + left = len(data) + for i in range(int(len(data) / data_length)): + start = i * data_length + end = (i + 1) * data_length + left = left - data_length + self._print_debug("_send_data data start:", start) + self._print_debug("_send_data data end:", end) + self._print_debug("_send_data i:", i) packet = [_STARTCODE >> 8, _STARTCODE & 0xFF] packet = packet + self.address - packet.append(_DATAPACKET) + + if left <= 0: + packet.append(_ENDDATAPACKET) + else: + packet.append(_DATAPACKET) + length = len(data[start:end]) + 2 - # print(length) + self._print_debug("_send_data length:", length) packet.append(length >> 8) packet.append(length & 0xFF) checksum = _DATAPACKET + (length >> 8) + (length & 0xFF) - for j in range(len(data[start:end])): + #for j in range(len(data[start:end])): + for j in range(start, end): packet.append(data[j]) checksum += data[j] packet.append(checksum >> 8) packet.append(checksum & 0xFF) - # print("Sending: ", [hex(i) for i in packet]) + self._print_debug("_send_data sending packet:", packet, data_type="hex") 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 = _ENDDATAPACKET + (length >> 8) + (length & 0xFF) + def soft_reset(self): + """Performs a soft reset of the sensor""" + self._send_packet([_SOFTRESET]) + if self._get_packet(12)[0] == OK: + if self._uart.read(1)[0] != MODULEOK: + raise RuntimeError("Sensor did not send a handshake signal!") - for j in range(len(data[start:end])): - packet.append(data[j]) - checksum += data[j] + def _print_debug(self, info, data, data_type="str"): + """Prints debugging information. This is activated + by flag __debug""" + if not self._debug: + return - packet.append(checksum >> 8) - packet.append(checksum & 0xFF) + if data_type == "hex": + print("*** DEBUG ==>", info, ["{:02x}".format(i) for i in data]) + elif data_type == "str": + print("*** DEBUG ==>", info, data) - # print("Sending: ", [hex(i) for i in packet]) - self._uart.write(packet) - # print(i) diff --git a/examples/fingerprint_template_file_compare.py b/examples/fingerprint_template_file_compare.py new file mode 100644 index 0000000..e5e5540 --- /dev/null +++ b/examples/fingerprint_template_file_compare.py @@ -0,0 +1,175 @@ +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("COM6", 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-bte +# uart = serial.Serial("/dev/ttyAMA0", baudrate=57600, timeout=1) + +finger = adafruit_fingerprint.Adafruit_Fingerprint(uart) + +################################################## + + +def sensor_reset(): + """Reset sensor""" + print("Resetting sensor...") + if finger.soft_reset() != adafruit_fingerprint.OK: + print("Unable to reset sensor!") + print("Sensor is reset.") + + +# pylint: disable=too-many-branches +def fingerprint_check_file(): + """Compares a new fingerprint template to an existing template stored in a file + This is useful when templates are stored centrally (i.e. in a database)""" + print("Waiting for finger print...") + finger.set_led(color=3, mode=1) + while finger.get_image() != adafruit_fingerprint.OK: + pass + print("Templating...") + if finger.image_2_tz(1) != adafruit_fingerprint.OK: + return False + + print("Loading file template...", end="", flush=True) + with open('template0.dat', 'rb') as f: + data = f.read() + finger.send_fpdata(list(data), "char", 2) + + i = finger.compare_templates() + if i == adafruit_fingerprint.OK: + finger.set_led(color=2, speed=150, mode=6) + print("Fingerprint match template in file.") + return True + else: + if i == adafruit_fingerprint.NOMATCH: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Templates do not match!") + else: + print("Other error!") + return False + + +def enroll_save_to_file(): + """Take a 2 finger images and template it, then store it in a file""" + finger.set_led(color=3, mode=1) + 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: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Imaging error") + return False + else: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + 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: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Image too messy") + elif i == adafruit_fingerprint.FEATUREFAIL: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Could not identify features") + elif i == adafruit_fingerprint.INVALIDIMAGE: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Image invalid") + else: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Other error") + return False + + if fingerimg == 1: + print("Remove finger") + 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: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Prints did not match") + else: + finger.set_led(color=1, mode=2, speed=20, cycles=10) + print("Other error") + return False + + print("Downloading template...") + data = finger.get_fpdata("char", 1) + print(data) + with open("template0.dat", "wb") as f: + f.write(bytearray(data)) + + print("Template is saved in template0.dat file.") + + return True + + +# initialize LED color +led_color = 1 +led_mode = 3 + +finger.set_led(color=3, mode=2, speed=10, cycles=10) + +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.set_sysparam(6, 2) != adafruit_fingerprint.OK: + raise RuntimeError("Unable to set package size to 128!") + if finger.read_sysparam() != adafruit_fingerprint.OK: + raise RuntimeError("Failed to get system parameters") + print("Package size (x128):", finger.data_packet_size) + print("Size of template library: ", finger.library_size) + print("e) enroll print and save to file (template0.dat)") + print("c) compare print to file (template0.dat)") + print("r) soft reset") + print("x) quit") + print("----------------") + c = input("> ") + + if c == "x" or c == "q": + print("Exiting fingerprint example program") + # turn off LED + finger.set_led(mode=4) + raise SystemExit + elif c == "e": + enroll_save_to_file() + elif c == "c": + fingerprint_check_file() + elif c == "r": + sensor_reset() + else: + print("Invalid choice: Try again") \ No newline at end of file From d0279ee88bdddb7fa08190396390184f5a5c1624 Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Mon, 15 Feb 2021 16:59:06 -0500 Subject: [PATCH 2/8] bugfix for LED behaviour --- examples/fingerprint_template_file_compare.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/examples/fingerprint_template_file_compare.py b/examples/fingerprint_template_file_compare.py index e5e5540..de78596 100644 --- a/examples/fingerprint_template_file_compare.py +++ b/examples/fingerprint_template_file_compare.py @@ -6,7 +6,7 @@ # 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("COM6", baudrate=57600, timeout=1) +uart = serial.Serial("COM4", baudrate=57600, timeout=1) # If using with Linux/Raspberry Pi and hardware UART: # uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=1) @@ -122,10 +122,9 @@ def enroll_save_to_file(): print("Downloading template...") data = finger.get_fpdata("char", 1) - print(data) with open("template0.dat", "wb") as f: f.write(bytearray(data)) - + finger.set_led(color=2, speed=150, mode=6) print("Template is saved in template0.dat file.") return True @@ -153,8 +152,8 @@ def enroll_save_to_file(): raise RuntimeError("Failed to get system parameters") print("Package size (x128):", finger.data_packet_size) print("Size of template library: ", finger.library_size) - print("e) enroll print and save to file (template0.dat)") - print("c) compare print to file (template0.dat)") + print("e) enroll print and save to file") + print("c) compare print to file") print("r) soft reset") print("x) quit") print("----------------") From 8f89c07fcf6aee693696cb5f6e61fff867ae581d Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Tue, 16 Feb 2021 10:23:17 -0500 Subject: [PATCH 3/8] bugfix for LED calls changed import micropython code --- adafruit_fingerprint.py | 9 +--- examples/fingerprint_template_file_compare.py | 44 ++++++++++--------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 9e9af73..9f014ee 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -25,12 +25,7 @@ https://github.com/adafruit/circuitpython/releases """ -try: - from micropython import const -except: - def const(x): - "Emulate making a constant" - return x +from micropython import const try: import struct @@ -496,7 +491,7 @@ def soft_reset(self): def _print_debug(self, info, data, data_type="str"): """Prints debugging information. This is activated - by flag __debug""" + by flag _debug""" if not self._debug: return diff --git a/examples/fingerprint_template_file_compare.py b/examples/fingerprint_template_file_compare.py index de78596..30e2a5c 100644 --- a/examples/fingerprint_template_file_compare.py +++ b/examples/fingerprint_template_file_compare.py @@ -2,7 +2,7 @@ import adafruit_fingerprint -# import board +# import board (if you are using a micropython 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: @@ -32,7 +32,7 @@ def fingerprint_check_file(): """Compares a new fingerprint template to an existing template stored in a file This is useful when templates are stored centrally (i.e. in a database)""" print("Waiting for finger print...") - finger.set_led(color=3, mode=1) + set_led_local(color=3, mode=1) while finger.get_image() != adafruit_fingerprint.OK: pass print("Templating...") @@ -46,12 +46,12 @@ def fingerprint_check_file(): i = finger.compare_templates() if i == adafruit_fingerprint.OK: - finger.set_led(color=2, speed=150, mode=6) + set_led_local(color=2, speed=150, mode=6) print("Fingerprint match template in file.") return True else: if i == adafruit_fingerprint.NOMATCH: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Templates do not match!") else: print("Other error!") @@ -60,7 +60,7 @@ def fingerprint_check_file(): def enroll_save_to_file(): """Take a 2 finger images and template it, then store it in a file""" - finger.set_led(color=3, mode=1) + set_led_local(color=3, mode=1) for fingerimg in range(1, 3): if fingerimg == 1: print("Place finger on sensor...", end="", flush=True) @@ -75,11 +75,11 @@ def enroll_save_to_file(): if i == adafruit_fingerprint.NOFINGER: print(".", end="", flush=True) elif i == adafruit_fingerprint.IMAGEFAIL: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Imaging error") return False else: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Other error") return False @@ -89,16 +89,16 @@ def enroll_save_to_file(): print("Templated") else: if i == adafruit_fingerprint.IMAGEMESS: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Image too messy") elif i == adafruit_fingerprint.FEATUREFAIL: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Could not identify features") elif i == adafruit_fingerprint.INVALIDIMAGE: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Image invalid") else: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Other error") return False @@ -113,10 +113,10 @@ def enroll_save_to_file(): print("Created") else: if i == adafruit_fingerprint.ENROLLMISMATCH: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Prints did not match") else: - finger.set_led(color=1, mode=2, speed=20, cycles=10) + set_led_local(color=1, mode=2, speed=20, cycles=10) print("Other error") return False @@ -124,21 +124,23 @@ def enroll_save_to_file(): data = finger.get_fpdata("char", 1) with open("template0.dat", "wb") as f: f.write(bytearray(data)) - finger.set_led(color=2, speed=150, mode=6) + set_led_local(color=2, speed=150, mode=6) print("Template is saved in template0.dat file.") return True +def set_led_local(color=1, mode=3, speed=0x80, cycles=0): + """this is to make sure LED doesn't interfer with example + running on models without LED support - needs testing""" + try: + finger.set_led(color, mode, speed, cycles) + except: + pass -# initialize LED color -led_color = 1 -led_mode = 3 -finger.set_led(color=3, mode=2, speed=10, cycles=10) +set_led_local(color=3, mode=2, speed=10, cycles=10) 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") @@ -162,7 +164,7 @@ def enroll_save_to_file(): if c == "x" or c == "q": print("Exiting fingerprint example program") # turn off LED - finger.set_led(mode=4) + set_led_local(mode=4) raise SystemExit elif c == "e": enroll_save_to_file() From 64a78d2ecbccf433a6fc46327c0a30d1e18e408e Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Tue, 16 Feb 2021 10:24:06 -0500 Subject: [PATCH 4/8] added license info to example --- examples/fingerprint_template_file_compare.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/fingerprint_template_file_compare.py b/examples/fingerprint_template_file_compare.py index 30e2a5c..0c3f41c 100644 --- a/examples/fingerprint_template_file_compare.py +++ b/examples/fingerprint_template_file_compare.py @@ -1,3 +1,6 @@ +# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries +# SPDX-License-Identifier: MIT + import serial import adafruit_fingerprint From 90706fce8dcc264292f467a7727ff6be6c32a044 Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Tue, 16 Feb 2021 20:19:47 -0500 Subject: [PATCH 5/8] Ran pylint and black --- .pylintrc | 2 +- adafruit_fingerprint.py | 16 +++---- examples/fingerprint_template_file_compare.py | 44 ++++++++++++++----- 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/.pylintrc b/.pylintrc index 5c31f66..06d9682 100644 --- a/.pylintrc +++ b/.pylintrc @@ -208,7 +208,7 @@ redefining-builtins-modules=six.moves,future.builtins # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. # expected-line-ending-format= -expected-line-ending-format=LF +expected-line-ending-format=CRLF # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 9f014ee..9aca0eb 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -208,7 +208,7 @@ def load_model(self, location, 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 and slot != 2: + if slot not in (1, 2): # raise error or use default value? slot = 2 if sensorbuffer == "image": @@ -219,14 +219,14 @@ def get_fpdata(self, sensorbuffer="char", slot=1): raise RuntimeError("Uknown sensor buffer type") if self._get_packet(12)[0] == 0: res = self._get_data(9) - self._print_debug("get_fpdata data size:", str(len(res))) + self._print_debug("get_fpdata data size:", str(len(res))) self._print_debug("get_fdata res:", res, data_type="hex") return res 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 and slot != 2: + if slot not in (1, 2): # raise error or use default value? slot = 2 if sensorbuffer == "image": @@ -294,7 +294,6 @@ def finger_fast_search(self): def close_uart(self): """close serial port""" self._uart.close() - return def finger_search(self): """Asks the sensor to search for a matching fingerprint starting at @@ -314,7 +313,7 @@ def compare_templates(self): """Compares two fingerprint templates in char buffers 1 and 2. Stores the confidence score in self.finger_id and self.confidence. Returns the packet error code or OK success""" - self._send_packet( [_COMPARE] ) + self._send_packet([_COMPARE]) r = self._get_packet(14) self.confidence = struct.unpack(">H", bytes(r[1:3])) self._print_debug("compare_templates confidence:", self.confidence) @@ -437,7 +436,7 @@ def _send_packet(self, data): def _send_data(self, data): self._print_debug("_send_data length:", len(data)) self._print_debug("_send_data data:", data, data_type="hex") - #self.read_sysparam() #moved this to init + # self.read_sysparam() #moved this to init if self.data_packet_size == 0: data_length = 32 elif self.data_packet_size == 1: @@ -471,7 +470,7 @@ def _send_data(self, data): packet.append(length & 0xFF) checksum = _DATAPACKET + (length >> 8) + (length & 0xFF) - #for j in range(len(data[start:end])): + # for j in range(len(data[start:end])): for j in range(start, end): packet.append(data[j]) checksum += data[j] @@ -491,7 +490,7 @@ def soft_reset(self): def _print_debug(self, info, data, data_type="str"): """Prints debugging information. This is activated - by flag _debug""" + by flag _debug""" if not self._debug: return @@ -499,4 +498,3 @@ def _print_debug(self, info, data, data_type="str"): print("*** DEBUG ==>", info, ["{:02x}".format(i) for i in data]) elif data_type == "str": print("*** DEBUG ==>", info, data) - diff --git a/examples/fingerprint_template_file_compare.py b/examples/fingerprint_template_file_compare.py index 0c3f41c..a881f03 100644 --- a/examples/fingerprint_template_file_compare.py +++ b/examples/fingerprint_template_file_compare.py @@ -1,6 +1,27 @@ # SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries # SPDX-License-Identifier: MIT +""" +`fingerprint_template_file_compare.py` +==================================================== + +This is an example program to demo storing fingerprint templates in a file. It also allows +comparing a newly obtained print with one stored in the file in previous step. This is helpful +when fingerprint templates are stored centrally (not on sensor's flash memory) and shared +between multiple sensors. + +* Author(s): admiralmaggie + +Implementation Notes +-------------------- + +**Hardware:** + +* `Fingerprint sensor `_ (Product ID: 751) +* `Panel Mount Fingerprint sensor `_ (Product ID: 4651) +""" + + import serial import adafruit_fingerprint @@ -9,7 +30,7 @@ # 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("COM4", baudrate=57600, timeout=1) +uart = serial.Serial("COM6", baudrate=57600, timeout=1) # If using with Linux/Raspberry Pi and hardware UART: # uart = serial.Serial("/dev/ttyS0", baudrate=57600, timeout=1) @@ -33,7 +54,7 @@ def sensor_reset(): # pylint: disable=too-many-branches def fingerprint_check_file(): """Compares a new fingerprint template to an existing template stored in a file - This is useful when templates are stored centrally (i.e. in a database)""" + This is useful when templates are stored centrally (i.e. in a database)""" print("Waiting for finger print...") set_led_local(color=3, mode=1) while finger.get_image() != adafruit_fingerprint.OK: @@ -43,8 +64,8 @@ def fingerprint_check_file(): return False print("Loading file template...", end="", flush=True) - with open('template0.dat', 'rb') as f: - data = f.read() + with open("template0.dat", "rb") as file: + data = file.read() finger.send_fpdata(list(data), "char", 2) i = finger.compare_templates() @@ -125,20 +146,21 @@ def enroll_save_to_file(): print("Downloading template...") data = finger.get_fpdata("char", 1) - with open("template0.dat", "wb") as f: - f.write(bytearray(data)) + with open("template0.dat", "wb") as file: + file.write(bytearray(data)) set_led_local(color=2, speed=150, mode=6) print("Template is saved in template0.dat file.") return True + def set_led_local(color=1, mode=3, speed=0x80, cycles=0): """this is to make sure LED doesn't interfer with example - running on models without LED support - needs testing""" + running on models without LED support - needs testing""" try: finger.set_led(color, mode, speed, cycles) - except: - pass + except Exception as exc: + print("INFO: Sensor les not support LED!") set_led_local(color=3, mode=2, speed=10, cycles=10) @@ -164,7 +186,7 @@ def set_led_local(color=1, mode=3, speed=0x80, cycles=0): print("----------------") c = input("> ") - if c == "x" or c == "q": + if c in ("x", "q"): print("Exiting fingerprint example program") # turn off LED set_led_local(mode=4) @@ -176,4 +198,4 @@ def set_led_local(color=1, mode=3, speed=0x80, cycles=0): elif c == "r": sensor_reset() else: - print("Invalid choice: Try again") \ No newline at end of file + print("Invalid choice: Try again") From 820d9b70fb32a1ff8e3ae9563a828d617119531f Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Tue, 16 Feb 2021 20:21:57 -0500 Subject: [PATCH 6/8] Pylint LF restore --- .pylintrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pylintrc b/.pylintrc index 06d9682..5c31f66 100644 --- a/.pylintrc +++ b/.pylintrc @@ -208,7 +208,7 @@ redefining-builtins-modules=six.moves,future.builtins # Expected format of line ending, e.g. empty (any line ending), LF or CRLF. # expected-line-ending-format= -expected-line-ending-format=CRLF +expected-line-ending-format=LF # Regexp for a line that is allowed to be longer than the limit. ignore-long-lines=^\s*(# )??$ From a5897ea75fc59a2147233d10884b1f07ea1a722e Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Tue, 16 Feb 2021 20:29:01 -0500 Subject: [PATCH 7/8] More Pylint corrections... :( --- adafruit_fingerprint.py | 1 + examples/fingerprint_template_file_compare.py | 19 +++++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/adafruit_fingerprint.py b/adafruit_fingerprint.py index 9aca0eb..4e2f54f 100644 --- a/adafruit_fingerprint.py +++ b/adafruit_fingerprint.py @@ -90,6 +90,7 @@ MODULEOK = const(0x55) # pylint: disable=too-many-instance-attributes +# pylint: disable=too-many-public-methods class Adafruit_Fingerprint: """UART based fingerprint sensor.""" diff --git a/examples/fingerprint_template_file_compare.py b/examples/fingerprint_template_file_compare.py index a881f03..47b8abb 100644 --- a/examples/fingerprint_template_file_compare.py +++ b/examples/fingerprint_template_file_compare.py @@ -73,15 +73,14 @@ def fingerprint_check_file(): set_led_local(color=2, speed=150, mode=6) print("Fingerprint match template in file.") return True + if i == adafruit_fingerprint.NOMATCH: + set_led_local(color=1, mode=2, speed=20, cycles=10) + print("Templates do not match!") else: - if i == adafruit_fingerprint.NOMATCH: - set_led_local(color=1, mode=2, speed=20, cycles=10) - print("Templates do not match!") - else: - print("Other error!") - return False - + print("Other error!") + return False +# pylint: disable=too-many-statements def enroll_save_to_file(): """Take a 2 finger images and template it, then store it in a file""" set_led_local(color=3, mode=1) @@ -153,14 +152,14 @@ def enroll_save_to_file(): return True - +# pylint: disable=broad-except def set_led_local(color=1, mode=3, speed=0x80, cycles=0): """this is to make sure LED doesn't interfer with example running on models without LED support - needs testing""" try: finger.set_led(color, mode, speed, cycles) except Exception as exc: - print("INFO: Sensor les not support LED!") + print("INFO: Sensor les not support LED. Error:", str(exc)) set_led_local(color=3, mode=2, speed=10, cycles=10) @@ -191,7 +190,7 @@ def set_led_local(color=1, mode=3, speed=0x80, cycles=0): # turn off LED set_led_local(mode=4) raise SystemExit - elif c == "e": + if c == "e": enroll_save_to_file() elif c == "c": fingerprint_check_file() From 4a934a986de42cd3587fb29d92e9cf01b0315e68 Mon Sep 17 00:00:00 2001 From: "arouhi@abap.us" Date: Tue, 16 Feb 2021 20:30:06 -0500 Subject: [PATCH 8/8] More Black corrections... --- examples/fingerprint_template_file_compare.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/fingerprint_template_file_compare.py b/examples/fingerprint_template_file_compare.py index 47b8abb..191d382 100644 --- a/examples/fingerprint_template_file_compare.py +++ b/examples/fingerprint_template_file_compare.py @@ -80,6 +80,7 @@ def fingerprint_check_file(): print("Other error!") return False + # pylint: disable=too-many-statements def enroll_save_to_file(): """Take a 2 finger images and template it, then store it in a file""" @@ -152,6 +153,7 @@ def enroll_save_to_file(): return True + # pylint: disable=broad-except def set_led_local(color=1, mode=3, speed=0x80, cycles=0): """this is to make sure LED doesn't interfer with example