@pos-360/touch-id
Version:
The Touch ID API is used to interface with fingerprint scanning hardware.
291 lines (210 loc) • 9.57 kB
Markdown
# @pos-360/touch-id
A Node.js native module to interface with SecuGen fingerprint readers on Windows. This module provides an intuitive API for interacting with the SecuGen Hamster SDK (sgfplib.dll).
## Features
- **Device Management:** Open, close, and retrieve device information (image dimensions, contrast, brightness, etc.) from connected SecuGen fingerprint readers.
- **Capture & Template Creation:** Capture fingerprint images and create fingerprint templates for matching.
- **Template Matching:** Compare two fingerprint templates to determine a match.
- **Auto-On Mode:** Enable convenient "auto-on" mode to capture fingerprints as soon as a finger is placed on the reader.
- **Asynchronous Operations:** Fingerprint capture and template creation are asynchronous, allowing for non-blocking behavior.
## Installation
```bash
npm install @pos-360/touch-id
```
## Usage
### Import the module
```typescript
import { SecugenHandler, AutoOnEvent, SecugenErrors } from '@pos-360/touch-id';
```
### Create a new instance of the SecugenHandler class
```typescript
const secugen = new SecugenHandler();
```
### Open the device
```typescript
const openResult = secugen.open();
if (openResult.ok === false) {
console.error(openResult.message);
process.exit(1);
}
console.log("Opened device.");
```
### Get device information
```typescript
const deviceInfoResult = secugen.getDeviceInfo();
if (deviceInfoResult.ok === false) {
console.error(deviceInfoResult.message);
} else {
console.log("Device info:", deviceInfoResult);
}
```
### Capture a fingerprint and create a template
```typescript
const captureResult = await secugen.captureAndCreateTemplate();
if (captureResult.ok === false) {
console.error(captureResult.message);
} else {
console.log("Captured template:", captureResult);
}
```
### Compare two templates
```typescript
const compareResult = await secugen.compareTemplates(template1, template2);
if (compareResult.ok === false) {
console.error(compareResult.message);
} else {
console.log("Templates match:", compareResult.isMatch);
}
```
### Start auto-on mode
```typescript
const startAutoOnResult = await secugen.startAutoOn();
if (startAutoOnResult.ok === false) {
console.error(startAutoOnResult.message);
} else {
console.log("Started auto-on mode.");
secugen.subscribeToAutoOnEvent(AutoOnEvent.Capture, (payload) => {
if (payload.ok === false) {
console.error(payload.message);
} else {
console.log("Auto-on capture:", payload);
}
});
}
```
### Stop auto-on mode
```typescript
const stopAutoOnResult = secugen.stopAutoOn();
if (stopAutoOnResult.ok === false) {
console.error(stopAutoOnResult.message);
} else {
console.log("Stopped auto-on mode.");
}
```
### Capture a fingerprint from auto-on mode
```typescript
const captureResult = await secugen.captureFromAutoOn(5_000);
if (captureResult.ok === false) {
if (captureResult.code === SecugenErrors.CAPTURE_TIMEOUT) {
console.log("Capture timeout.");
} else {
console.error(captureResult.message);
}
} else {
console.log("Captured from auto-on:", captureResult);
}
```
### Cancel capture from auto-on mode
```typescript
const cancelResult = await secugen.cancelCaptureFromAutoOn();
if (cancelResult.ok === false) {
console.error(cancelResult.message);
} else {
console.log("Cancelled capture.");
}
```
### Close the device
```typescript
const closeResult = await secugen.close();
if (closeResult.ok === false) {
console.error(closeResult.message);
} else {
console.log("Closed device.");
}
```
## Error handling
The `SecugenHandler` methods return objects with the following structure:
```typescript
type GoodResult = {
ok: true;
// ... other properties
};
type BadResult = {
ok: false;
code: SecugenErrorCodes;
message: SecugenErrorMessages;
};
```
You can use the `ok` property to check if the operation was successful. If it
was not, you can use the `code` and `message` properties to get more
information about the error. The `SecugenErrors` object contains a list of all
possible error codes and messages.
## Example
```typescript
import {
SecugenHandler,
AutoOnEvent,
SecugenErrors,
} from "@pos-360/touch-id";
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
(async () => {
const secugen = new SecugenHandler();
const openResult = secugen.open();
if (openResult.ok === false) {
console.error(openResult.message);
process.exit(1);
}
console.log("Opened device.");
try {
await secugen.startAutoOn();
console.log("Started auto-on mode.");
const autoTemplateData = await secugen.captureFromAutoOn();
if (autoTemplateData.ok === false) {
if (autoTemplateData.code === SecugenErrors.CAPTURE_TIMEOUT) {
console.log("Capture timeout.");
} else {
console.error(autoTemplateData.message);
}
} else {
console.log("Auto-on template data:", autoTemplateData);
}
} catch (err) {
console.error(err);
} finally {
await secugen.close();
console.log("Closed device.");
}
})();
```
## API Reference
### `SecugenHandler` Class
- `new SecugenHandler()`: Creates a new `SecugenHandler` instance.
#### Methods
- `open(): DefaultResponse`: Opens the connected SecuGen device. Returns a `DefaultResponse` object indicating success or failure.
- `close(): Promise<DefaultResponse>`: Closes the SecuGen device. Returns a Promise that resolves with a `DefaultResponse` object indicating success or failure.
- `getDeviceInfo(): DeviceInfoResult`: Returns a `DeviceInfoResult` object with device information including `DeviceID`, `ImageWidth`, `ImageHeight`, `Contrast`, `Brightness`, `Gain`, and `ImageDPI`, or an error object if the device is not opened.
- `captureAndCreateTemplate(): Promise<CaptureResult>`: Asynchronously captures a fingerprint image and creates a template. Returns a Promise that resolves with a `CaptureResult` object containing the raw image data and the base64-encoded template, or an error object if the device is not opened or auto-on mode is active.
- `startAutoOn(): Promise<DefaultResponse>`: Starts the "auto-on" mode. The provided callback function will be invoked with events when fingers are placed/removed from the reader and when captures are made. Returns a Promise that resolves with a `DefaultResponse` object indicating success or failure.
- `stopAutoOn(): DefaultResponse`: Stops the "auto-on" mode. Returns a `DefaultResponse` object indicating success or failure.
- `captureFromAutoOn(timeout?: number): Promise<CaptureResult>`: Asynchronously captures a fingerprint in "auto-on" mode. Returns a Promise that resolves with a `CaptureResult` object containing the raw image data and the base64-encoded template, or an error object if auto-on mode is not active or a timeout occurs. An optional `timeout` parameter in milliseconds can be provided.
- `cancelCaptureFromAutoOn(): Promise<DefaultResponse>`: Cancels the capture operation initiated by `captureFromAutoOn`. Returns a Promise that resolves with a `DefaultResponse` object indicating success or failure.
- `compareTemplates(template1: string, template2: string): CompareResult`: Compares two base64-encoded fingerprint templates. Returns a `CompareResult` object indicating whether a match was found, or an error object if the device is not opened.
- `isAutoOnActive(): boolean`: Returns a boolean indicating whether "auto-on" mode is active.
- `subscribeToAutoOnEvent<T extends AutoOnEvent>(event: T, listener: (payload: AutoOnEventPayload<T>) => void): DefaultResponse`: Subscribes to an event in auto-on mode. Returns a `DefaultResponse` object indicating success or failure. Available events are `fingerOn`, `fingerOff`, `capture`, and `error`.
- `unsubscribeFromAutoOnEvent<T extends AutoOnEvent>(event: T, listener: (payload: AutoOnEventPayload<T>) => void): DefaultResponse`: Unsubscribes from an event in auto-on mode. Returns a `DefaultResponse` object indicating success or failure.
## Troubleshooting
### Module not initialized
If you get the error `Module not initialized` or the method calls return `{ ok: false, code: 'FAILURE_TO_INIT', message: 'Module not initialized' }`, then make sure that you have called `open()` before any other methods and that the SecuGen device is connected to your computer.
### Device not found
If you get the error `Device not found`, make sure that the SecuGen device is connected to your computer and that the driver is installed.
### USB Bandwidth is not sufficient
If you get the error `USB Bandwidth is not sufficient for image transfer`, try using a different USB port or a USB hub with its own power supply.
## Building
### Troubleshooting on Windows
If you have a problem building on Windows due to a `openssl != ''` error, make the following edit to `<node-gyp path>/gyp/pylib/gyp/input.py`:
```
diff --git a/gyp/pylib/gyp/input.py b/gyp/pylib/gyp/input.py
index 354958b..bb982eb 100644
--- a/gyp/pylib/gyp/input.py
+++ b/gyp/pylib/gyp/input.py
@@ -1190,7 +1190,7 @@ def EvalSingleCondition(cond_expr, true_dict, false_dict, phase, variables, buil
else:
ast_code = compile(cond_expr_expanded, "<string>", "eval")
cached_conditions_asts[cond_expr_expanded] = ast_code
- env = {"__builtins__": {}, "v": StrictVersion}
+ env = {"__builtins__": {"openssl_fips": ""}, "v": StrictVersion}
if eval(ast_code, env, variables):
return true_dict
return false_dict
```
## License
MIT