Skip to content

Commit 667b492

Browse files
implemented additional functionalities
1 parent 2a94c93 commit 667b492

File tree

1 file changed

+203
-5
lines changed

1 file changed

+203
-5
lines changed

adafruit_fingerprint.py

Lines changed: 203 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,17 @@
6262
_STORE = const(0x06)
6363
_LOAD = const(0x07)
6464
_UPLOAD = const(0x08)
65+
_DOWNLOAD = const(0x09)
66+
_UPLOADIMAGE = const(0x0A)
67+
_DOWNLOADIMAGE = const(0x0B)
6568
_DELETE = const(0x0C)
6669
_EMPTY = const(0x0D)
70+
_READSYSPARA = const(0x0F)
6771
_HISPEEDSEARCH = const(0x1B)
6872
_VERIFYPASSWORD = const(0x13)
6973
_TEMPLATECOUNT = const(0x1D)
7074
_TEMPLATEREAD = const(0x1F)
75+
_GETECHO = const(0x53)
7176

7277
# Packet error code
7378
OK = const(0x0)
@@ -92,6 +97,7 @@
9297
INVALIDREG = const(0x1A)
9398
ADDRCODE = const(0x20)
9499
PASSVERIFY = const(0x21)
100+
MODULEOK = const(0x55)
95101

96102
class Adafruit_Fingerprint:
97103
"""UART based fingerprint sensor."""
@@ -103,6 +109,11 @@ class Adafruit_Fingerprint:
103109
confidence = None
104110
templates = []
105111
template_count = None
112+
library_size = None
113+
security_level = None
114+
device_address = None
115+
data_packet_size = None
116+
baudrate = None
106117

107118
def __init__(self, uart, passwd=(0, 0, 0, 0)):
108119
# Create object with UART for interface, and default 32-bit password
@@ -111,6 +122,14 @@ def __init__(self, uart, passwd=(0, 0, 0, 0)):
111122
if self.verify_password() != OK:
112123
raise RuntimeError('Failed to find sensor, check wiring!')
113124

125+
def check_module(self):
126+
"""Checks the state of the fingerprint scanner module.
127+
Returns OK or error."""
128+
self._send_packet([_GETECHO])
129+
if self._get_packet(12)[0] != MODULEOK:
130+
raise RuntimeError('Something is wrong with the sensor.')
131+
return True
132+
114133
def verify_password(self):
115134
"""Checks if the password/connection is correct, returns True/False"""
116135
self._send_packet([_VERIFYPASSWORD] + list(self.password))
@@ -124,6 +143,19 @@ def count_templates(self):
124143
self.template_count = struct.unpack('>H', bytes(r[1:3]))[0]
125144
return r[0]
126145

146+
def read_sysparam(self):
147+
"""Returns the system parameters on success via attributes."""
148+
self._send_packet([_READSYSPARA])
149+
r = self._get_packet(28)
150+
if r[0] != OK:
151+
raise RuntimeError('Command failed.')
152+
self.library_size = struct.unpack('>H', bytes(r[5:7]))[0]
153+
self.security_level = struct.unpack('>H', bytes(r[7:9]))[0]
154+
self.device_address = bytes(r[9:13])
155+
self.data_packet_size = struct.unpack('>H', bytes(r[13:15]))[0]
156+
self.baudrate = struct.unpack('>H', bytes(r[15:17]))[0]
157+
return r[0]
158+
127159
def get_image(self):
128160
"""Requests the sensor to take an image and store it memory, returns
129161
the packet error code or OK success"""
@@ -142,10 +174,10 @@ def create_model(self):
142174
self._send_packet([_REGMODEL])
143175
return self._get_packet(12)[0]
144176

145-
def store_model(self, location):
177+
def store_model(self, location, charbuf):
146178
"""Requests the sensor store the model into flash memory and assign
147179
a location. Returns the packet error code or OK success"""
148-
self._send_packet([_STORE, 1, location >> 8, location & 0xFF])
180+
self._send_packet([_STORE, charbuf, location >> 8, location & 0xFF])
149181
return self._get_packet(12)[0]
150182

151183
def delete_model(self, location):
@@ -154,6 +186,48 @@ def delete_model(self, location):
154186
self._send_packet([_DELETE, location >> 8, location & 0xFF, 0x00, 0x01])
155187
return self._get_packet(12)[0]
156188

