Skip to content

Commit 05a2c8e

Browse files
authored
Merge pull request #28 from admiralmaggie/master
Template upload/download fixes, misc improvements
2 parents 9a69885 + 4a934a9 commit 05a2c8e

File tree

2 files changed

+301
-58
lines changed

2 files changed

+301
-58
lines changed

adafruit_fingerprint.py

+99-58
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343

4444
_GETIMAGE = const(0x01)
4545
_IMAGE2TZ = const(0x02)
46+
_COMPARE = const(0x03)
4647
_FINGERPRINTSEARCH = const(0x04)
4748
_REGMODEL = const(0x05)
4849
_STORE = const(0x06)
@@ -53,11 +54,13 @@
5354
_DOWNLOADIMAGE = const(0x0B)
5455
_DELETE = const(0x0C)
5556
_EMPTY = const(0x0D)
57+
_SETSYSPARA = const(0x0E)
5658
_READSYSPARA = const(0x0F)
5759
_HISPEEDSEARCH = const(0x1B)
5860
_VERIFYPASSWORD = const(0x13)
5961
_TEMPLATECOUNT = const(0x1D)
6062
_TEMPLATEREAD = const(0x1F)
63+
_SOFTRESET = const(0x3D)
6164
_GETECHO = const(0x53)
6265
_SETAURA = const(0x35)
6366

@@ -87,9 +90,11 @@
8790
MODULEOK = const(0x55)
8891

8992
# pylint: disable=too-many-instance-attributes
93+
# pylint: disable=too-many-public-methods
9094
class Adafruit_Fingerprint:
9195
"""UART based fingerprint sensor."""
9296

97+
_debug = False
9398
_uart = None
9499

95100
password = None
@@ -112,6 +117,8 @@ def __init__(self, uart, passwd=(0, 0, 0, 0)):
112117
self._uart = uart
113118
if self.verify_password() != OK:
114119
raise RuntimeError("Failed to find sensor, check wiring!")
120+
if self.read_sysparam() != OK:
121+
raise RuntimeError("Failed to read system parameters!")
115122

116123
def check_module(self):
117124
"""Checks the state of the fingerprint scanner module.
@@ -149,6 +156,20 @@ def read_sysparam(self):
149156
self.baudrate = struct.unpack(">H", bytes(r[15:17]))[0]
150157
return r[0]
151158

159+
def set_sysparam(self, param_num, param_val):
160+
"""Set the system parameters (param_num)"""
161+
self._send_packet([_SETSYSPARA, param_num, param_val])
162+
r = self._get_packet(12)
163+
if r[0] != OK:
164+
raise RuntimeError("Command failed.")
165+
if param_num == 4:
166+
self.baudrate = param_val
167+
elif param_num == 5:
168+
self.security_level = param_val
169+
elif param_num == 6:
170+
self.data_packet_size = param_val
171+
return r[0]
172+
152173
def get_image(self):
153174
"""Requests the sensor to take an image and store it memory, returns
154175
the packet error code or OK success"""
@@ -188,7 +209,7 @@ def load_model(self, location, slot=1):
188209
def get_fpdata(self, sensorbuffer="char", slot=1):
189210
"""Requests the sensor to transfer the fingerprint image or
190211
template. Returns the data payload only."""
191-
if slot != 1 or slot != 2:
212+
if slot not in (1, 2):
192213
# raise error or use default value?
193214
slot = 2
194215
if sensorbuffer == "image":
@@ -199,14 +220,14 @@ def get_fpdata(self, sensorbuffer="char", slot=1):
199220
raise RuntimeError("Uknown sensor buffer type")
200221
if self._get_packet(12)[0] == 0:
201222
res = self._get_data(9)
202-
# print('datasize: ' + str(len(res)))
203-
# print(res)
223+
self._print_debug("get_fpdata data size:", str(len(res)))
224+
self._print_debug("get_fdata res:", res, data_type="hex")
204225
return res
205226

206227
def send_fpdata(self, data, sensorbuffer="char", slot=1):
207228
"""Requests the sensor to receive data, either a fingerprint image or
208229
a character/template data. Data is the payload only."""
209-
if slot != 1 or slot != 2:
230+
if slot not in (1, 2):
210231
# raise error or use default value?
211232
slot = 2
212233
if sensorbuffer == "image":
@@ -217,8 +238,8 @@ def send_fpdata(self, data, sensorbuffer="char", slot=1):
217238
raise RuntimeError("Uknown sensor buffer type")
218239
if self._get_packet(12)[0] == 0:
219240
self._send_data(data)
220-
# print('datasize: ' + str(len(res)))
221-
# print(res)
241+
self._print_debug("send_fpdata data size:", str(len(data)))
242+
self._print_debug("sent_fdata data:", data, data_type="hex")
222243
return True
223244

224245
def empty_library(self):
@@ -268,9 +289,13 @@ def finger_fast_search(self):
268289
)
269290
r = self._get_packet(16)
270291
self.finger_id, self.confidence = struct.unpack(">HH", bytes(r[1:5]))
271-
# print(r)
292+
self._print_debug("finger_fast_search packet:", r, data_type="hex")
272293
return r[0]
273294

295+
def close_uart(self):
296+
"""close serial port"""
297+
self._uart.close()
298+
274299
def finger_search(self):
275300
"""Asks the sensor to search for a matching fingerprint starting at
276301
slot 1. Stores the location and confidence in self.finger_id
@@ -282,7 +307,17 @@ def finger_search(self):
282307
)
283308
r = self._get_packet(16)
284309
self.finger_id, self.confidence = struct.unpack(">HH", bytes(r[1:5]))
285-
# print(r)
310+
self._print_debug("finger_search packet:", r, data_type="hex")
311+
return r[0]
312+
313+
def compare_templates(self):
314+
"""Compares two fingerprint templates in char buffers 1 and 2. Stores the confidence score
315+
in self.finger_id and self.confidence. Returns the packet error code or
316+
OK success"""
317+
self._send_packet([_COMPARE])
318+
r = self._get_packet(14)
319+
self.confidence = struct.unpack(">H", bytes(r[1:3]))
320+
self._print_debug("compare_templates confidence:", self.confidence)
286321
return r[0]
287322

