From 7e956c1fccce7b8c878c0ce7149e54033d6237d6 Mon Sep 17 00:00:00 2001 From: "kilian (dks-laptop)" Date: Sun, 10 Nov 2019 08:26:26 +0100 Subject: [PATCH] tools fingerprint --- CGI/api/fingerprint.cgi | 109 ++ CGI/api/tools/fingerdelete.py | 46 + CGI/api/tools/fingerenroll.py | 79 + CGI/api/tools/fingerledoff.py | 27 + CGI/api/tools/fingerledon.py | 27 + CGI/api/tools/fingersearch.py | 69 + CGI/api/tools/pyfingerprint2/__init__.py | 11 + .../pyfingerprint2/pyfingerprint.orig.py | 1326 ++++++++++++++++ CGI/api/tools/pyfingerprint2/pyfingerprint.py | 1358 +++++++++++++++++ syncdb.pl | 156 +- 10 files changed, 3100 insertions(+), 108 deletions(-) create mode 100644 CGI/api/fingerprint.cgi create mode 100644 CGI/api/tools/fingerdelete.py create mode 100644 CGI/api/tools/fingerenroll.py create mode 100644 CGI/api/tools/fingerledoff.py create mode 100644 CGI/api/tools/fingerledon.py create mode 100644 CGI/api/tools/fingersearch.py create mode 100644 CGI/api/tools/pyfingerprint2/__init__.py create mode 100644 CGI/api/tools/pyfingerprint2/pyfingerprint.orig.py create mode 100644 CGI/api/tools/pyfingerprint2/pyfingerprint.py diff --git a/CGI/api/fingerprint.cgi b/CGI/api/fingerprint.cgi new file mode 100644 index 0000000..76c2d3f --- /dev/null +++ b/CGI/api/fingerprint.cgi @@ -0,0 +1,109 @@ +#!/Users/kilian/perl5/perlbrew/perls/perl-5.24.1/bin/perl +use strict; +use FindBin qw($Bin); +# use lib ('CGI/api/lib/perl5'); +# use lib ('CGI/api/lib'); +use lib ($Bin.'/CGI/api/lib/perl5'); +use lib ($Bin.'/CGI/api/lib'); +use CGI; +use CGI::Cookie; +# use CGI::Carp qw/fatalsToBrowser/; +use File::Basename; +use JSON::PP; + +use dksconfig qw/$sitecfg/; +use dksdb; +my $cgi = new CGI(); +my $scriptpath = $cgi->url(-absolute => 1); +my $p = (); +my @params = $cgi->param(); +foreach my $pe (@params){ + $p->{$pe} = $cgi->param($pe); +} +my $html->{result} = (); +# $p->{sid} = $cgi->cookie($sitecfg->{cookiename}); +# my $se = session->new(); +# my $sess = $se->getsession($p->{sid}); +if (exists($p->{fn}) ){ + if (exists($p->{id_user})){ + if (($p->{fn} eq "delete") || (($p->{fn} eq "renew"))){ + my $sql = "select id,fingerpos from staff where id=".$p->{id_user}.";"; + my $db = dksdb->new(); + #$html->{result}->{sql} = $sql; + my @rdb = $db->query($sql); + if (scalar(@rdb) > 0){ + my $cmd ='/usr/bin/python2 '.dirname($0).'/tools/fingerdelete.py '.$rdb[0]->{fingerpos}; + my $res = `$cmd`; + chomp($res); + if ($res eq ""){ + my $sql = "update staff set fingerpos=null,fingerhash=null where id=".$p->{id_user}.";"; + $html->{result}->{status} = "deleted"; + if ($p->{fn} eq "renew"){ + $p->{fn} = "new"; + } + } + } + + } + if ($p->{fn} eq "new"){ + my $cmd ='/usr/bin/python2 '.dirname($0).'/tools/fingerledon.py'; + my $res = `$cmd`; + chomp($res); + if ($res eq ''){ + $cmd ='/usr/bin/python2 '.dirname($0).'/tools/fingerenroll.py'; + my $res = `$cmd`; + } + + }elsif ($p->{fn} eq "check"){ + my $cmd ='sudo /usr/bin/python '.dirname($0).'/tools/fingersearch.py'; + my $res = `$cmd`; + chomp($res); + if ($res =~ /POS:.*HASH:/){ + my ($pos,$hash) = $res =~ m/.*POS:(\d+);HASH:(.+)\s*$/; + #$html->{result}->{pos} = $pos; + #$html->{result}->{hash} = $hash; + if (length($pos) > 0 && length($hash) > 0){ + my $sql = "select id,fingerpos,fingerhash from staff where id=".$p->{id_user}." and fingerpos=".$pos." and fingerhash='".$hash."';"; + my $db = dksdb->new(); + #$html->{result}->{sql} = $sql; + my @rdb = $db->query($sql); + if (scalar(@rdb) > 0 ){ + $html->{result}->{status} ="OK"; + #$html->{result}->{db} = \@rdb; + $cmd ='/usr/bin/python2 '.dirname($0).'/tools/fingerledoff.py'; + $res = `$cmd`; + } + } + + } else { + $html->{result}->{status} = $res; + } + } + } + elsif($p->{fn} eq "unload"){ + my $cmd = 'ps ax | grep "tools/finger" | awk \'{ print \$ }\''; + my $res = `$cmd`; + } + elsif($p->{fn} eq "ledon"){ + my $cmd ='/usr/bin/python2 '.dirname($0).'/tools/fingerledon.py'; + my $res = `$cmd`; + chomp($res); + if ($res eq ""){ + $html->{result}->{status} = "ok"; + } else { + $html->{result}->{status} = "error"; + } + } + elsif($p->{fn} eq "ledoff"){ + my $cmd ='/usr/bin/python2 '.dirname($0).'/tools/fingerledoff.py'; + my $res = `$cmd`; + chomp($res); + if ($res eq ""){ + $html->{result}->{status} = "ok"; + } else { + $html->{result}->{status} = "error"; + } + } +} +print $cgi->header(-type=>"application/json", -charset => "utf-8"); +print JSON::PP::encode_json($html); \ No newline at end of file diff --git a/CGI/api/tools/fingerdelete.py b/CGI/api/tools/fingerdelete.py new file mode 100644 index 0000000..ab3a325 --- /dev/null +++ b/CGI/api/tools/fingerdelete.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" +import sys +from pyfingerprint2.pyfingerprint import PyFingerprint +if len(sys.argv) == 1: + print ('Error: No position!'); + exit(1) + +## Deletes a finger from sensor +## + + +## Tries to initialize the sensor +try: + f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000) + + if ( f.verifyPassword() == False ): + raise ValueError('The given fingerprint sensor password is wrong!') + +except Exception as e: + print('The fingerprint sensor could not be initialized!') + print('Exception message: ' + str(e)) + exit(1) + +## Gets some sensor information +#print('Currently used templates: ' + str(f.getTemplateCount()) +'/'+ str(f.getStorageCapacity())) + +## Tries to delete the template of the finger +try: + positionNumber = int(sys.argv[1]) + + if ( f.deleteTemplate(positionNumber) == True ): + True + #print('Template ' + str(positionNumber) +' deleted!') + +except Exception as e: + print('Operation failed!') + print('Exception message: ' + str(e)) + exit(1) diff --git a/CGI/api/tools/fingerenroll.py b/CGI/api/tools/fingerenroll.py new file mode 100644 index 0000000..8319dc8 --- /dev/null +++ b/CGI/api/tools/fingerenroll.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" + +import time +from pyfingerprint2.pyfingerprint import PyFingerprint + + +## Enrolls new finger +## + +## Tries to initialize the sensor +try: + f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000) + + if ( f.verifyPassword() == False ): + raise ValueError('The given fingerprint sensor password is wrong!') + +except Exception as e: + print('The fingerprint sensor could not be initialized!') + print('Exception message: ' + str(e)) + exit(1) + +## Gets some sensor information +print('Currently used templates: ' + str(f.getTemplateCount()) +'/'+ str(f.getStorageCapacity())) + +## Tries to enroll new finger +try: + print('Waiting for finger...') + + ## Wait that finger is read + while ( f.readImage() == False ): + pass + + ## Converts read image to characteristics and stores it in charbuffer 1 + f.convertImage(0x01) + + ## Checks if finger is already enrolled + result = f.searchTemplate() + positionNumber = result[0] + + if ( positionNumber >= 0 ): + print('Template already exists at position #' + str(positionNumber)) + exit(0) + + print('Remove finger...') + time.sleep(2) + + print('Waiting for same finger again...') + + ## Wait that finger is read again + while ( f.readImage() == False ): + pass + + ## Converts read image to characteristics and stores it in charbuffer 2 + f.convertImage(0x02) + + ## Compares the charbuffers + if ( f.compareCharacteristics() == 0 ): + raise Exception('Fingers do not match') + + ## Creates a template + f.createTemplate() + + ## Saves template at new position number + positionNumber = f.storeTemplate() + print('Finger enrolled successfully!') + print('New template position #' + str(positionNumber)) + +except Exception as e: + print('Operation failed!') + print('Exception message: ' + str(e)) + exit(1) diff --git a/CGI/api/tools/fingerledoff.py b/CGI/api/tools/fingerledoff.py new file mode 100644 index 0000000..1eec425 --- /dev/null +++ b/CGI/api/tools/fingerledoff.py @@ -0,0 +1,27 @@ +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" + +import time +from pyfingerprint2.pyfingerprint import PyFingerprint + + +## Enrolls new finger +## + +## Tries to initialize the sensor +try: + f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000) + + if ( f.verifyPassword() == False ): + raise ValueError('The given fingerprint sensor password is wrong!') + +except Exception as e: + print('The fingerprint sensor could not be initialized!') + print('Exception message: ' + str(e)) + exit(1) + +f.setLEDoff() diff --git a/CGI/api/tools/fingerledon.py b/CGI/api/tools/fingerledon.py new file mode 100644 index 0000000..8a08f7f --- /dev/null +++ b/CGI/api/tools/fingerledon.py @@ -0,0 +1,27 @@ +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" + +import time +from pyfingerprint2.pyfingerprint import PyFingerprint + + +## Enrolls new finger +## + +## Tries to initialize the sensor +try: + f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000) + + if ( f.verifyPassword() == False ): + raise ValueError('The given fingerprint sensor password is wrong!') + +except Exception as e: + print('The fingerprint sensor could not be initialized!') + print('Exception message: ' + str(e)) + exit(1) + +f.setLEDon() diff --git a/CGI/api/tools/fingersearch.py b/CGI/api/tools/fingersearch.py new file mode 100644 index 0000000..be98fce --- /dev/null +++ b/CGI/api/tools/fingersearch.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" + +import hashlib +from pyfingerprint2.pyfingerprint import PyFingerprint + + +## Search for a finger +## + +## Tries to initialize the sensor +try: + f = PyFingerprint('/dev/ttyUSB0', 57600, 0xFFFFFFFF, 0x00000000) + + if ( f.verifyPassword() == False ): + raise ValueError('The given fingerprint sensor password is wrong!') + +except Exception as e: + print('The fingerprint sensor could not be initialized!') + print('Exception message: ' + str(e)) + exit(1) + +## Gets some sensor information +print('Currently used templates: ' + str(f.getTemplateCount()) +'/'+ str(f.getStorageCapacity())) + +## Tries to search the finger and calculate hash +try: + print('Waiting for finger...') + + ## Wait that finger is read + while ( f.readImage() == False ): + pass + + ## Converts read image to characteristics and stores it in charbuffer 1 + f.convertImage(0x01) + + ## Searchs template + result = f.searchTemplate() + + positionNumber = result[0] + accuracyScore = result[1] + + if ( positionNumber == -1 ): + print('No match found!') + exit(0) + else: + print('Found template at position #' + str(positionNumber)) + print('The accuracy score is: ' + str(accuracyScore)) + ## Loads the found template to charbuffer 1 + f.loadTemplate(positionNumber, 0x01) + + ## Downloads the characteristics of template loaded in charbuffer 1 + characterics = str(f.downloadCharacteristics(0x01)).encode('utf-8') + + ## Hashes characteristics of template + #print('SHA-2 hash of template: ' + hashlib.sha256(characterics).hexdigest()) + print('POS:' + str(positionNumber) + ';HASH:' + hashlib.sha256(characterics).hexdigest()) + +except Exception as e: + print('Operation failed!') + print('Exception message: ' + str(e)) + exit(1) diff --git a/CGI/api/tools/pyfingerprint2/__init__.py b/CGI/api/tools/pyfingerprint2/__init__.py new file mode 100644 index 0000000..4882220 --- /dev/null +++ b/CGI/api/tools/pyfingerprint2/__init__.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" + +__version__ = '1.5' diff --git a/CGI/api/tools/pyfingerprint2/pyfingerprint.orig.py b/CGI/api/tools/pyfingerprint2/pyfingerprint.orig.py new file mode 100644 index 0000000..af2f663 --- /dev/null +++ b/CGI/api/tools/pyfingerprint2/pyfingerprint.orig.py @@ -0,0 +1,1326 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" + +import os +import serial +from PIL import Image +import struct + + +## Baotou start byte +FINGERPRINT_STARTCODE = 0xEF01 + +## Packet identification +## + +FINGERPRINT_COMMANDPACKET = 0x01 + +FINGERPRINT_ACKPACKET = 0x07 +FINGERPRINT_DATAPACKET = 0x02 +FINGERPRINT_ENDDATAPACKET = 0x08 + +## Instruction codes +## + +FINGERPRINT_VERIFYPASSWORD = 0x13 +FINGERPRINT_SETPASSWORD = 0x12 +FINGERPRINT_SETADDRESS = 0x15 +FINGERPRINT_SETSYSTEMPARAMETER = 0x0E +FINGERPRINT_GETSYSTEMPARAMETERS = 0x0F +FINGERPRINT_TEMPLATEINDEX = 0x1F +FINGERPRINT_TEMPLATECOUNT = 0x1D + +FINGERPRINT_READIMAGE = 0x01 + +## Note: The documentation mean upload to host computer. +FINGERPRINT_DOWNLOADIMAGE = 0x0A + +FINGERPRINT_CONVERTIMAGE = 0x02 + +FINGERPRINT_CREATETEMPLATE = 0x05 +FINGERPRINT_STORETEMPLATE = 0x06 +FINGERPRINT_SEARCHTEMPLATE = 0x04 +FINGERPRINT_LOADTEMPLATE = 0x07 +FINGERPRINT_DELETETEMPLATE = 0x0C + +FINGERPRINT_CLEARDATABASE = 0x0D +FINGERPRINT_GENERATERANDOMNUMBER = 0x14 +FINGERPRINT_COMPARECHARACTERISTICS = 0x03 + +## Note: The documentation mean download from host computer. +FINGERPRINT_UPLOADCHARACTERISTICS = 0x09 + +## Note: The documentation mean upload to host computer. +FINGERPRINT_DOWNLOADCHARACTERISTICS = 0x08 + +## Packet reply confirmations +## + +FINGERPRINT_OK = 0x00 +FINGERPRINT_ERROR_COMMUNICATION = 0x01 + +FINGERPRINT_ERROR_WRONGPASSWORD = 0x13 + +FINGERPRINT_ERROR_INVALIDREGISTER = 0x1A + +FINGERPRINT_ERROR_NOFINGER = 0x02 +FINGERPRINT_ERROR_READIMAGE = 0x03 + +FINGERPRINT_ERROR_MESSYIMAGE = 0x06 +FINGERPRINT_ERROR_FEWFEATUREPOINTS = 0x07 +FINGERPRINT_ERROR_INVALIDIMAGE = 0x15 + +FINGERPRINT_ERROR_CHARACTERISTICSMISMATCH = 0x0A + +FINGERPRINT_ERROR_INVALIDPOSITION = 0x0B +FINGERPRINT_ERROR_FLASH = 0x18 + +FINGERPRINT_ERROR_NOTEMPLATEFOUND = 0x09 + +FINGERPRINT_ERROR_LOADTEMPLATE = 0x0C + +FINGERPRINT_ERROR_DELETETEMPLATE = 0x10 + +FINGERPRINT_ERROR_CLEARDATABASE = 0x11 + +FINGERPRINT_ERROR_NOTMATCHING = 0x08 + +FINGERPRINT_ERROR_DOWNLOADIMAGE = 0x0F +FINGERPRINT_ERROR_DOWNLOADCHARACTERISTICS = 0x0D + +## Unknown error codes +## + +FINGERPRINT_ADDRCODE = 0x20 +FINGERPRINT_PASSVERIFY = 0x21 + +FINGERPRINT_PACKETRESPONSEFAIL = 0x0E + +FINGERPRINT_ERROR_TIMEOUT = 0xFF +FINGERPRINT_ERROR_BADPACKET = 0xFE + + +class PyFingerprint(object): + """ + A python written library for the ZhianTec ZFM-20 fingerprint sensor. + + @attribute integer(4 bytes) __address + Address to connect to sensor. + + @attribute integer(4 bytes) __password + Password to connect to sensor. + + @attribute Serial __serial + UART serial connection via PySerial. + """ + __address = None + __password = None + __serial = None + + def __init__(self, port = '/dev/ttyUSB0', baudRate = 57600, address = 0xFFFFFFFF, password = 0x00000000): + """ + Constructor + + @param string port + @param integer baudRate + @param integer(4 bytes) address + @param integer(4 bytes) password + """ + + if ( os.path.exists(port) == False ): + raise ValueError('The fingerprint sensor port "' + port + '" was not found!') + + if ( baudRate < 9600 or baudRate > 115200 or baudRate % 9600 != 0 ): + raise ValueError('The given baudrate is invalid!') + + if ( address < 0x00000000 or address > 0xFFFFFFFF ): + raise ValueError('The given address is invalid!') + + if ( password < 0x00000000 or password > 0xFFFFFFFF ): + raise ValueError('The given password is invalid!') + + self.__address = address + self.__password = password + + ## Initialize PySerial connection + self.__serial = serial.Serial(port = port, baudrate = baudRate, bytesize = serial.EIGHTBITS, timeout = 2) + + if ( self.__serial.isOpen() == True ): + self.__serial.close() + + self.__serial.open() + + def __del__(self): + """ + Destructor + + """ + + ## Close connection if still established + if ( self.__serial is not None and self.__serial.isOpen() == True ): + self.__serial.close() + + def __rightShift(self, n, x): + """ + Shift a byte. + + @param integer n + @param integer x + @return integer + """ + + return (n >> x & 0xFF) + + def __leftShift(self, n, x): + """ + Shift a byte. + + @param integer n + @param integer x + @return integer + """ + + return (n << x) + + def __bitAtPosition(self, n, p): + """ + Get the bit of n at position p. + + @param integer n + @param integer p + @return integer + """ + + ## A bitshift 2 ^ p + twoP = 1 << p + + ## Binary AND composition (on both positions must be a 1) + ## This can only happen at position p + result = n & twoP + return int(result > 0) + + def __byteToString(self, byte): + """ + Converts a byte to string. + + @param byte byte + @return string + """ + + return struct.pack('@B', byte) + + def __stringToByte(self, string): + """ + Convert one "string" byte (like '0xFF') to real integer byte (0xFF). + + @param string string + @return byte + """ + + return struct.unpack('@B', string)[0] + + def __writePacket(self, packetType, packetPayload): + """ + Send a packet to fingerprint sensor. + + @param integer(1 byte) packetType + @param tuple packetPayload + + @return void + """ + + ## Write header (one byte at once) + self.__serial.write(self.__byteToString(self.__rightShift(FINGERPRINT_STARTCODE, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(FINGERPRINT_STARTCODE, 0))) + + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 24))) + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 16))) + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 0))) + + self.__serial.write(self.__byteToString(packetType)) + + ## The packet length = package payload (n bytes) + checksum (2 bytes) + packetLength = len(packetPayload) + 2 + + self.__serial.write(self.__byteToString(self.__rightShift(packetLength, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(packetLength, 0))) + + ## The packet checksum = packet type (1 byte) + packet length (2 bytes) + payload (n bytes) + packetChecksum = packetType + self.__rightShift(packetLength, 8) + self.__rightShift(packetLength, 0) + + ## Write payload + for i in range(0, len(packetPayload)): + self.__serial.write(self.__byteToString(packetPayload[i])) + packetChecksum += packetPayload[i] + + ## Write checksum (2 bytes) + self.__serial.write(self.__byteToString(self.__rightShift(packetChecksum, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(packetChecksum, 0))) + + def __readPacket(self): + """ + Receive a packet from fingerprint sensor. + + Return a tuple that contain the following information: + 0: integer(1 byte) The packet type. + 1: integer(n bytes) The packet payload. + + @return tuple + """ + + receivedPacketData = [] + i = 0 + + while ( True ): + + ## Read one byte + receivedFragment = self.__serial.read() + + if ( len(receivedFragment) != 0 ): + receivedFragment = self.__stringToByte(receivedFragment) + ## print 'Received packet fragment = ' + hex(receivedFragment) + + ## Insert byte if packet seems valid + receivedPacketData.insert(i, receivedFragment) + i += 1 + + ## Packet could be complete (the minimal packet size is 12 bytes) + if ( i >= 12 ): + + ## Check the packet header + if ( receivedPacketData[0] != self.__rightShift(FINGERPRINT_STARTCODE, 8) or receivedPacketData[1] != self.__rightShift(FINGERPRINT_STARTCODE, 0) ): + raise Exception('The received packet do not begin with a valid header!') + + ## Calculate packet payload length (combine the 2 length bytes) + packetPayloadLength = self.__leftShift(receivedPacketData[7], 8) + packetPayloadLength = packetPayloadLength | self.__leftShift(receivedPacketData[8], 0) + + ## Check if the packet is still fully received + ## Condition: index counter < packet payload length + packet frame + if ( i < packetPayloadLength + 9 ): + continue + + ## At this point the packet should be fully received + + packetType = receivedPacketData[6] + + ## Calculate checksum: + ## checksum = packet type (1 byte) + packet length (2 bytes) + packet payload (n bytes) + packetChecksum = packetType + receivedPacketData[7] + receivedPacketData[8] + + packetPayload = [] + + ## Collect package payload (ignore the last 2 checksum bytes) + for j in range(9, 9 + packetPayloadLength - 2): + packetPayload.append(receivedPacketData[j]) + packetChecksum += receivedPacketData[j] + + ## Calculate full checksum of the 2 separate checksum bytes + receivedChecksum = self.__leftShift(receivedPacketData[i - 2], 8) + receivedChecksum = receivedChecksum | self.__leftShift(receivedPacketData[i - 1], 0) + + if ( receivedChecksum != packetChecksum ): + raise Exception('The received packet is corrupted (the checksum is wrong)!') + + return (packetType, packetPayload) + + def verifyPassword(self): + """ + Verify password of the fingerprint sensor. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_VERIFYPASSWORD, + self.__rightShift(self.__password, 24), + self.__rightShift(self.__password, 16), + self.__rightShift(self.__password, 8), + self.__rightShift(self.__password, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Sensor password is correct + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ADDRCODE ): + raise Exception('The address is wrong') + + ## DEBUG: Sensor password is wrong + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_WRONGPASSWORD ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def setPassword(self, newPassword): + """ + Set the password of the sensor. + + @param integer(4 bytes) newPassword + @return boolean + """ + + ## Validate the password (maximum 4 bytes) + if ( newPassword < 0x00000000 or newPassword > 0xFFFFFFFF ): + raise ValueError('The given password is invalid!') + + packetPayload = ( + FINGERPRINT_SETPASSWORD, + self.__rightShift(newPassword, 24), + self.__rightShift(newPassword, 16), + self.__rightShift(newPassword, 8), + self.__rightShift(newPassword, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Password set was successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + self.__password = newPassword + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def setAddress(self, newAddress): + """ + Set the module address of the sensor. + + @param integer(4 bytes) newAddress + @return boolean + """ + + ## Validate the address (maximum 4 bytes) + if ( newAddress < 0x00000000 or newAddress > 0xFFFFFFFF ): + raise ValueError('The given address is invalid!') + + packetPayload = ( + FINGERPRINT_SETADDRESS, + self.__rightShift(newAddress, 24), + self.__rightShift(newAddress, 16), + self.__rightShift(newAddress, 8), + self.__rightShift(newAddress, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Address set was successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + self.__address = newAddress + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def setSystemParameter(self, parameterNumber, parameterValue): + """ + Set a system parameter of the sensor. + + @param integer(1 byte) parameterNumber + @param integer(1 byte) parameterValue + @return boolean + """ + + ## Validate the baudrate parameter + if ( parameterNumber == 4 ): + + if ( parameterValue < 1 or parameterValue > 12 ): + raise ValueError('The given baudrate parameter is invalid!') + + ## Validate the security level parameter + elif ( parameterNumber == 5 ): + + if ( parameterValue < 1 or parameterValue > 5 ): + raise ValueError('The given security level parameter is invalid!') + + ## Validate the package length parameter + elif ( parameterNumber == 6 ): + + if ( parameterValue < 0 or parameterValue > 3 ): + raise ValueError('The given package length parameter is invalid!') + + ## The parameter number is not valid + else: + raise ValueError('The given parameter number is invalid!') + + packetPayload = ( + FINGERPRINT_SETSYSTEMPARAMETER, + parameterNumber, + parameterValue, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Parameter set was successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDREGISTER ): + raise Exception('Invalid register number') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def getSystemParameters(self): + """ + Get all available system information of the sensor. + + Return a tuple that contain the following information: + 0: integer(2 bytes) The status register. + 1: integer(2 bytes) The system id. + 2: integer(2 bytes) The storage capacity. + 3: integer(2 bytes) The security level. + 4: integer(4 bytes) The sensor address. + 5: integer(2 bytes) The packet length. + 6: integer(2 bytes) The baudrate. + + @return tuple + """ + + packetPayload = ( + FINGERPRINT_GETSYSTEMPARAMETERS, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Read successfully + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + + statusRegister = self.__leftShift(receivedPacketPayload[1], 8) | self.__leftShift(receivedPacketPayload[2], 0) + systemID = self.__leftShift(receivedPacketPayload[3], 8) | self.__leftShift(receivedPacketPayload[4], 0) + storageCapacity = self.__leftShift(receivedPacketPayload[5], 8) | self.__leftShift(receivedPacketPayload[6], 0) + securityLevel = self.__leftShift(receivedPacketPayload[7], 8) | self.__leftShift(receivedPacketPayload[8], 0) + deviceAddress = ((receivedPacketPayload[9] << 8 | receivedPacketPayload[10]) << 8 | receivedPacketPayload[11]) << 8 | receivedPacketPayload[12] ## TODO + packetLength = self.__leftShift(receivedPacketPayload[13], 8) | self.__leftShift(receivedPacketPayload[14], 0) + baudRate = self.__leftShift(receivedPacketPayload[15], 8) | self.__leftShift(receivedPacketPayload[16], 0) + + return (statusRegister, systemID, storageCapacity, securityLevel, deviceAddress, packetLength, baudRate) + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def getTemplateIndex(self, page): + """ + Get a list of the template positions with usage indicator. + + @param integer(1 byte) page + @return list + """ + + if ( page < 0 or page > 3 ): + raise ValueError('The given index page is invalid!') + + packetPayload = ( + FINGERPRINT_TEMPLATEINDEX, + page, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Read index table successfully + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + + templateIndex = [] + + ## Contain the table page bytes (skip the first status byte) + pageElements = receivedPacketPayload[1:] + + for pageElement in pageElements: + ## Test every bit (bit = template position is used indicator) of a table page element + for p in range(0, 7 + 1): + positionIsUsed = (self.__bitAtPosition(pageElement, p) == 1) + templateIndex.append(positionIsUsed) + + return templateIndex + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def getTemplateCount(self): + """ + Get the number of stored templates. + + @return integer(2 bytes) + """ + + packetPayload = ( + FINGERPRINT_TEMPLATECOUNT, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Read successfully + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + templateCount = self.__leftShift(receivedPacketPayload[1], 8) + templateCount = templateCount | self.__leftShift(receivedPacketPayload[2], 0) + return templateCount + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def readImage(self): + """ + Read the image of a finger and stores it in ImageBuffer. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_READIMAGE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Image read successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: No finger found + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_NOFINGER ): + return False + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_READIMAGE ): + raise Exception('Could not read image') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + ## TODO: + ## Implementation of uploadImage() + + def downloadImage(self, imageDestination): + """ + Download the image of a finger to host computer. + + @param string imageDestination + @return void + """ + + destinationDirectory = os.path.dirname(imageDestination) + + if ( os.access(destinationDirectory, os.W_OK) == False ): + raise ValueError('The given destination directory "' + destinationDirectory + '" is not writable!') + + packetPayload = ( + FINGERPRINT_DOWNLOADIMAGE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: The sensor will sent follow-up packets + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_DOWNLOADIMAGE ): + raise Exception('Could not download image') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + ## Initialize image library + resultImage = Image.new('L', (256, 288), 'white') + pixels = resultImage.load() + + ## Y coordinate of current pixel + line = 0 + + ## Get follow-up data packets until the last data packet is received + while ( receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_DATAPACKET and receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + raise Exception('The received packet is no data packet!') + + ## X coordinate of current pixel + x = 0 + + for i in range(0, len(receivedPacketPayload)): + + ## Thanks to Danylo Esterman for the "multiple with 17" improvement: + + ## Draw left 4 Bits one byte of package + pixels[x, line] = (receivedPacketPayload[i] >> 4) * 17 + x = x + 1 + + ## Draw right 4 Bits one byte of package + pixels[x, line] = (receivedPacketPayload[i] & 0b00001111) * 17 + x = x + 1 + + line = line + 1 + + resultImage.save(imageDestination) + + def convertImage(self, charBufferNumber = 0x01): + """ + Convert the image in ImageBuffer to finger characteristics and store in CharBuffer1 or CharBuffer2. + + @param integer(1 byte) charBufferNumber + @return boolean + """ + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_CONVERTIMAGE, + charBufferNumber, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Image converted + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_MESSYIMAGE ): + raise Exception('The image is too messy') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_FEWFEATUREPOINTS ): + raise Exception('The image contains too few feature points') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDIMAGE ): + raise Exception('The image is invalid') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def createTemplate(self): + """ + Combine the characteristics which are stored in CharBuffer1 and CharBuffer2 to a template. + The created template will be stored again in CharBuffer1 and CharBuffer2 as the same. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_CREATETEMPLATE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template created successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: The characteristics not matching + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_CHARACTERISTICSMISMATCH ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def storeTemplate(self, positionNumber = -1, charBufferNumber = 0x01): + """ + Save a template from the specified CharBuffer to the given position number. + + @param integer(2 bytes) positionNumber + @param integer(1 byte) charBufferNumber + @return integer + """ + + ## Find a free index + if ( positionNumber == -1 ): + for page in range(0, 4): + ## Free index found? + if ( positionNumber >= 0 ): + break + + templateIndex = self.getTemplateIndex(page) + + for i in range(0, len(templateIndex)): + ## Index not used? + if ( templateIndex[i] == False ): + positionNumber = (len(templateIndex) * page) + i + break + + if ( positionNumber < 0x0000 or positionNumber >= self.getStorageCapacity() ): + raise ValueError('The given position number is invalid!') + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_STORETEMPLATE, + charBufferNumber, + self.__rightShift(positionNumber, 8), + self.__rightShift(positionNumber, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template stored successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return positionNumber + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDPOSITION ): + raise Exception('Could not store template in that position') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_FLASH ): + raise Exception('Error writing to flash') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def searchTemplate(self): + """ + Search the finger characteristics in CharBuffer in database. + + Return a tuple that contain the following information: + 0: integer(2 bytes) The position number of found template. + 1: integer(2 bytes) The accuracy score of found template. + + @return tuple + """ + + ## CharBuffer1 and CharBuffer2 are the same in this case + charBufferNumber = 0x01 + + ## Begin search at index 0 + positionStart = 0x0000 + templatesCount = self.getStorageCapacity() + + packetPayload = ( + FINGERPRINT_SEARCHTEMPLATE, + charBufferNumber, + self.__rightShift(positionStart, 8), + self.__rightShift(positionStart, 0), + self.__rightShift(templatesCount, 8), + self.__rightShift(templatesCount, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Found template + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + + positionNumber = self.__leftShift(receivedPacketPayload[1], 8) + positionNumber = positionNumber | self.__leftShift(receivedPacketPayload[2], 0) + + accuracyScore = self.__leftShift(receivedPacketPayload[3], 8) + accuracyScore = accuracyScore | self.__leftShift(receivedPacketPayload[4], 0) + + return (positionNumber, accuracyScore) + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: Did not found a matching template + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_NOTEMPLATEFOUND ): + return (-1, -1) + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def loadTemplate(self, positionNumber, charBufferNumber = 0x01): + """ + Load an existing template specified by position number to specified CharBuffer. + + @param integer(2 bytes) positionNumber + @param integer(1 byte) charBufferNumber + @return boolean + """ + + if ( positionNumber < 0x0000 or positionNumber >= self.getStorageCapacity() ): + raise ValueError('The given position number is invalid!') + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_LOADTEMPLATE, + charBufferNumber, + self.__rightShift(positionNumber, 8), + self.__rightShift(positionNumber, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template loaded successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_LOADTEMPLATE ): + raise Exception('The template could not be read') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDPOSITION ): + raise Exception('Could not load template from that position') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def deleteTemplate(self, positionNumber, count = 1): + """ + Delete templates from fingerprint database. Per default one. + + @param integer(2 bytes) positionNumber + @param integer(2 bytes) count + @return boolean + """ + + capacity = self.getStorageCapacity() + + if ( positionNumber < 0x0000 or positionNumber >= capacity ): + raise ValueError('The given position number is invalid!') + + if ( count < 0x0000 or count > capacity - positionNumber ): + raise ValueError('The given count is invalid!') + + packetPayload = ( + FINGERPRINT_DELETETEMPLATE, + self.__rightShift(positionNumber, 8), + self.__rightShift(positionNumber, 0), + self.__rightShift(count, 8), + self.__rightShift(count, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template deleted successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDPOSITION ): + raise Exception('Invalid position') + + ## DEBUG: Could not delete template + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_DELETETEMPLATE ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def clearDatabase(self): + """ + Clear the complete template database. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_CLEARDATABASE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Database cleared successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: Could not clear database + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_CLEARDATABASE ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def compareCharacteristics(self): + """ + Compare the finger characteristics of CharBuffer1 with CharBuffer2 and return the accuracy score. + + @return integer(2 bytes) + """ + + packetPayload = ( + FINGERPRINT_COMPARECHARACTERISTICS, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Comparison successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + accuracyScore = self.__leftShift(receivedPacketPayload[1], 8) + accuracyScore = accuracyScore | self.__leftShift(receivedPacketPayload[2], 0) + return accuracyScore + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: The characteristics do not matching + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_NOTMATCHING ): + return 0 + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def uploadCharacteristics(self, charBufferNumber = 0x01, characteristicsData = [0]): + """ + Upload finger characteristics to CharBuffer1 or CharBuffer2. + + @author: David Gilson + + @param integer(1 byte) charBufferNumber + @param integer(list) characteristicsData + + @return boolean + Return true if everything is right. + """ + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + if ( characteristicsData == [0] ): + raise ValueError('The characteristics data is required!') + + maxPacketSize = self.getMaxPacketSize() + + ## Upload command + + packetPayload = ( + FINGERPRINT_UPLOADCHARACTERISTICS, + charBufferNumber + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: The sensor will sent follow-up packets + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_PACKETRESPONSEFAIL ): + raise Exception('Could not upload characteristics') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + ## Upload data packets + packetNbr = len(characteristicsData) / maxPacketSize + + if ( packetNbr <= 1 ): + self.__writePacket(FINGERPRINT_ENDDATAPACKET, characteristicsData) + else: + i = 1 + while ( i < packetNbr ): + lfrom = (i-1) * maxPacketSize + lto = lfrom + maxPacketSize + self.__writePacket(FINGERPRINT_DATAPACKET, characteristicsData[lfrom:lto]) + i += 1 + + lfrom = (i-1) * maxPacketSize + lto = lfrom + maxPacketSize + self.__writePacket(FINGERPRINT_ENDDATAPACKET, characteristicsData[lfrom:lto]) + + ## Verify uploaded characteristics + characterics = self.downloadCharacteristics(charBufferNumber) + return (characterics == characteristicsData) + + def getMaxPacketSize(self): + """ + Get the maximum allowed size of packet by sensor. + + @author: David Gilson + + @return int + Return the max size. Default 32 bytes. + """ + + packetMaxSizeType = self.getSystemParameters()[5] + + if (packetMaxSizeType == 1): + return 64 + elif (packetMaxSizeType == 2): + return 128 + elif (packetMaxSizeType == 3): + return 256 + else: + return 32 + + def getStorageCapacity(self): + """ + Get the sensor storage capacity. + + @return int + The storage capacity. + """ + + return self.getSystemParameters()[2] + + def generateRandomNumber(self): + """ + Generate a random 32-bit decimal number. + + @author: Philipp Meisberger + + @return int + The generated random number + """ + packetPayload = ( + FINGERPRINT_GENERATERANDOMNUMBER, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + number = 0 + number = number | self.__leftShift(receivedPacketPayload[1], 24) + number = number | self.__leftShift(receivedPacketPayload[2], 16) + number = number | self.__leftShift(receivedPacketPayload[3], 8) + number = number | self.__leftShift(receivedPacketPayload[4], 0) + return number + + def downloadCharacteristics(self, charBufferNumber = 0x01): + """ + Download the finger characteristics of CharBuffer1 or CharBuffer2. + + @param integer(1 byte) charBufferNumber + + @return list + Return a list that contains 512 integer(1 byte) elements of the characteristic. + """ + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_DOWNLOADCHARACTERISTICS, + charBufferNumber, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: The sensor will sent follow-up packets + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_DOWNLOADCHARACTERISTICS ): + raise Exception('Could not download characteristics') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + completePayload = [] + + ## Get follow-up data packets until the last data packet is received + while ( receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_DATAPACKET and receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + raise Exception('The received packet is no data packet!') + + for i in range(0, len(receivedPacketPayload)): + completePayload.append(receivedPacketPayload[i]) + + return completePayload diff --git a/CGI/api/tools/pyfingerprint2/pyfingerprint.py b/CGI/api/tools/pyfingerprint2/pyfingerprint.py new file mode 100644 index 0000000..f5e8d19 --- /dev/null +++ b/CGI/api/tools/pyfingerprint2/pyfingerprint.py @@ -0,0 +1,1358 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +""" +PyFingerprint +Copyright (C) 2015 Bastian Raschke +All rights reserved. + +""" + +import os +import serial +from PIL import Image +import struct + + +## Baotou start byte +FINGERPRINT_STARTCODE = 0xEF01 + +## Packet identification +## + +FINGERPRINT_COMMANDPACKET = 0x01 + +FINGERPRINT_ACKPACKET = 0x07 +FINGERPRINT_DATAPACKET = 0x02 +FINGERPRINT_ENDDATAPACKET = 0x08 + +## Instruction codes +## + +FINGERPRINT_VERIFYPASSWORD = 0x13 +FINGERPRINT_SETPASSWORD = 0x12 +FINGERPRINT_SETADDRESS = 0x15 +FINGERPRINT_SETSYSTEMPARAMETER = 0x0E +FINGERPRINT_GETSYSTEMPARAMETERS = 0x0F +FINGERPRINT_TEMPLATEINDEX = 0x1F +FINGERPRINT_TEMPLATECOUNT = 0x1D + +FINGERPRINT_READIMAGE = 0x01 + +## Note: The documentation mean upload to host computer. +FINGERPRINT_DOWNLOADIMAGE = 0x0A + +FINGERPRINT_CONVERTIMAGE = 0x02 + +FINGERPRINT_CREATETEMPLATE = 0x05 +FINGERPRINT_STORETEMPLATE = 0x06 +FINGERPRINT_SEARCHTEMPLATE = 0x04 +FINGERPRINT_LOADTEMPLATE = 0x07 +FINGERPRINT_DELETETEMPLATE = 0x0C + +FINGERPRINT_CLEARDATABASE = 0x0D +FINGERPRINT_GENERATERANDOMNUMBER = 0x14 +FINGERPRINT_COMPARECHARACTERISTICS = 0x03 + +## Note: The documentation mean download from host computer. +FINGERPRINT_UPLOADCHARACTERISTICS = 0x09 + +## Note: The documentation mean upload to host computer. +FINGERPRINT_DOWNLOADCHARACTERISTICS = 0x08 +## LED +FINGERPRINT_LEDON = 0x50 +FINGERPRINT_LEDOFF = 0x51 +## Packet reply confirmations +## + +FINGERPRINT_OK = 0x00 +FINGERPRINT_ERROR_COMMUNICATION = 0x01 + +FINGERPRINT_ERROR_WRONGPASSWORD = 0x13 + +FINGERPRINT_ERROR_INVALIDREGISTER = 0x1A + +FINGERPRINT_ERROR_NOFINGER = 0x02 +FINGERPRINT_ERROR_READIMAGE = 0x03 + +FINGERPRINT_ERROR_MESSYIMAGE = 0x06 +FINGERPRINT_ERROR_FEWFEATUREPOINTS = 0x07 +FINGERPRINT_ERROR_INVALIDIMAGE = 0x15 + +FINGERPRINT_ERROR_CHARACTERISTICSMISMATCH = 0x0A + +FINGERPRINT_ERROR_INVALIDPOSITION = 0x0B +FINGERPRINT_ERROR_FLASH = 0x18 + +FINGERPRINT_ERROR_NOTEMPLATEFOUND = 0x09 + +FINGERPRINT_ERROR_LOADTEMPLATE = 0x0C + +FINGERPRINT_ERROR_DELETETEMPLATE = 0x10 + +FINGERPRINT_ERROR_CLEARDATABASE = 0x11 + +FINGERPRINT_ERROR_NOTMATCHING = 0x08 + +FINGERPRINT_ERROR_DOWNLOADIMAGE = 0x0F +FINGERPRINT_ERROR_DOWNLOADCHARACTERISTICS = 0x0D + +## Unknown error codes +## + +FINGERPRINT_ADDRCODE = 0x20 +FINGERPRINT_PASSVERIFY = 0x21 + +FINGERPRINT_PACKETRESPONSEFAIL = 0x0E + +FINGERPRINT_ERROR_TIMEOUT = 0xFF +FINGERPRINT_ERROR_BADPACKET = 0xFE + + +class PyFingerprint(object): + """ + A python written library for the ZhianTec ZFM-20 fingerprint sensor. + + @attribute integer(4 bytes) __address + Address to connect to sensor. + + @attribute integer(4 bytes) __password + Password to connect to sensor. + + @attribute Serial __serial + UART serial connection via PySerial. + """ + __address = None + __password = None + __serial = None + + def __init__(self, port = '/dev/ttyUSB0', baudRate = 57600, address = 0xFFFFFFFF, password = 0x00000000): + """ + Constructor + + @param string port + @param integer baudRate + @param integer(4 bytes) address + @param integer(4 bytes) password + """ + + if ( os.path.exists(port) == False ): + raise ValueError('The fingerprint sensor port "' + port + '" was not found!') + + if ( baudRate < 9600 or baudRate > 115200 or baudRate % 9600 != 0 ): + raise ValueError('The given baudrate is invalid!') + + if ( address < 0x00000000 or address > 0xFFFFFFFF ): + raise ValueError('The given address is invalid!') + + if ( password < 0x00000000 or password > 0xFFFFFFFF ): + raise ValueError('The given password is invalid!') + + self.__address = address + self.__password = password + + ## Initialize PySerial connection + self.__serial = serial.Serial(port = port, baudrate = baudRate, bytesize = serial.EIGHTBITS, timeout = 2) + + if ( self.__serial.isOpen() == True ): + self.__serial.close() + + self.__serial.open() + + def __del__(self): + """ + Destructor + + """ + + ## Close connection if still established + if ( self.__serial is not None and self.__serial.isOpen() == True ): + self.__serial.close() + + def __rightShift(self, n, x): + """ + Shift a byte. + + @param integer n + @param integer x + @return integer + """ + + return (n >> x & 0xFF) + + def __leftShift(self, n, x): + """ + Shift a byte. + + @param integer n + @param integer x + @return integer + """ + + return (n << x) + + def __bitAtPosition(self, n, p): + """ + Get the bit of n at position p. + + @param integer n + @param integer p + @return integer + """ + + ## A bitshift 2 ^ p + twoP = 1 << p + + ## Binary AND composition (on both positions must be a 1) + ## This can only happen at position p + result = n & twoP + return int(result > 0) + + def __byteToString(self, byte): + """ + Converts a byte to string. + + @param byte byte + @return string + """ + + return struct.pack('@B', byte) + + def __stringToByte(self, string): + """ + Convert one "string" byte (like '0xFF') to real integer byte (0xFF). + + @param string string + @return byte + """ + + return struct.unpack('@B', string)[0] + + def __writePacket(self, packetType, packetPayload): + """ + Send a packet to fingerprint sensor. + + @param integer(1 byte) packetType + @param tuple packetPayload + + @return void + """ + + ## Write header (one byte at once) + self.__serial.write(self.__byteToString(self.__rightShift(FINGERPRINT_STARTCODE, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(FINGERPRINT_STARTCODE, 0))) + + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 24))) + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 16))) + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(self.__address, 0))) + + self.__serial.write(self.__byteToString(packetType)) + + ## The packet length = package payload (n bytes) + checksum (2 bytes) + packetLength = len(packetPayload) + 2 + + self.__serial.write(self.__byteToString(self.__rightShift(packetLength, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(packetLength, 0))) + + ## The packet checksum = packet type (1 byte) + packet length (2 bytes) + payload (n bytes) + packetChecksum = packetType + self.__rightShift(packetLength, 8) + self.__rightShift(packetLength, 0) + + ## Write payload + for i in range(0, len(packetPayload)): + self.__serial.write(self.__byteToString(packetPayload[i])) + packetChecksum += packetPayload[i] + + ## Write checksum (2 bytes) + self.__serial.write(self.__byteToString(self.__rightShift(packetChecksum, 8))) + self.__serial.write(self.__byteToString(self.__rightShift(packetChecksum, 0))) + + def __readPacket(self): + """ + Receive a packet from fingerprint sensor. + + Return a tuple that contain the following information: + 0: integer(1 byte) The packet type. + 1: integer(n bytes) The packet payload. + + @return tuple + """ + + receivedPacketData = [] + i = 0 + + while ( True ): + + ## Read one byte + receivedFragment = self.__serial.read() + + if ( len(receivedFragment) != 0 ): + receivedFragment = self.__stringToByte(receivedFragment) + ## print 'Received packet fragment = ' + hex(receivedFragment) + + ## Insert byte if packet seems valid + receivedPacketData.insert(i, receivedFragment) + i += 1 + + ## Packet could be complete (the minimal packet size is 12 bytes) + if ( i >= 12 ): + + ## Check the packet header + if ( receivedPacketData[0] != self.__rightShift(FINGERPRINT_STARTCODE, 8) or receivedPacketData[1] != self.__rightShift(FINGERPRINT_STARTCODE, 0) ): + raise Exception('The received packet do not begin with a valid header!') + + ## Calculate packet payload length (combine the 2 length bytes) + packetPayloadLength = self.__leftShift(receivedPacketData[7], 8) + packetPayloadLength = packetPayloadLength | self.__leftShift(receivedPacketData[8], 0) + + ## Check if the packet is still fully received + ## Condition: index counter < packet payload length + packet frame + if ( i < packetPayloadLength + 9 ): + continue + + ## At this point the packet should be fully received + + packetType = receivedPacketData[6] + + ## Calculate checksum: + ## checksum = packet type (1 byte) + packet length (2 bytes) + packet payload (n bytes) + packetChecksum = packetType + receivedPacketData[7] + receivedPacketData[8] + + packetPayload = [] + + ## Collect package payload (ignore the last 2 checksum bytes) + for j in range(9, 9 + packetPayloadLength - 2): + packetPayload.append(receivedPacketData[j]) + packetChecksum += receivedPacketData[j] + + ## Calculate full checksum of the 2 separate checksum bytes + receivedChecksum = self.__leftShift(receivedPacketData[i - 2], 8) + receivedChecksum = receivedChecksum | self.__leftShift(receivedPacketData[i - 1], 0) + + if ( receivedChecksum != packetChecksum ): + raise Exception('The received packet is corrupted (the checksum is wrong)!') + + return (packetType, packetPayload) + + def verifyPassword(self): + """ + Verify password of the fingerprint sensor. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_VERIFYPASSWORD, + self.__rightShift(self.__password, 24), + self.__rightShift(self.__password, 16), + self.__rightShift(self.__password, 8), + self.__rightShift(self.__password, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Sensor password is correct + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ADDRCODE ): + raise Exception('The address is wrong') + + ## DEBUG: Sensor password is wrong + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_WRONGPASSWORD ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def setPassword(self, newPassword): + """ + Set the password of the sensor. + + @param integer(4 bytes) newPassword + @return boolean + """ + + ## Validate the password (maximum 4 bytes) + if ( newPassword < 0x00000000 or newPassword > 0xFFFFFFFF ): + raise ValueError('The given password is invalid!') + + packetPayload = ( + FINGERPRINT_SETPASSWORD, + self.__rightShift(newPassword, 24), + self.__rightShift(newPassword, 16), + self.__rightShift(newPassword, 8), + self.__rightShift(newPassword, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Password set was successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + self.__password = newPassword + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def setAddress(self, newAddress): + """ + Set the module address of the sensor. + + @param integer(4 bytes) newAddress + @return boolean + """ + + ## Validate the address (maximum 4 bytes) + if ( newAddress < 0x00000000 or newAddress > 0xFFFFFFFF ): + raise ValueError('The given address is invalid!') + + packetPayload = ( + FINGERPRINT_SETADDRESS, + self.__rightShift(newAddress, 24), + self.__rightShift(newAddress, 16), + self.__rightShift(newAddress, 8), + self.__rightShift(newAddress, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Address set was successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + self.__address = newAddress + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def setSystemParameter(self, parameterNumber, parameterValue): + """ + Set a system parameter of the sensor. + + @param integer(1 byte) parameterNumber + @param integer(1 byte) parameterValue + @return boolean + """ + + ## Validate the baudrate parameter + if ( parameterNumber == 4 ): + + if ( parameterValue < 1 or parameterValue > 12 ): + raise ValueError('The given baudrate parameter is invalid!') + + ## Validate the security level parameter + elif ( parameterNumber == 5 ): + + if ( parameterValue < 1 or parameterValue > 5 ): + raise ValueError('The given security level parameter is invalid!') + + ## Validate the package length parameter + elif ( parameterNumber == 6 ): + + if ( parameterValue < 0 or parameterValue > 3 ): + raise ValueError('The given package length parameter is invalid!') + + ## The parameter number is not valid + else: + raise ValueError('The given parameter number is invalid!') + + packetPayload = ( + FINGERPRINT_SETSYSTEMPARAMETER, + parameterNumber, + parameterValue, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Parameter set was successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDREGISTER ): + raise Exception('Invalid register number') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + + def getSystemParameters(self): + """ + Get all available system information of the sensor. + + Return a tuple that contain the following information: + 0: integer(2 bytes) The status register. + 1: integer(2 bytes) The system id. + 2: integer(2 bytes) The storage capacity. + 3: integer(2 bytes) The security level. + 4: integer(4 bytes) The sensor address. + 5: integer(2 bytes) The packet length. + 6: integer(2 bytes) The baudrate. + + @return tuple + """ + + packetPayload = ( + FINGERPRINT_GETSYSTEMPARAMETERS, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Read successfully + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + + statusRegister = self.__leftShift(receivedPacketPayload[1], 8) | self.__leftShift(receivedPacketPayload[2], 0) + systemID = self.__leftShift(receivedPacketPayload[3], 8) | self.__leftShift(receivedPacketPayload[4], 0) + storageCapacity = self.__leftShift(receivedPacketPayload[5], 8) | self.__leftShift(receivedPacketPayload[6], 0) + securityLevel = self.__leftShift(receivedPacketPayload[7], 8) | self.__leftShift(receivedPacketPayload[8], 0) + deviceAddress = ((receivedPacketPayload[9] << 8 | receivedPacketPayload[10]) << 8 | receivedPacketPayload[11]) << 8 | receivedPacketPayload[12] ## TODO + packetLength = self.__leftShift(receivedPacketPayload[13], 8) | self.__leftShift(receivedPacketPayload[14], 0) + baudRate = self.__leftShift(receivedPacketPayload[15], 8) | self.__leftShift(receivedPacketPayload[16], 0) + + return (statusRegister, systemID, storageCapacity, securityLevel, deviceAddress, packetLength, baudRate) + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def getTemplateIndex(self, page): + """ + Get a list of the template positions with usage indicator. + + @param integer(1 byte) page + @return list + """ + + if ( page < 0 or page > 3 ): + raise ValueError('The given index page is invalid!') + + packetPayload = ( + FINGERPRINT_TEMPLATEINDEX, + page, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Read index table successfully + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + + templateIndex = [] + + ## Contain the table page bytes (skip the first status byte) + pageElements = receivedPacketPayload[1:] + + for pageElement in pageElements: + ## Test every bit (bit = template position is used indicator) of a table page element + for p in range(0, 7 + 1): + positionIsUsed = (self.__bitAtPosition(pageElement, p) == 1) + templateIndex.append(positionIsUsed) + + return templateIndex + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def getTemplateCount(self): + """ + Get the number of stored templates. + + @return integer(2 bytes) + """ + + packetPayload = ( + FINGERPRINT_TEMPLATECOUNT, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Read successfully + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + templateCount = self.__leftShift(receivedPacketPayload[1], 8) + templateCount = templateCount | self.__leftShift(receivedPacketPayload[2], 0) + return templateCount + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def readImage(self): + """ + Read the image of a finger and stores it in ImageBuffer. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_READIMAGE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Image read successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: No finger found + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_NOFINGER ): + return False + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_READIMAGE ): + raise Exception('Could not read image') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + ## TODO: + ## Implementation of uploadImage() + def setLEDoff(self): + packetPayload = ( + FINGERPRINT_LEDOFF, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + def setLEDon(self): + packetPayload = ( + FINGERPRINT_LEDON, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + def downloadImage(self, imageDestination): + """ + Download the image of a finger to host computer. + + @param string imageDestination + @return void + """ + + destinationDirectory = os.path.dirname(imageDestination) + + if ( os.access(destinationDirectory, os.W_OK) == False ): + raise ValueError('The given destination directory "' + destinationDirectory + '" is not writable!') + + packetPayload = ( + FINGERPRINT_DOWNLOADIMAGE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: The sensor will sent follow-up packets + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_DOWNLOADIMAGE ): + raise Exception('Could not download image') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + ## Initialize image library + resultImage = Image.new('L', (256, 288), 'white') + pixels = resultImage.load() + + ## Y coordinate of current pixel + line = 0 + + ## Get follow-up data packets until the last data packet is received + while ( receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_DATAPACKET and receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + raise Exception('The received packet is no data packet!') + + ## X coordinate of current pixel + x = 0 + + for i in range(0, len(receivedPacketPayload)): + + ## Thanks to Danylo Esterman for the "multiple with 17" improvement: + + ## Draw left 4 Bits one byte of package + pixels[x, line] = (receivedPacketPayload[i] >> 4) * 17 + x = x + 1 + + ## Draw right 4 Bits one byte of package + pixels[x, line] = (receivedPacketPayload[i] & 0b00001111) * 17 + x = x + 1 + + line = line + 1 + + resultImage.save(imageDestination) + + def convertImage(self, charBufferNumber = 0x01): + """ + Convert the image in ImageBuffer to finger characteristics and store in CharBuffer1 or CharBuffer2. + + @param integer(1 byte) charBufferNumber + @return boolean + """ + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_CONVERTIMAGE, + charBufferNumber, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Image converted + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_MESSYIMAGE ): + raise Exception('The image is too messy') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_FEWFEATUREPOINTS ): + raise Exception('The image contains too few feature points') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDIMAGE ): + raise Exception('The image is invalid') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def createTemplate(self): + """ + Combine the characteristics which are stored in CharBuffer1 and CharBuffer2 to a template. + The created template will be stored again in CharBuffer1 and CharBuffer2 as the same. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_CREATETEMPLATE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template created successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: The characteristics not matching + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_CHARACTERISTICSMISMATCH ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def storeTemplate(self, positionNumber = -1, charBufferNumber = 0x01): + """ + Save a template from the specified CharBuffer to the given position number. + + @param integer(2 bytes) positionNumber + @param integer(1 byte) charBufferNumber + @return integer + """ + + ## Find a free index + if ( positionNumber == -1 ): + for page in range(0, 4): + ## Free index found? + if ( positionNumber >= 0 ): + break + + templateIndex = self.getTemplateIndex(page) + + for i in range(0, len(templateIndex)): + ## Index not used? + if ( templateIndex[i] == False ): + positionNumber = (len(templateIndex) * page) + i + break + + if ( positionNumber < 0x0000 or positionNumber >= self.getStorageCapacity() ): + raise ValueError('The given position number is invalid!') + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_STORETEMPLATE, + charBufferNumber, + self.__rightShift(positionNumber, 8), + self.__rightShift(positionNumber, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template stored successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return positionNumber + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDPOSITION ): + raise Exception('Could not store template in that position') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_FLASH ): + raise Exception('Error writing to flash') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def searchTemplate(self): + """ + Search the finger characteristics in CharBuffer in database. + + Return a tuple that contain the following information: + 0: integer(2 bytes) The position number of found template. + 1: integer(2 bytes) The accuracy score of found template. + + @return tuple + """ + + ## CharBuffer1 and CharBuffer2 are the same in this case + charBufferNumber = 0x01 + + ## Begin search at index 0 + positionStart = 0x0000 + templatesCount = self.getStorageCapacity() + + packetPayload = ( + FINGERPRINT_SEARCHTEMPLATE, + charBufferNumber, + self.__rightShift(positionStart, 8), + self.__rightShift(positionStart, 0), + self.__rightShift(templatesCount, 8), + self.__rightShift(templatesCount, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Found template + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + + positionNumber = self.__leftShift(receivedPacketPayload[1], 8) + positionNumber = positionNumber | self.__leftShift(receivedPacketPayload[2], 0) + + accuracyScore = self.__leftShift(receivedPacketPayload[3], 8) + accuracyScore = accuracyScore | self.__leftShift(receivedPacketPayload[4], 0) + + return (positionNumber, accuracyScore) + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: Did not found a matching template + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_NOTEMPLATEFOUND ): + return (-1, -1) + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def loadTemplate(self, positionNumber, charBufferNumber = 0x01): + """ + Load an existing template specified by position number to specified CharBuffer. + + @param integer(2 bytes) positionNumber + @param integer(1 byte) charBufferNumber + @return boolean + """ + + if ( positionNumber < 0x0000 or positionNumber >= self.getStorageCapacity() ): + raise ValueError('The given position number is invalid!') + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_LOADTEMPLATE, + charBufferNumber, + self.__rightShift(positionNumber, 8), + self.__rightShift(positionNumber, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template loaded successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_LOADTEMPLATE ): + raise Exception('The template could not be read') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDPOSITION ): + raise Exception('Could not load template from that position') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def deleteTemplate(self, positionNumber, count = 1): + """ + Delete templates from fingerprint database. Per default one. + + @param integer(2 bytes) positionNumber + @param integer(2 bytes) count + @return boolean + """ + + capacity = self.getStorageCapacity() + + if ( positionNumber < 0x0000 or positionNumber >= capacity ): + raise ValueError('The given position number is invalid!') + + if ( count < 0x0000 or count > capacity - positionNumber ): + raise ValueError('The given count is invalid!') + + packetPayload = ( + FINGERPRINT_DELETETEMPLATE, + self.__rightShift(positionNumber, 8), + self.__rightShift(positionNumber, 0), + self.__rightShift(count, 8), + self.__rightShift(count, 0), + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Template deleted successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_INVALIDPOSITION ): + raise Exception('Invalid position') + + ## DEBUG: Could not delete template + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_DELETETEMPLATE ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def clearDatabase(self): + """ + Clear the complete template database. + + @return boolean + """ + + packetPayload = ( + FINGERPRINT_CLEARDATABASE, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Database cleared successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + return True + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: Could not clear database + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_CLEARDATABASE ): + return False + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def compareCharacteristics(self): + """ + Compare the finger characteristics of CharBuffer1 with CharBuffer2 and return the accuracy score. + + @return integer(2 bytes) + """ + + packetPayload = ( + FINGERPRINT_COMPARECHARACTERISTICS, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: Comparison successful + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + accuracyScore = self.__leftShift(receivedPacketPayload[1], 8) + accuracyScore = accuracyScore | self.__leftShift(receivedPacketPayload[2], 0) + return accuracyScore + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + ## DEBUG: The characteristics do not matching + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_NOTMATCHING ): + return 0 + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + def uploadCharacteristics(self, charBufferNumber = 0x01, characteristicsData = [0]): + """ + Upload finger characteristics to CharBuffer1 or CharBuffer2. + + @author: David Gilson + + @param integer(1 byte) charBufferNumber + @param integer(list) characteristicsData + + @return boolean + Return true if everything is right. + """ + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + if ( characteristicsData == [0] ): + raise ValueError('The characteristics data is required!') + + maxPacketSize = self.getMaxPacketSize() + + ## Upload command + + packetPayload = ( + FINGERPRINT_UPLOADCHARACTERISTICS, + charBufferNumber + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: The sensor will sent follow-up packets + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_PACKETRESPONSEFAIL ): + raise Exception('Could not upload characteristics') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + ## Upload data packets + packetNbr = len(characteristicsData) / maxPacketSize + + if ( packetNbr <= 1 ): + self.__writePacket(FINGERPRINT_ENDDATAPACKET, characteristicsData) + else: + i = 1 + while ( i < packetNbr ): + lfrom = (i-1) * maxPacketSize + lto = lfrom + maxPacketSize + self.__writePacket(FINGERPRINT_DATAPACKET, characteristicsData[lfrom:lto]) + i += 1 + + lfrom = (i-1) * maxPacketSize + lto = lfrom + maxPacketSize + self.__writePacket(FINGERPRINT_ENDDATAPACKET, characteristicsData[lfrom:lto]) + + ## Verify uploaded characteristics + characterics = self.downloadCharacteristics(charBufferNumber) + return (characterics == characteristicsData) + + def getMaxPacketSize(self): + """ + Get the maximum allowed size of packet by sensor. + + @author: David Gilson + + @return int + Return the max size. Default 32 bytes. + """ + + packetMaxSizeType = self.getSystemParameters()[5] + + if (packetMaxSizeType == 1): + return 64 + elif (packetMaxSizeType == 2): + return 128 + elif (packetMaxSizeType == 3): + return 256 + else: + return 32 + + def getStorageCapacity(self): + """ + Get the sensor storage capacity. + + @return int + The storage capacity. + """ + + return self.getSystemParameters()[2] + + def generateRandomNumber(self): + """ + Generate a random 32-bit decimal number. + + @author: Philipp Meisberger + + @return int + The generated random number + """ + packetPayload = ( + FINGERPRINT_GENERATERANDOMNUMBER, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + number = 0 + number = number | self.__leftShift(receivedPacketPayload[1], 24) + number = number | self.__leftShift(receivedPacketPayload[2], 16) + number = number | self.__leftShift(receivedPacketPayload[3], 8) + number = number | self.__leftShift(receivedPacketPayload[4], 0) + return number + + def downloadCharacteristics(self, charBufferNumber = 0x01): + """ + Download the finger characteristics of CharBuffer1 or CharBuffer2. + + @param integer(1 byte) charBufferNumber + + @return list + Return a list that contains 512 integer(1 byte) elements of the characteristic. + """ + + if ( charBufferNumber != 0x01 and charBufferNumber != 0x02 ): + raise ValueError('The given charbuffer number is invalid!') + + packetPayload = ( + FINGERPRINT_DOWNLOADCHARACTERISTICS, + charBufferNumber, + ) + + self.__writePacket(FINGERPRINT_COMMANDPACKET, packetPayload) + + ## Get first reply packet + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_ACKPACKET ): + raise Exception('The received packet is no ack packet!') + + ## DEBUG: The sensor will sent follow-up packets + if ( receivedPacketPayload[0] == FINGERPRINT_OK ): + pass + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_COMMUNICATION ): + raise Exception('Communication error') + + elif ( receivedPacketPayload[0] == FINGERPRINT_ERROR_DOWNLOADCHARACTERISTICS ): + raise Exception('Could not download characteristics') + + else: + raise Exception('Unknown error '+ hex(receivedPacketPayload[0])) + + completePayload = [] + + ## Get follow-up data packets until the last data packet is received + while ( receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + + receivedPacket = self.__readPacket() + + receivedPacketType = receivedPacket[0] + receivedPacketPayload = receivedPacket[1] + + if ( receivedPacketType != FINGERPRINT_DATAPACKET and receivedPacketType != FINGERPRINT_ENDDATAPACKET ): + raise Exception('The received packet is no data packet!') + + for i in range(0, len(receivedPacketPayload)): + completePayload.append(receivedPacketPayload[i]) + + return completePayload diff --git a/syncdb.pl b/syncdb.pl index 798016b..1e78afe 100644 --- a/syncdb.pl +++ b/syncdb.pl @@ -1,108 +1,48 @@ -#!/usr/bin/perl - -use strict; -use Data::Dumper; -use JSON::PP; -use DBI; -use DBD::SQLite; -use Encode; -my $strcfg = ""; -open(CFG,$ENV{HOME}.'/data/hourtrax.json'); -while (my $l = ){ - chomp($l); - $strcfg .= $l; -} -close(CFG); -my $cmd = "mount | grep ".$ENV{HOME}."/sync"; -my $ismnt = `$cmd`; -chomp($ismnt); -#print "Test 1: mounted:".$ismnt."\n"; -if ($ismnt ne ""){ - my $cmd = "sudo umount ".$ENV{HOME}."/sync"; - system($cmd); -} -my $data = JSON::PP::decode_json($strcfg); -my $conn = "sudo mount -t cifs -o username=".$data->{sync}->{user}.",password=".$data->{sync}->{pwd}." //".$data->{sync}->{host}.'/'.$data->{sync}->{path}." ".$ENV{HOME}.'/sync'; -#print $conn."\n"; -my $ret = `$conn`; -#print $ret."\n"; - -if ($ret =~ /unable to/){ - print "$ret\n"; - exit(1); -} else { - my $localdb = $ENV{HOME}.'/data/hourtrax.sqlite'; - my $remotedb = $ENV{HOME}.'/sync/'.$data->{sync}->{dbname}.".sqlite"; - if (-e $remotedb){ - my $rd = &dbquery('id',$data->{sync}->{sql},$remotedb) ; - foreach my $r (keys(%{$rd})){ - my $sql1= "select id,prename,surname from staff where id='".$r."'"; - my $rl = &dbquery('id',$sql1,$localdb); - if (keys(%{$rl}) > 0){ - if (($rd->{$r}->{prename} ne $rl->{$r}->{prename}) || - ($rd->{$r}->{surname} ne $rl->{$r}->{surname})){ - &dbexec("UPDATE staff set prename='".$rd->{$r}->{prename}."',surname='".$rd->{$r}->{surname}."' where id='".$r."'",$localdb); - } - my $sql2= "select id,idstaff,weekhours,startdate from contract where idstaff='".$r."' and startdate='".$rd->{$r}->{startdate}."'"; - my $rl2 = &dbquery('idstaff',$sql2,$localdb); - if (keys(%{$rl2}) > 0){ - if (($rl2->{$rd->{$r}->{id}}->{weekhours} ne $rl->{$r}->{weekhours}) && ($rl->{$r}->{weekhours} ne '')){ - &dbexec("UPDATE contract SET weekhours='".$rl->{$r}->{weekhours}."' WHERE id='".$rl2->{$rd->{$r}->{id}}->{id}."'",,$localdb); - } - }else { - &dbexec("INSERT INTO contract (idstaff,weekhours,startdate) VALUES ('".$rd->{$r}->{id}."','".$rd->{$r}->{weekhours}."',date('".$rd->{$r}->{startdate}."');",$localdb); - } - }else { - &dbexec("INSERT INTO staff (id,prename,surname) VALUES ('".$rd->{$r}->{id}."','".$rd->{$r}->{prename}."','".$rd->{$r}->{surname}."')",$data->{sync}->{sql},$localdb); - &dbexec("INSERT INTO contract (idstaff,weekhours,startdate) VALUES ('".$rd->{$r}->{id}."','".$rd->{$r}->{weekhours}."',date('".$rd->{$r}->{startdate}."');",$localdb); - } - } - } - -} -$cmd = "sudo umount ".$ENV{HOME}."/sync"; -system($cmd); -print "Normal END!\n"; - - -sub dbquery(){ - my $key = shift; - my $stat = shift; - my $file = shift; - my $retdata =(); - my $dbh = DBI->connect('DBI:SQLite:dbname='.$file,"","",{PrintError=>1,RaiseError=>1,AutoCommit=>1}) or exit(2); - #$stat = encode("utf8", $stat); - - #open FILE,">>/tmp/sql.log"; - print "Query with key: $stat\n"; - # close FILE; - my $sth = $dbh->prepare($stat); - $sth->execute() or exit(2); - while(my $data = $sth->fetchrow_hashref()) - { - if (exists $data->{$key}){ - foreach my $k (keys %{$data}){ - $retdata->{$data->{$key}}{$k} = decode( "utf8", $data->{$k}); - } - } - } - if (keys(%{$retdata}) == 0){ - $retdata =(); - } - $sth->finish(); - $dbh->disconnect(); - return $retdata; -} - -sub dbexec(){ - my $stat = shift; - my $file =shift; -# my $dbh = DBI->connect('DBI:SQLite:dbname='.$$file,"","",{PrintError=>1,AutoCommit=>1}) or exit(2); - print "Exec: $stat\n"; -# my $sth = $dbh->prepare($stat); -# my $rv =$dbh->do($stat) or exit(2); -# $dbh->disconnect(); - return 1; -# return $rv; -} - +#!/home/dks/perl5/perlbrew/perls/perl-5.28.1/bin/perl +use strict; +use FindBin qw($Bin); +# use lib ('CGI/api/lib/perl5'); +# use lib ('CGI/api/lib'); +use lib ($Bin.'/CGI/api/lib/perl5'); +use lib ($Bin.'/CGI/api/lib'); +# use CGI::Carp qw/fatalsToBrowser/; +use File::Basename; +use JSON::PP; +use Getopt::Long; +use dksconfig qw/$sitecfg/; +use dksdb; +use Encode; +my $sql = ""; +my @allsql = (); +my $file = ""; +GetOptions("sql|s=s" => \$sql,"file|f=s" => \$file); +if ($sql ne ""){ + @allsql = split(";",$sql); +} +elsif ($file ne "" && -e $file){ + my $strfile = ""; + open(SQF,$file); + while (my $l = ){ + $strfile .= $l; + } + close(SQF); + @allsql = split(";",$strfile); +} +my $db = dksdb->new(); +my $qall = (); +my $cnt = 0; +foreach my $sq (@allsql){ + my $qres = (); + if ($sq eq ""){next;} + if (lc($sql) =~ /^\s*select/){ + $qall->{$cnt} = $db->query($sq.";"); + } else { + $qall->{$cnt} = $db->exec($sq.";"); + } + $cnt++; +} +my $json = JSON::PP->new->utf8; +$json->pretty(1); +print $json->encode($qall); + + -- 2.39.5