189+
def load_model(self, location, charbuf):
190+
"""
191+
"""
192+
self._send_packet([_LOAD, charbuf, location >> 8, location & 0xFF])
193+
return self._get_packet(12)[0]
194+
195+
def get_fpdata(self, buffer='char', slot=1):
196+
"""Requests the sensor to transfer the fingerprint image or
197+
template. Returns the data payload only."""
198+
if slot != 1 or slot != 2:
199+
# raise error or use default value?
200+
slot = 1
201+
if buffer == 'image':
202+
self._send_packet([_UPLOADIMAGE])
203+
elif buffer == 'char':
204+
self._send_packet([_UPLOAD, slot])
205+
else:
206+
raise RuntimeError('Uknown buffer type')
207+
if self._get_packet(12)[0] == 0:
208+
res = self._get_data(9)
209+
#print('datasize: ' + str(len(res)))
210+
#print(res)
211+
return res
212+
213+
def send_fpdata(self, data, buffer='char', slot=1):
214+
"""ONGOING"""
215+
print(slot)
216+
if slot != 1 or slot != 2:
217+
# raise error or use default value?
218+
slot = 2
219+
if buffer == 'image':
220+
self._send_packet([_DOWNLOADIMAGE])
221+
elif buffer == 'char':
222+
self._send_packet([_DOWNLOAD, slot])
223+
else:
224+
raise RuntimeError('Uknown buffer type')
225+
if self._get_packet(12)[0] == 0:
226+
self._send_data(data)
227+
#print('datasize: ' + str(len(res)))
228+
#print(res)
229+
return True
230+
157231
def empty_library(self):
158232
"""Requests the sensor to delete all models from flash memory.
159233
Returns the packet error code or OK success"""
@@ -164,16 +238,17 @@ def read_templates(self):
164238
"""Requests the sensor to list of all template locations in use and
165239
stores them in self.templates. Returns the packet error code or OK success"""
166240
self.templates = []
241+
self.read_sysparam()
167242
temp_r = [0x0c, ]
168-
for j in range(4):
243+
for j in range(int(self.library_size/250)):
169244
self._send_packet([_TEMPLATEREAD, j])
170245
r = self._get_packet(44)
171246
if r[0] == OK:
172247
for i in range(32):
173248
byte = r[i+1]
174249
for bit in range(8):
175250
if byte & (1 << bit):
176-
self.templates.append(i * 8 + bit + j * 256)
251+
self.templates.append((i * 8) + bit + (j * 256))
177252
temp_r = r
178253
else:
179254
r = temp_r
@@ -185,7 +260,8 @@ def finger_fast_search(self):
185260
and self.confidence. Returns the packet error code or OK success"""
186261
# high speed search of slot #1 starting at page 0x0000 and page #0x00A3
187262
#self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3])
188-
self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE8])
263+
# or page #0x03E9 to accommodate modules with up to 1000 capacity
264+
self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE9])
189265
r = self._get_packet(16)
190266
self.finger_id, self.confidence = struct.unpack('>HH', bytes(r[1:5]))
191267
return r[0]
@@ -214,10 +290,61 @@ def _get_packet(self, expected):
214290
if packet_type != _ACKPACKET:
215291
raise RuntimeError('Incorrect packet data')
216292

293+
# we should check the checksum
294+
# but i don't know how
295+
# not yet anyway
296+
#packet_sum = struct.unpack('>H', res[9+(length-2):9+length])[0]
297+
#print(packet_sum)
298+
#print(packet_type + length + struct.unpack('>HHHH', res[9:9+(length-2)]))
299+
217300
reply = [i for i in res[9:9+(length-2)]]
218301
#print(reply)
219302
return reply
220303

304+
def _get_data(self, expected):
305+
""" Gets packet from serial and checks structure for _DATAPACKET
306+
and _ENDDATAPACKET. Alternate method for getting data such
307+
as fingerprint image, etc. Returns the data payload."""
308+
res = self._uart.read(expected)
309+
#print("Got", res)
310+
if (not res) or (len(res) != expected):
311+
raise RuntimeError('Failed to read data from sensor')
312+
313+
# first two bytes are start code
314+
start = struct.unpack('>H', res[0:2])[0]
315+
#print(start)
316+
if start != _STARTCODE:
317+
raise RuntimeError('Incorrect packet data')
318+
# next 4 bytes are address
319+
addr = [i for i in res[2:6]]
320+
#print(addr)
321+
if addr != self.address:
322+
raise RuntimeError('Incorrect address')
323+
324+
packet_type, length = struct.unpack('>BH', res[6:9])
325+
#print(str(packet_type) + ' ' + str(length))
326+
327+
# todo: check checksum
328+
329+
if packet_type != _DATAPACKET:
330+
if packet_type != _ENDDATAPACKET:
331+
raise RuntimeError('Incorrect packet data')
332+
333+
if packet_type == _DATAPACKET:
334+
res = self._uart.read(length-2)
335+
# todo: we should really inspect the headers and checksum
336+
reply = [i for i in res[0:length]]
337+
self._uart.read(2) # disregard checksum but we really shouldn't
338+
reply += self._get_data(9)
339+
elif packet_type == _ENDDATAPACKET:
340+
res = self._uart.read(length-2)
341+
# todo: we should really inspect the headers and checksum
342+
reply = [i for i in res[0:length]]
343+
self._uart.read(2) # disregard checksum but we really shouldn't
344+
print(len(reply))
345+
#print(reply)
346+
return reply
347+
221348
def _send_packet(self, data):
222349
packet = [_STARTCODE >> 8, _STARTCODE & 0xFF]
223350
packet = packet + self.address
@@ -235,3 +362,74 @@ def _send_packet(self, data):
235362

236363
#print("Sending: ", [hex(i) for i in packet])
237364
self._uart.write(bytearray(packet))
365+
366+
def _send_data(self, data):
367+
"""ONGOING"""
368+
print(len(data))
369+
self.read_sysparam()
370+
if self.data_packet_size == 0:
371+
data_length = 32
372+
elif self.data_packet_size == 1:
373+
data_length = 64
374+
elif self.data_packet_size == 2:
375+
data_length = 128
376+
elif self.data_packet_size == 3:
377+
data_length = 256
378+
379+
for i in range(int(len(data) / (data_length - 2))):
380+
start = i * (data_length - 2)
381+
end = (i + 1) * (data_length - 2)
382+
#print(start)
383+
#print(end)
384+
#print(i)
385+
386+
packet = [_STARTCODE >> 8, _STARTCODE & 0xFF]
387+
packet = packet + self.address
388+
packet.append(_DATAPACKET)
389+
length = len(data[start:end]) + 2
390+
#print(length)
391+
packet.append(length >> 8)
392+
packet.append(length & 0xFF)
393+
checksum = _DATAPACKET + (length >> 8) + (length & 0xFF)
394+
395+
for j in range(len(data[start:end])):
396+
packet.append(data[j])
397+
#packet.append(struct.pack('@B', data[j]))
398+
checksum += data[j]
399+
400+
packet.append(checksum >> 8)
401+
packet.append(checksum & 0xFF)
402+
403+
#print("Sending: ", [hex(i) for i in packet])
404+
#self._uart.write(bytearray(packet))
405+
self._uart.write(packet)
406+
#print(i)
407+
408+
i += 1
409+
start = i * (data_length - 2)
410+
end = (i + 1) * (data_length - 2)
411+
#print(start)
412+
#print(end)
413+
#print(i)
414+
415+
packet = [_STARTCODE >> 8, _STARTCODE & 0xFF]
416+
packet = packet + self.address
417+
packet.append(_ENDDATAPACKET)
418+
length = len(data[start:end]) + 2
419+
#print(length)
420+
packet.append(length >> 8)
421+
packet.append(length & 0xFF)
422+
checksum = _DATAPACKET + (length >> 8) + (length & 0xFF)
423+
424+
for j in range(len(data[start:end])):
425+
packet.append(data[j])
426+
#packet.append(struct.pack('@B', data[j]))
427+
checksum += data[j]
428+
429+
packet.append(checksum >> 8)
430+
packet.append(checksum & 0xFF)
431+
432+
#print("Sending: ", [hex(i) for i in packet])
433+
#self._uart.write(bytearray(packet))
434+
self._uart.write(packet)
435+
#print(i)

0 commit comments

Comments
 (0)