288323
def set_led(self, color=1, mode=3, speed=0x80, cycles=0):
@@ -302,7 +337,7 @@ def _get_packet(self, expected):
302337
"""Helper to parse out a packet from the UART and check structure.
303338
Returns just the data payload from the packet"""
304339
res = self._uart.read(expected)
305-
# print("Got", res)
340+
self._print_debug("_get_packet received data:", res, data_type="hex")
306341
if (not res) or (len(res) != expected):
307342
raise RuntimeError("Failed to read data from sensor")
308343

@@ -328,30 +363,32 @@ def _get_packet(self, expected):
328363
# print(packet_type + length + struct.unpack('>HHHH', res[9:9+(length-2)]))
329364

330365
reply = list(i for i in res[9 : 9 + (length - 2)])
331-
# print(reply)
366+
self._print_debug("_get_packet reply:", reply, data_type="hex")
332367
return reply
333368

334369
def _get_data(self, expected):
335370
"""Gets packet from serial and checks structure for _DATAPACKET
336371
and _ENDDATAPACKET. Alternate method for getting data such
337372
as fingerprint image, etc. Returns the data payload."""
338373
res = self._uart.read(expected)
374+
self._print_debug("_get_data received data:", res, data_type="hex")
339375
if (not res) or (len(res) != expected):
340376
raise RuntimeError("Failed to read data from sensor")
341377

342378
# first two bytes are start code
343379
start = struct.unpack(">H", res[0:2])[0]
344-
# print(start)
380+
self._print_debug("_get_data received start pos:", start)
345381
if start != _STARTCODE:
346382
raise RuntimeError("Incorrect packet data")
347383
# next 4 bytes are address
348384
addr = list(i for i in res[2:6])
349-
# print(addr)
385+
self._print_debug("_get_data received address:", addr)
350386
if addr != self.address:
351387
raise RuntimeError("Incorrect address")
352388

353389
packet_type, length = struct.unpack(">BH", res[6:9])
354-
# print(str(packet_type) + ' ' + str(length))
390+
self._print_debug("_get_data received packet_type:", packet_type)
391+
self._print_debug("_get_data received length:", length)
355392

356393
# todo: check checksum
357394

@@ -363,15 +400,19 @@ def _get_data(self, expected):
363400
res = self._uart.read(length - 2)
364401
# todo: we should really inspect the headers and checksum
365402
reply = list(i for i in res[0:length])
366-
self._uart.read(2) # disregard checksum but we really shouldn't
403+
received_checksum = struct.unpack(">H", self._uart.read(2))
404+
self._print_debug("_get_data received checksum:", received_checksum)
405+
367406
reply += self._get_data(9)
368407
elif packet_type == _ENDDATAPACKET:
369408
res = self._uart.read(length - 2)
370409
# todo: we should really inspect the headers and checksum
371410
reply = list(i for i in res[0:length])
372-
self._uart.read(2) # disregard checksum but we really shouldn't
373-
# print(len(reply))
374-
# print(reply)
411+
received_checksum = struct.unpack(">H", self._uart.read(2))
412+
self._print_debug("_get_data received checksum:", received_checksum)
413+
414+
self._print_debug("_get_data reply length:", len(reply))
415+
self._print_debug("_get_data reply:", reply, data_type="hex")
375416
return reply
376417

