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,6 +143,19 @@ 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"""
@@ -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 , charbuf ):
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 , charbuf , location >> 8 , location & 0xFF ])
149
181
return self ._get_packet (12 )[0 ]
150
182
151
183
def delete_model (self , location ):
@@ -154,6 +186,48 @@ 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 , 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
+
157
231
def empty_library (self ):
158
232
"""Requests the sensor to delete all models from flash memory.
159
233
Returns the packet error code or OK success"""
@@ -164,16 +238,17 @@ def read_templates(self):
164
238
"""Requests the sensor to list of all template locations in use and
165
239
stores them in self.templates. Returns the packet error code or OK success"""
166
240
self .templates = []
241
+ self .read_sysparam ()
167
242
temp_r = [0x0c , ]
168
- for j in range (4 ):
243
+ for j in range (int ( self . library_size / 250 ) ):
169
244
self ._send_packet ([_TEMPLATEREAD , j ])
170
245
r = self ._get_packet (44 )
171
246
if r [0 ] == OK :
172
247
for i in range (32 ):
173
248
byte = r [i + 1 ]
174
249
for bit in range (8 ):
175
250
if byte & (1 << bit ):
176
- self .templates .append (i * 8 + bit + j * 256 )
251
+ self .templates .append (( i * 8 ) + bit + ( j * 256 ) )
177
252
temp_r = r
178
253
else :
179
254
r = temp_r
@@ -185,7 +260,8 @@ def finger_fast_search(self):
185
260
and self.confidence. Returns the packet error code or OK success"""
186
261
# high speed search of slot #1 starting at page 0x0000 and page #0x00A3
187
262
#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 ])
189
265
r = self ._get_packet (16 )
190
266
self .finger_id , self .confidence = struct .unpack ('>HH' , bytes (r [1 :5 ]))
191
267
return r [0 ]
@@ -214,10 +290,61 @@ def _get_packet(self, expected):
214
290
if packet_type != _ACKPACKET :
215
291
raise RuntimeError ('Incorrect packet data' )
216
292
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
+
217
300
reply = [i for i in res [9 :9 + (length - 2 )]]
218
301
#print(reply)
219
302
return reply
220
303
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
+
221
348
def _send_packet (self , data ):
222
349
packet = [_STARTCODE >> 8 , _STARTCODE & 0xFF ]
223
350
packet = packet + self .address
@@ -235,3 +362,74 @@ def _send_packet(self, data):
235
362
236
363
#print("Sending: ", [hex(i) for i in packet])
237
364
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