@waiting/fingerprint-reader-bp8903
Version:
173 lines (154 loc) • 4.87 kB
JavaScript
/**
* @waiting/fingerprint-reader-bp8903
* 南天 BP8903 集成键盘 指纹采集、验证
*
* @version 2.1.2
* @author waiting
* @license MIT
* @link https://github.com/waitingsong/node-fingerprint-reader-bp8903#readme
*/
;
Object.defineProperty(exports, '__esModule', { value: true });
var win32Def = require('win32-def');
var log = require('@waiting/log');
var sharedCore = require('@waiting/shared-core');
var ffi = require('ffi');
var rxjs = require('rxjs');
var operators = require('rxjs/operators');
/** 初始化参数 */
const initialOpts = {
dllTxt: '',
dllSearchPath: '',
debug: false,
port: 0,
searchAll: false,
};
const dllFuncs = {
ABC_GetFeature: [win32Def.DTypes.INT, [win32Def.DTypes.BYTE, win32Def.DTypes.POINT, win32Def.DTypes.INT]],
ABC_GetTemplate: [win32Def.DTypes.INT, [win32Def.DTypes.BYTE, win32Def.DTypes.POINT, win32Def.DTypes.INT]],
ABC_Match: [win32Def.DTypes.INT, [win32Def.DTypes.POINT, win32Def.DTypes.POINT]],
};
function findDeviceList(deviceOpts, apib) {
const arr = [];
if (deviceOpts.port > 0) {
const device = findDevice(deviceOpts.port, deviceOpts, apib);
if (device.openPort > 0) {
arr.push(device);
}
}
else {
throw new Error('deviceOpts.port must be specified')
}
return arr
}
function findDevice(port, deviceOpts, apib) {
const device = {
apib,
deviceOpts,
inUse: false,
openPort: port,
};
return device
}
/** Sampling fingerprint once, return base64 */
function readOnce(device, bufLen = 1024) {
device.deviceOpts.debug && log.info('staring read once...');
const buf = Buffer.alloc(bufLen);
const code = device.apib.ABC_GetFeature(device.openPort, buf, bufLen);
const ret = code === 1
? buf
: Buffer.alloc(0);
if (device.deviceOpts.debug) {
log.info(`Fingerprint readOnce code: ${code}. (1:succeed, 0/others:failed)`);
}
return ret
}
/** Sampling fingerprint 3times, return base64 */
function readThrice(device, bufLen = 1024) {
device.deviceOpts.debug && log.info('staring read thrice...');
const buf = Buffer.alloc(bufLen);
const code = device.apib.ABC_GetTemplate(device.openPort, buf, bufLen);
const ret = code === 1
? buf
: Buffer.alloc(0);
if (device.deviceOpts.debug) {
log.info(`Fingerprint readThice code: ${code}. (1:succeed, 0/others:failed)`);
}
return ret
}
function compareFP(device, fp1, fp2) {
return new Promise(resolve => {
// const code = device.apib.ABC_Match(fp1, fp2)
device.apib.ABC_Match.async(fp1, fp2, (err, code) => {
resolve(code === 1 ? true : false);
return code
});
})
}
async function init(options) {
const deviceOpts = parseDeviceOpts(options);
const { debug } = deviceOpts;
if (debug) {
log.info(deviceOpts);
}
await sharedCore.validateDllFile(deviceOpts.dllTxt);
const apib = ffi.Library(deviceOpts.dllTxt, dllFuncs);
const devices = findDeviceList(deviceOpts, apib);
if (devices && devices.length) {
return devices
}
else {
throw new Error('未找到读卡设备')
}
}
/**
* Sample fingprint
*
* mode (default: strict):
* - simple: read once
* - strict: read 3 times
*/
function sampleFP(device, mode = 'strict') {
const buf = mode === 'simple' ? readOnce(device) : readThrice(device);
const ret = parseResultBuffer(buf);
return Promise.resolve(ret)
}
function verifyFP(device, fp) {
const fp1$ = rxjs.of(readOnce(device)).pipe(operators.tap(buf => {
if (!buf.byteLength) {
throw new Error('Sampling result empty. will retry once')
}
}), operators.retry(1), operators.tap(buf => {
if (!buf.byteLength) {
throw new Error('Sampling result empty')
}
}));
const fp2$ = rxjs.of(Buffer.from(fp)).pipe(operators.tap(buf => {
if (!buf.byteLength) {
throw new Error('Input fingerprint key being validated is invalid')
}
}));
const ret$ = rxjs.forkJoin(fp1$, fp2$).pipe(operators.mergeMap(([fp1, fp2]) => compareFP(device, fp1, fp2)));
return ret$.toPromise()
}
function parseDeviceOpts(options) {
const deviceOpts = Object.assign({}, initialOpts, options);
if (!options.dllTxt) {
throw new Error('params dllTxt undefined or blank')
}
else {
deviceOpts.dllTxt = sharedCore.normalize(deviceOpts.dllTxt);
}
return deviceOpts
}
/** convert sampling result to base64 */
function parseResultBuffer(buf) {
const ret = buf.byteLength
? buf.toString().replace(/\0+$/, '')
: '';
return ret
}
exports.initialOpts = initialOpts;
exports.init = init;
exports.sampleFP = sampleFP;
exports.verifyFP = verifyFP;