62
62
_STORE = const (0x06 )
63
63
_LOAD = const (0x07 )
64
64
_UPLOAD = const (0x08 )
65
+ _DOWNLOAD = const (0x09 )
66
+ _UPLOADIMAGE = const (0x0A )
67
+ _DOWNLOADIMAGE = const (0x0B )
65
68
_DELETE = const (0x0C )
66
69
_EMPTY = const (0x0D )
70
+ _READSYSPARA = const (0x0F )
67
71
_HISPEEDSEARCH = const (0x1B )
68
72
_VERIFYPASSWORD = const (0x13 )
69
73
_TEMPLATECOUNT = const (0x1D )
70
74
_TEMPLATEREAD = const (0x1F )
75
+ _GETECHO = const (0x53 )
71
76
72
77
# Packet error code
73
78
OK = const (0x0 )
92
97
INVALIDREG = const (0x1A )
93
98
ADDRCODE = const (0x20 )
94
99
PASSVERIFY = const (0x21 )
100
+ MODULEOK = const (0x55 )
95
101
96
102
class Adafruit_Fingerprint :
97
103
"""UART based fingerprint sensor."""
@@ -103,6 +109,11 @@ class Adafruit_Fingerprint:
103
109
confidence = None
104
110
templates = []
105
111
template_count = None
112
+ library_size = None
113
+ security_level = None
114
+ device_address = None
115
+ data_packet_size = None
116
+ baudrate = None
106
117
107
118
def __init__ (self , uart , passwd = (0 , 0 , 0 , 0 )):
108
119
# Create object with UART for interface, and default 32-bit password
@@ -111,6 +122,14 @@ def __init__(self, uart, passwd=(0, 0, 0, 0)):
111
122
if self .verify_password () != OK :
112
123
raise RuntimeError ('Failed to find sensor, check wiring!' )
113
124
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
+
114
133
def verify_password (self ):
115
134
"""Checks if the password/connection is correct, returns True/False"""
116
135
self ._send_packet ([_VERIFYPASSWORD ] + list (self .password ))
@@ -124,13 +143,26 @@ def count_templates(self):
124
143
self .template_count = struct .unpack ('>H' , bytes (r [1 :3 ]))[0 ]
125
144
return r [0 ]
126
145
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
+
127
159
def get_image (self ):
128
160
"""Requests the sensor to take an image and store it memory, returns
129
161
the packet error code or OK success"""
130
162
self ._send_packet ([_GETIMAGE ])
131
163
return self ._get_packet (12 )[0 ]
132
164
133
- def image_2_tz (self , slot ):
165
+ def image_2_tz (self , slot = 1 ):
134
166
"""Requests the sensor convert the image to a template, returns
135
167
the packet error code or OK success"""
136
168
self ._send_packet ([_IMAGE2TZ , slot ])
@@ -142,10 +174,10 @@ def create_model(self):
142
174
self ._send_packet ([_REGMODEL ])
143
175
return self ._get_packet (12 )[0 ]
144
176
145
- def store_model (self , location ):
177
+ def store_model (self , location , slot = 1 ):
146
178
"""Requests the sensor store the model into flash memory and assign
147
179
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 , slot , location >> 8 , location & 0xFF ])
149
181
return self ._get_packet (12 )[0 ]
150
182
151
183
def delete_model (self , location ):
@@ -154,27 +186,92 @@ def delete_model(self, location):
154
186
self ._send_packet ([_DELETE , location >> 8 , location & 0xFF , 0x00 , 0x01 ])
155
187
return self ._get_packet (12 )[0 ]
156
188
189
+ def load_model (self , location , slot = 1 ):
190
+ """Requests the sensor to load a model from the given memory location
191
+ to the given slot. Returns the packet error code or success"""
192
+ self ._send_packet ([_LOAD , slot , location >> 8 , location & 0xFF ])
193
+ return self ._get_packet (12 )[0 ]
194
+
195
+ def get_fpdata (self , sensorbuffer = '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 = 2
201
+ if sensorbuffer == 'image' :
202
+ self ._send_packet ([_UPLOADIMAGE ])
203
+ elif sensorbuffer == 'char' :
204
+ self ._send_packet ([_UPLOAD , slot ])
205
+ else :
206
+ raise RuntimeError ('Uknown sensor 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 , sensorbuffer = 'char' , slot = 1 ):
214
+ """Requests the sensor to receive data, either a fingerprint image or
215
+ a character/template data. Data is the payload only."""
216
+ if slot != 1 or slot != 2 :
217
+ # raise error or use default value?
218
+ slot = 2
219
+ if sensorbuffer == 'image' :
220
+ self ._send_packet ([_DOWNLOADIMAGE ])
221
+ elif sensorbuffer == 'char' :
222
+ self ._send_packet ([_DOWNLOAD , slot ])
223
+ else :
224
+ raise RuntimeError ('Uknown sensor 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
+
231
+ def empty_library (self ):
232
+ """Requests the sensor to delete all models from flash memory.
233
+ Returns the packet error code or OK success"""
234
+ self ._send_packet ([_EMPTY ])
235
+ return self ._get_packet (12 )[0 ]
236
+
157
237
def read_templates (self ):
158
238
"""Requests the sensor to list of all template locations in use and
159
- stores them in self.templates. Returns the packet error code or OK success"""
160
- self . _send_packet ([ _TEMPLATEREAD , 0x00 ])
161
- r = self . _get_packet ( 44 )
239
+ stores them in self.templates. Returns the packet error code or
240
+ OK success"""
241
+ import math
162
242
self .templates = []
163
- for i in range (32 ):
164
- byte = r [i + 1 ]
165
- for bit in range (8 ):
166
- if byte & (1 << bit ):
167
- self .templates .append (i * 8 + bit )
243
+ self .read_sysparam ()
244
+ temp_r = [0x0c , ]
245
+ for j in range (math .ceil (self .library_size / 256 )):
246
+ self ._send_packet ([_TEMPLATEREAD , j ])
247
+ r = self ._get_packet (44 )
248
+ if r [0 ] == OK :
249
+ for i in range (32 ):
250
+ byte = r [i + 1 ]
251
+ for bit in range (8 ):
252
+ if byte & (1 << bit ):
253
+ self .templates .append ((i * 8 ) + bit + (j * 256 ))
254
+ temp_r = r
255
+ else :
256
+ r = temp_r
168
257
return r [0 ]
169
258
170
259
def finger_fast_search (self ):
171
260
"""Asks the sensor to search for a matching fingerprint template to the
172
261
last model generated. Stores the location and confidence in self.finger_id
173
262
and self.confidence. Returns the packet error code or OK success"""
174
263
# high speed search of slot #1 starting at page 0x0000 and page #0x00A3
175
- self ._send_packet ([_HISPEEDSEARCH , 0x01 , 0x00 , 0x00 , 0x00 , 0xA3 ])
264
+ #self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x00, 0xA3])
265
+ # or page #0x03E9 to accommodate modules with up to 1000 capacity
266
+ #self._send_packet([_HISPEEDSEARCH, 0x01, 0x00, 0x00, 0x03, 0xE9])
267
+ # or base the page on module's capacity
268
+ self .read_sysparam ()
269
+ capacity = self .library_size
270
+ self ._send_packet ([_HISPEEDSEARCH , 0x01 , 0x00 , 0x00 , capacity >> 8 ,
271
+ capacity & 0xFF ])
176
272
r = self ._get_packet (16 )
177
273
self .finger_id , self .confidence = struct .unpack ('>HH' , bytes (r [1 :5 ]))
274
+ # print(r)
178
275
return r [0 ]
179
276
180
277
##################################################
@@ -201,10 +298,60 @@ def _get_packet(self, expected):
201
298
if packet_type != _ACKPACKET :
202
299
raise RuntimeError ('Incorrect packet data' )
203
300
301
+ # we should check the checksum
302
+ # but i don't know how
303
+ # not yet anyway
304
+ #packet_sum = struct.unpack('>H', res[9+(length-2):9+length])[0]
305
+ #print(packet_sum)
306
+ #print(packet_type + length + struct.unpack('>HHHH', res[9:9+(length-2)]))
307
+
204
308
reply = [i for i in res [9 :9 + (length - 2 )]]
205
309
#print(reply)
206
310
return reply
207
311
312
+ def _get_data (self , expected ):
313
+ """ Gets packet from serial and checks structure for _DATAPACKET
314
+ and _ENDDATAPACKET. Alternate method for getting data such
315
+ as fingerprint image, etc. Returns the data payload."""
316
+ res = self ._uart .read (expected )
317
+ if (not res ) or (len (res ) != expected ):
318
+ raise RuntimeError ('Failed to read data from sensor' )
319
+
320
+ # first two bytes are start code
321
+ start = struct .unpack ('>H' , res [0 :2 ])[0 ]
322
+ # print(start)
323
+ if start != _STARTCODE :
324
+ raise RuntimeError ('Incorrect packet data' )
325
+ # next 4 bytes are address
326
+ addr = [i for i in res [2 :6 ]]
327
+ # print(addr)
328
+ if addr != self .address :
329
+ raise RuntimeError ('Incorrect address' )
330
+
331
+ packet_type , length = struct .unpack ('>BH' , res [6 :9 ])
332
+ #print(str(packet_type) + ' ' + str(length))
333
+
334
+ # todo: check checksum
335
+
336
+ if packet_type != _DATAPACKET :
337
+ if packet_type != _ENDDATAPACKET :
338
+ raise RuntimeError ('Incorrect packet data' )
339
+
340
+ if packet_type == _DATAPACKET :
341
+ res = self ._uart .read (length - 2 )
342
+ # todo: we should really inspect the headers and checksum
343
+ reply = [i for i in res [0 :length ]]
344
+ self ._uart .read (2 ) # disregard checksum but we really shouldn't
345
+ reply += self ._get_data (9 )
346
+ elif packet_type == _ENDDATAPACKET :
347
+ res = self ._uart .read (length - 2 )
348
+ # todo: we should really inspect the headers and checksum
349
+ reply = [i for i in res [0 :length ]]
350
+ self ._uart .read (2 ) # disregard checksum but we really shouldn't
351
+ # print(len(reply))
352
+ # print(reply)
353
+ return reply
354
+
208
355
def _send_packet (self , data ):
209
356
packet = [_STARTCODE >> 8 , _STARTCODE & 0xFF ]
210
357
packet = packet + self .address
@@ -222,3 +369,70 @@ def _send_packet(self, data):
222
369
223
370
#print("Sending: ", [hex(i) for i in packet])
224
371
self ._uart .write (bytearray (packet ))
372
+
373
+ def _send_data (self , data ):
374
+ print (len (data ))
375
+ self .read_sysparam ()
376
+ if self .data_packet_size == 0 :
377
+ data_length = 32
378
+ elif self .data_packet_size == 1 :
379
+ data_length = 64
380
+ elif self .data_packet_size == 2 :
381
+ data_length = 128
382
+ elif self .data_packet_size == 3 :
383
+ data_length = 256
384
+
385
+ i = 0
386
+ for i in range (int (len (data ) / (data_length - 2 ))):
387
+ start = i * (data_length - 2 )
388
+ end = (i + 1 ) * (data_length - 2 )
389
+ # print(start)
390
+ # print(end)
391
+ # print(i)
392
+
393
+ packet = [_STARTCODE >> 8 , _STARTCODE & 0xFF ]
394
+ packet = packet + self .address
395
+ packet .append (_DATAPACKET )
396
+ length = len (data [start :end ]) + 2
397
+ # print(length)
398
+ packet .append (length >> 8 )
399
+ packet .append (length & 0xFF )
400
+ checksum = _DATAPACKET + (length >> 8 ) + (length & 0xFF )
401
+
402
+ for j in range (len (data [start :end ])):
403
+ packet .append (data [j ])
404
+ checksum += data [j ]
405
+
406
+ packet .append (checksum >> 8 )
407
+ packet .append (checksum & 0xFF )
408
+
409
+ # print("Sending: ", [hex(i) for i in packet])
410
+ self ._uart .write (packet )
411
+ # print(i)
412
+
413
+ i += 1
414
+ start = i * (data_length - 2 )
415
+ end = (i + 1 ) * (data_length - 2 )
416
+ # print(start)
417
+ # print(end)
418
+ # print(i)
419
+
420
+ packet = [_STARTCODE >> 8 , _STARTCODE & 0xFF ]
421
+ packet = packet + self .address
422
+ packet .append (_ENDDATAPACKET )
423
+ length = len (data [start :end ]) + 2
424
+ # print(length)
425
+ packet .append (length >> 8 )
426
+ packet .append (length & 0xFF )
427
+ checksum = _ENDDATAPACKET + (length >> 8 ) + (length & 0xFF )
428
+
429
+ for j in range (len (data [start :end ])):
430
+ packet .append (data [j ])
431
+ checksum += data [j ]
432
+
433
+ packet .append (checksum >> 8 )
434
+ packet .append (checksum & 0xFF )
435
+
436
+ # print("Sending: ", [hex(i) for i in packet])
437
+ self ._uart .write (packet )
438
+ # print(i)
0 commit comments