377418
def _send_packet(self, data):
@@ -389,12 +430,14 @@ def _send_packet(self, data):
389430
packet.append(checksum >> 8)
390431
packet.append(checksum & 0xFF)
391432

392-
# print("Sending: ", [hex(i) for i in packet])
433+
self._print_debug("_send_packet length:", len(packet))
434+
self._print_debug("_send_packet data:", packet, data_type="hex")
393435
self._uart.write(bytearray(packet))
394436

395437
def _send_data(self, data):
396-
print(len(data))
397-
self.read_sysparam()
438+
self._print_debug("_send_data length:", len(data))
439+
self._print_debug("_send_data data:", data, data_type="hex")
440+
# self.read_sysparam() #moved this to init
398441
if self.data_packet_size == 0:
399442
data_length = 32
400443
elif self.data_packet_size == 1:
@@ -403,58 +446,56 @@ def _send_data(self, data):
403446
data_length = 128
404447
elif self.data_packet_size == 3:
405448
data_length = 256
406-
449+
self._print_debug("_send_data sensor data length:", data_length)
407450
i = 0
408-
for i in range(int(len(data) / (data_length - 2))):
409-
start = i * (data_length - 2)
410-
end = (i + 1) * (data_length - 2)
411-
# print(start)
412-
# print(end)
413-
# print(i)
451+
left = len(data)
452+
for i in range(int(len(data) / data_length)):
453+
start = i * data_length
454+
end = (i + 1) * data_length
455+
left = left - data_length
456+
self._print_debug("_send_data data start:", start)
457+
self._print_debug("_send_data data end:", end)
458+
self._print_debug("_send_data i:", i)
414459

415460
packet = [_STARTCODE >> 8, _STARTCODE & 0xFF]
416461
packet = packet + self.address
417-
packet.append(_DATAPACKET)
462+
463+
if left <= 0:
464+
packet.append(_ENDDATAPACKET)
465+
else:
466+
packet.append(_DATAPACKET)
467+
418468
length = len(data[start:end]) + 2
419-
# print(length)
469+
self._print_debug("_send_data length:", length)
420470
packet.append(length >> 8)
421471
packet.append(length & 0xFF)
422472
checksum = _DATAPACKET + (length >> 8) + (length & 0xFF)
423473

424-
for j in range(len(data[start:end])):
474+
# for j in range(len(data[start:end])):
475+
for j in range(start, end):
425476
packet.append(data[j])
426477
checksum += data[j]
427478

428479
packet.append(checksum >> 8)
429480
packet.append(checksum & 0xFF)
430481

431-
# print("Sending: ", [hex(i) for i in packet])
482+
self._print_debug("_send_data sending packet:", packet, data_type="hex")
432483
self._uart.write(packet)
433-
# print(i)
434-
435-
i += 1
436-
start = i * (data_length - 2)
437-
end = (i + 1) * (data_length - 2)
438-
# print(start)
439-
# print(end)
440-
# print(i)
441-
442-
packet = [_STARTCODE >> 8, _STARTCODE & 0xFF]
443-
packet = packet + self.address
444-
packet.append(_ENDDATAPACKET)
445-
length = len(data[start:end]) + 2
446-
# print(length)
447-
packet.append(length >> 8)
448-
packet.append(length & 0xFF)
449-
checksum = _ENDDATAPACKET + (length >> 8) + (length & 0xFF)
450-
451-
for j in range(len(data[start:end])):
452-
packet.append(data[j])
453-
checksum += data[j]
454-
455-
packet.append(checksum >> 8)
456-
packet.append(checksum & 0xFF)
457484

458-
# print("Sending: ", [hex(i) for i in packet])
459-
self._uart.write(packet)
460-
# print(i)
485+
def soft_reset(self):
486+
"""Performs a soft reset of the sensor"""
487+
self._send_packet([_SOFTRESET])
488+
if self._get_packet(12)[0] == OK:
489+
if self._uart.read(1)[0] != MODULEOK:
490+
raise RuntimeError("Sensor did not send a handshake signal!")
491+
492+
def _print_debug(self, info, data, data_type="str"):
493+
"""Prints debugging information. This is activated
494+
by flag _debug"""
495+
if not self._debug:
496+
return
497+
498+
if data_type == "hex":
499+
print("*** DEBUG ==>", info, ["{:02x}".format(i) for i in data])
500+
elif data_type == "str":
501+
print("*** DEBUG ==>", info, data)

0 commit comments

Comments
 (0)