Metadata-Version: 2.1
Name: fpscanner
Version: 0.1.1
Summary: UNKNOWN
Home-page: https://github.com/nikialeksey/fpscanner
Author: Alexey Niktin
Author-email: nikialeksey@gmail.com
License: MIT
Platform: UNKNOWN
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: POSIX
Classifier: Operating System :: POSIX :: BSD
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Description-Content-Type: text/markdown
Requires-Dist: Pillow (>=5.2.0)
Requires-Dist: pyserial (>=3.4)

# Python driver for fingerprint sensors by Zhiantec - ZFM-20 series

[![PyPI version](https://badge.fury.io/py/fpscanner.svg)](https://badge.fury.io/py/fpscanner)
[![PDD status](http://www.0pdd.com/svg?name=nikialeksey/fpscanner)](http://www.0pdd.com/p?name=nikialeksey/fpscanner)

## Is your scanner can be managed by this library?
If your scanner is ZFM-20 or his cheap clone then it possible. I made this library inspired by 
[pyfingerprint](https://github.com/bastianraschke/pyfingerprint), so it may also work with ZFM-60, ZFM-70, ZFM-100,
R303 and R305.

## Origin manuals
Fingerprint protocol specs are taken from 
[original ZHM-20 user manual](https://raw.githubusercontent.com/nikialeksey/fpscanner/master/ZFM+user+manualV15.pdf).

## Terminology

**Image**

  Image is a Fingerprint scanned grayscale image. Image can be scanned and stored in volatile image buffer.

**Characteristic**

  Characteristic is a fingerprint characteristic. It represented by a bytearray. Characteristic can be created from 
  fingerprint image and stored in volatile characteristic buffer.

**Template**

  Template is a registered fingerprint model stored in scanner nonvolatile memory. 
  We can not see or feel the template, we only can ask scanner if characteristic look like some template 
  in scanner memory.

## Working with sensor

### Handshake

First of all you need make a handshake to verify connection:
 ```python
with SerialPort(Serial(port='<COM1 or /dev/ttyUSB0>', baudrate=9600 * 6, timeout=2)) as port:
    rq = RqCommand(port)
    rs = RsSimple(port)
    Handshake(rq, rs).make()
```
As you see you will need to know serial port name of your scanner device. For windows users it may looks like `COM1`,
for unix users it may looks like `/dev/ttyUSB0`.

### Fingerprint image

More complex task - make an image of your fingerprint:
```python
with SerialPort(Serial(port='...', baudrate=9600 * 6, timeout=2)) as port:
    rq = RqCommand(port)
    rs = RsSimple(port)
    print 'Waiting for finger...'
    while not Scan(rq, rs).is_scanned():
        pass
    print 'Finger has been scanned! Downloading the finger image...'
    image = UpImage(rq, rs).image()
    image.show()
```

### Matching characteristics

Another more complex task - match characteristics of two fingerprints. Fingerprint scanner can matching only two 
fingerprints and it has two buffers for that operation - `RqCharBuffer1` and `RqCharBuffer2`.
```python
with SerialPort(Serial(port='...', baudrate=9600 * 6, timeout=2)) as port:
    rq = RqCommand(port)
    rs = RsSimple(port)
    print 'Wait for finger...'
    while not Scan(rq, rs).is_scanned():
        pass
    Img2Tz(rq, rs, RqCharBuffer1()).execute()

    print 'Once again...'
    while not Scan(rq, rs).is_scanned():
        pass
    Img2Tz(rq, rs, RqCharBuffer2()).execute()

    print 'Score {0}'.format(Match(rq, rs).score())
```

### Enroll fingerprint

Another complex task is enroll a finger.
```python
with SerialPort(Serial(port='...', baudrate=9600 * 6, timeout=2)) as port:
    rq = RqCommand(port)
    rs = RsSimple(port)
    print 'Wait for finger...'
    while not Scan(rq, rs).is_scanned():
        pass

    Img2Tz(rq, rs, RqCharBuffer1()).execute()
    searchResult = Search(rq, rs, start=0, count=TemplateCount(rq, rs).as_int()).execute()

    if searchResult.code() == 0:
        print 'Template already exist'
        exit(1)

    print 'Once again...'
    while not Scan(rq, rs).is_scanned():
        pass

    Img2Tz(rq, rs, RqCharBuffer2()).execute()
    score = Match(rq, rs).score()
    RegModel(rq, rs).execute()
    Store(rq, rs, RqCharBuffer1(), 1).execute()
    print 'Stored success!'
```

### Match fingerprint with it db saved version

```python
with SerialPort(Serial(port='...', baudrate=9600 * 6, timeout=2)) as port:
    rq = RqCommand(port)
    rs = RsSimple(port)
    while not Scan(rq, rs).is_scanned():
        pass
    Img2Tz(rq, rs, RqCharBuffer1()).execute()  # save scanned finger to the buffer 1

    templatesCount = TemplateCount(rq, rs).as_int()  # get all templates count
    searchResult = Search(rq, rs, start=0, count=templatesCount).execute()  # find finger in the db

    if searchResult.code() != 0:
        print('Finger has not been saved!')
    else:
        number = searchResult.number()  # finger index in the db
        print('Finger found in index {0}'.format(number))
        LoadChar(rq, rs, RqCharBuffer2(), number).execute()  # extract original template to the buffer 2

        print('Score {0}'.format(Match(rq, rs).score()))  # Match it!
```

@todo #1:30m Add deletion enrolled fingers

