UNPKG

@waiting/fingerprint-reader-bp8903

Version:
173 lines (154 loc) 4.87 kB
/** * @waiting/fingerprint-reader-bp8903 * 南天 BP8903 集成键盘 指纹采集、验证 * * @version 2.1.2 * @author waiting * @license MIT * @link https://github.com/waitingsong/node-fingerprint-reader-bp8903#readme */ 'use strict'; 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;