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
7378OK = const (0x0 )
9297INVALIDREG = const (0x1A )
9398ADDRCODE = const (0x20 )
9499PASSVERIFY = const (0x21 )
100+ MODULEOK = const (0x55 )
95101
96102class 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,13 +143,26 @@ 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"""
130162 self ._send_packet ([_GETIMAGE ])
131163 return self ._get_packet (12 )[0 ]
132164
133- def image_2_tz (self , slot ):
165+ def image_2_tz (self , slot = 1 ):
134166 """Requests the sensor convert the image to a template, returns
135167 the packet error code or OK success"""
136168 self ._send_packet ([_IMAGE2TZ , slot ])
@@ -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 , slot = 1 ):
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 , slot , location >> 8 , location & 0xFF ])
149181 return self ._get_packet (12 )[0 ]
150182
151183 def delete_model (self , location ):
@@ -154,27 +186,92 @@ 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 , 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+
157237 def read_templates (self ):
158238 """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
162242 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
168257 return r [0 ]
169258
170259 def finger_fast_search (self ):
171260 """Asks the sensor to search for a matching fingerprint template to the
172261 last model generated. Stores the location and confidence in self.finger_id
173262 and self.confidence. Returns the packet error code or OK success"""
174263 # 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 ])
176272 r = self ._get_packet (16 )
177273 self .finger_id , self .confidence = struct .unpack ('>HH' , bytes (r [1 :5 ]))
274+ # print(r)
178275 return r [0 ]
179276
180277##################################################
@@ -201,10 +298,60 @@ def _get_packet(self, expected):
201298 if packet_type != _ACKPACKET :
202299 raise RuntimeError ('Incorrect packet data' )
203300
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+
204308 reply = [i for i in res [9 :9 + (length - 2 )]]
205309 #print(reply)
206310 return reply
207311
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+
208355 def _send_packet (self , data ):
209356 packet = [_STARTCODE >> 8 , _STARTCODE & 0xFF ]
210357 packet = packet + self .address
@@ -222,3 +369,70 @@ def _send_packet(self, data):
222369
223370 #print("Sending: ", [hex(i) for i in packet])
224371 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