@samlab-corp/sfm-node 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +479 -0
  3. package/dist/commands/data.d.ts +29 -0
  4. package/dist/commands/data.d.ts.map +1 -0
  5. package/dist/commands/data.js +176 -0
  6. package/dist/commands/data.js.map +1 -0
  7. package/dist/commands/fingerprint.d.ts +132 -0
  8. package/dist/commands/fingerprint.d.ts.map +1 -0
  9. package/dist/commands/fingerprint.js +580 -0
  10. package/dist/commands/fingerprint.js.map +1 -0
  11. package/dist/commands/firmware.d.ts +37 -0
  12. package/dist/commands/firmware.d.ts.map +1 -0
  13. package/dist/commands/firmware.js +152 -0
  14. package/dist/commands/firmware.js.map +1 -0
  15. package/dist/commands/freescan.d.ts +68 -0
  16. package/dist/commands/freescan.d.ts.map +1 -0
  17. package/dist/commands/freescan.js +202 -0
  18. package/dist/commands/freescan.js.map +1 -0
  19. package/dist/commands/index.d.ts +88 -0
  20. package/dist/commands/index.d.ts.map +1 -0
  21. package/dist/commands/index.js +104 -0
  22. package/dist/commands/index.js.map +1 -0
  23. package/dist/commands/system.d.ts +82 -0
  24. package/dist/commands/system.d.ts.map +1 -0
  25. package/dist/commands/system.js +191 -0
  26. package/dist/commands/system.js.map +1 -0
  27. package/dist/constants/crypto.d.ts +11 -0
  28. package/dist/constants/crypto.d.ts.map +1 -0
  29. package/dist/constants/crypto.js +10 -0
  30. package/dist/constants/crypto.js.map +1 -0
  31. package/dist/constants/index.d.ts +6 -0
  32. package/dist/constants/index.d.ts.map +1 -0
  33. package/dist/constants/index.js +4 -0
  34. package/dist/constants/index.js.map +1 -0
  35. package/dist/constants/packet.d.ts +17 -0
  36. package/dist/constants/packet.d.ts.map +1 -0
  37. package/dist/constants/packet.js +17 -0
  38. package/dist/constants/packet.js.map +1 -0
  39. package/dist/constants/protocol.d.ts +653 -0
  40. package/dist/constants/protocol.d.ts.map +1 -0
  41. package/dist/constants/protocol.js +422 -0
  42. package/dist/constants/protocol.js.map +1 -0
  43. package/dist/core/client.d.ts +118 -0
  44. package/dist/core/client.d.ts.map +1 -0
  45. package/dist/core/client.js +320 -0
  46. package/dist/core/client.js.map +1 -0
  47. package/dist/core/crypto.d.ts +86 -0
  48. package/dist/core/crypto.d.ts.map +1 -0
  49. package/dist/core/crypto.js +248 -0
  50. package/dist/core/crypto.js.map +1 -0
  51. package/dist/core/errors.d.ts +25 -0
  52. package/dist/core/errors.d.ts.map +1 -0
  53. package/dist/core/errors.js +66 -0
  54. package/dist/core/errors.js.map +1 -0
  55. package/dist/core/index.d.ts +15 -0
  56. package/dist/core/index.d.ts.map +1 -0
  57. package/dist/core/index.js +10 -0
  58. package/dist/core/index.js.map +1 -0
  59. package/dist/core/packet.d.ts +126 -0
  60. package/dist/core/packet.d.ts.map +1 -0
  61. package/dist/core/packet.js +267 -0
  62. package/dist/core/packet.js.map +1 -0
  63. package/dist/core/serial.d.ts +123 -0
  64. package/dist/core/serial.d.ts.map +1 -0
  65. package/dist/core/serial.js +421 -0
  66. package/dist/core/serial.js.map +1 -0
  67. package/dist/core/tcp.d.ts +58 -0
  68. package/dist/core/tcp.d.ts.map +1 -0
  69. package/dist/core/tcp.js +219 -0
  70. package/dist/core/tcp.js.map +1 -0
  71. package/dist/index.d.ts +19 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +16 -0
  74. package/dist/index.js.map +1 -0
  75. package/package.json +49 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Samlab Corp
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,479 @@
1
+ # @samlab-corp/sfm-node
2
+
3
+ Node.js library for Suprema SFM (Suprema Fingerprint Module) devices based on SFM Protocol Manual V3.6.0.
4
+
5
+ Supports fingerprint enrollment, verification (1:1), identification (1:N), template management, firmware upgrade, and continuous scanning via Serial (RS232), RS422/485, or TCP/IP.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @samlab-corp/sfm-node
11
+ # or
12
+ yarn add @samlab-corp/sfm-node
13
+ ```
14
+
15
+ ### Requirements
16
+
17
+ - Node.js 18+
18
+ - A Suprema SFM fingerprint module connected via serial port or TCP/IP
19
+
20
+ ## Quick Start
21
+
22
+ ```typescript
23
+ import { SfmCommands } from "@samlab-corp/sfm-node";
24
+
25
+ // Create and connect in one step
26
+ const sfm = await SfmCommands.create({
27
+ portPath: "/dev/ttyUSB0",
28
+ baudRate: 115200,
29
+ });
30
+
31
+ // Enroll fingerprint (userId: 1)
32
+ await sfm.fingerprint.enroll(1);
33
+
34
+ // 1:1 Verification
35
+ await sfm.fingerprint.verify(1);
36
+
37
+ // 1:N Identification
38
+ await sfm.fingerprint.identify();
39
+
40
+ await sfm.disconnect();
41
+ ```
42
+
43
+ ## Constructor Options
44
+
45
+ ```typescript
46
+ const sfm = new SfmCommands({
47
+ portPath: "/dev/ttyUSB0", // Serial port path (used by create() / connect())
48
+ baudRate: 115200, // Serial baud rate (default: 115200)
49
+ debug: false, // Enable debug logging
50
+ commandTimeout: 20000, // Command response timeout in ms
51
+ readTimeout: 3000, // Data read timeout in ms
52
+ secureMode: false, // AES256 encryption mode
53
+ encryptionKey: Buffer, // AES256 encryption key (32 bytes)
54
+ iv: Buffer, // AES256 IV (16 bytes)
55
+ secureCode: Buffer, // Secure code
56
+ encryptionMode: "AES256_CBC", // Encryption mode ('AES256_CBC' | 'AES256_ECB')
57
+ networkMode: false, // RS422/485 network mode
58
+ terminalId: 0, // Network terminal ID
59
+ hexAsciiMode: false, // Hex-ASCII serial bridge mode
60
+ autoReconnect: {
61
+ // Auto-reconnect options
62
+ enabled: true,
63
+ interval: 3000,
64
+ maxRetries: 10,
65
+ },
66
+ });
67
+ ```
68
+
69
+ ## API Reference
70
+
71
+ ### Connection Management
72
+
73
+ | Method | Description |
74
+ | ------------------------------------------ | --------------------------------------------- |
75
+ | `SfmCommands.create(options)` | Create instance and connect in one step |
76
+ | `SfmCommands.listPorts()` | List available serial ports |
77
+ | `sfm.connect(portPath?)` | Connect to device (uses portPath from options if omitted) |
78
+ | `sfm.disconnect()` | Disconnect from device |
79
+ | `sfm.setSecureMode(enabled, options?)` | Toggle AES256 encryption mode |
80
+ | `sfm.setNetworkMode(enabled, terminalId?)` | Toggle RS422/485 network mode |
81
+ | `sfm.setOnDisconnect(callback)` | Register disconnect callback |
82
+ | `sfm.setAutoReconnect(options)` | Configure auto-reconnect |
83
+ | `sfm.setAutoReconnectCallbacks(callbacks)` | Register reconnect status callbacks |
84
+ | `sfm.isReconnecting` | Whether reconnection is in progress (boolean) |
85
+
86
+ ---
87
+
88
+ ### sfm.fingerprint — Enrollment / Verification / Identification
89
+
90
+ | Method | Description | Return Type |
91
+ | ----------------------------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------- |
92
+ | `enroll(userId, flag?, options?)` | Enroll fingerprint (auto-adapts to device ENROLL_MODE: 1-scan or 2-scan) | `EnrollResult` |
93
+ | `enrollScan1(userId, flag?, options?)` | First scan enrollment | `EnrollResult` |
94
+ | `enrollScan2(options?)` | Second scan enrollment (for SCAN2 modes) | `EnrollResult` |
95
+ | `verify(userId, options?)` | 1:1 Verification — match against a specific user | `VerifyResult` |
96
+ | `identify(options?)` | 1:N Identification — match against all enrolled fingerprints | `IdentifyResult` |
97
+ | `deleteTemplate(userId)` | Delete a specific user's fingerprint template | `CommandResult` |
98
+ | `deleteAllTemplates()` | Delete all fingerprint templates | `CommandResult` |
99
+ | `listUserIds(options?)` | List enrolled user IDs | `ListUserIdsResult` |
100
+ | `readTemplate(userId, options?)` | Read fingerprint template data from device (RTX protocol) | `{ success, templateData, error }` |
101
+ | `writeTemplate(userId, templateData, flag?, options?)` | Write fingerprint template to device (ET protocol, 384B chunks) | `{ success, userId, error }` |
102
+ | `writeTemplateMulti(userId, templateData, flag?, options?)` | Write fingerprint template to device (ETX extended protocol, multi-chunk) | `{ success, userId, error }` |
103
+ | `captureImage(options?)` | Capture fingerprint image (SI command) | `CaptureImageResult` |
104
+
105
+ #### Enrollment Flags
106
+
107
+ Flags used with `enroll`, `writeTemplate`, etc.:
108
+
109
+ | Flag | Value | Description |
110
+ | ----------------------- | ------ | ------------------------------- |
111
+ | `SFM_FLAG.NONE` | `0x00` | No flag (default) |
112
+ | `SFM_FLAG.CHECK_ID` | `0x70` | Check for duplicate ID |
113
+ | `SFM_FLAG.ADD_NEW` | `0x71` | Add fingerprint to existing ID |
114
+ | `SFM_FLAG.AUTO_ID` | `0x79` | Auto-assign ID |
115
+ | `SFM_FLAG.CHECK_FINGER` | `0x84` | Check for duplicate fingerprint |
116
+
117
+ #### Examples
118
+
119
+ ```typescript
120
+ // Basic enrollment
121
+ const result = await sfm.fingerprint.enroll(1);
122
+
123
+ // Enroll with duplicate fingerprint check
124
+ const result = await sfm.fingerprint.enroll(1, SFM_FLAG.CHECK_FINGER);
125
+
126
+ // With log callback
127
+ const result = await sfm.fingerprint.verify(1, {
128
+ onLog: (msg) => console.log(msg),
129
+ });
130
+
131
+ // Template backup / restore
132
+ const { templateData } = await sfm.fingerprint.readTemplate(1);
133
+ await sfm.fingerprint.writeTemplate(2, templateData, SFM_FLAG.ADD_NEW);
134
+
135
+ // List enrolled users
136
+ const list = await sfm.fingerprint.listUserIds();
137
+ // { success: true, userIds: [1, 2, 3], count: 3, error: null }
138
+
139
+ // Capture fingerprint image
140
+ const image = await sfm.fingerprint.captureImage();
141
+ // { success: true, imageData: Buffer, width: 256, height: 288, error: null }
142
+ ```
143
+
144
+ #### Return Types
145
+
146
+ ```typescript
147
+ interface EnrollResult {
148
+ success: boolean;
149
+ step: number; // Current scan step (1 or 2)
150
+ userId?: number;
151
+ error?: string;
152
+ }
153
+
154
+ interface VerifyResult {
155
+ success: boolean;
156
+ userId?: number;
157
+ error: string | null;
158
+ }
159
+
160
+ interface IdentifyResult {
161
+ success: boolean;
162
+ userId: number;
163
+ error: string | null;
164
+ }
165
+
166
+ interface ListUserIdsResult {
167
+ success: boolean;
168
+ userIds: number[];
169
+ count: number; // Number of enrolled templates
170
+ error: string | null;
171
+ }
172
+
173
+ interface CaptureImageResult {
174
+ success: boolean;
175
+ imageData: Buffer | null;
176
+ width: number;
177
+ height: number;
178
+ error: string | null;
179
+ }
180
+ ```
181
+
182
+ ---
183
+
184
+ ### sfm.system — System Configuration / Diagnostics
185
+
186
+ | Method | Description | Return Type |
187
+ | ------------------------------- | ------------------------------------------------------------- | ------------------------------------------------------- |
188
+ | `getSystemStatus()` | Get module and sensor status | `SystemStatusResult` |
189
+ | `getDeviceInfo()` | Get firmware version, build number, serial number | `{ firmwareVersion, buildNumber, serialNumber, error }` |
190
+ | `getParam(key)` | Read system parameter | `ParamResult` |
191
+ | `setParam(key, value)` | Write system parameter (RAM only) | `CommandResult` |
192
+ | `writeConfig(key, value)` | Write system parameter + save to flash (setParam + saveParam) | `CommandResult` |
193
+ | `saveParam()` | Save current parameters to flash | `CommandResult` |
194
+ | `reset()` | Reset module | `CommandResult` |
195
+ | `selfTest(command?, dataSize?)` | Communication self-test (data round-trip verification) | `SelfTestResult` |
196
+
197
+ #### Examples
198
+
199
+ ```typescript
200
+ // Device info
201
+ const info = await sfm.system.getDeviceInfo();
202
+ // { firmwareVersion: '3.10', buildNumber: '19.7.9.32', serialNumber: 12345, error: null }
203
+
204
+ // System status
205
+ const status = await sfm.system.getSystemStatus();
206
+ // { success: true, moduleStatusLabel: 'ALIVE', sensorStatusLabel: 'ALIVE', ... }
207
+
208
+ // Read parameter
209
+ const param = await sfm.system.getParam("SECURITY_LEVEL");
210
+ // { value: 0x33, error: null }
211
+
212
+ // Write parameter (string alias or numeric value)
213
+ await sfm.system.setParam("SECURITY_LEVEL", "HIGH");
214
+ await sfm.system.saveParam();
215
+
216
+ // Or use writeConfig to write + save in one call
217
+ await sfm.system.writeConfig("ENROLL_MODE", "SCAN2_MERGE");
218
+
219
+ // Self-test
220
+ const test = await sfm.system.selfTest();
221
+ // { success: true, sent: 65536, received: 65536, elapsed: 1200, error: null }
222
+ ```
223
+
224
+ #### Return Types
225
+
226
+ ```typescript
227
+ interface SystemStatusResult {
228
+ success: boolean;
229
+ moduleStatus?: number; // 0x30=ALIVE, 0x34=BUSY
230
+ moduleStatusLabel?: string;
231
+ sensorStatus?: number; // 0x30=ALIVE, 0x31=ERROR
232
+ sensorStatusLabel?: string;
233
+ error: string | null;
234
+ }
235
+
236
+ interface ParamResult {
237
+ value: number;
238
+ error: string | null;
239
+ }
240
+
241
+ interface CommandResult {
242
+ success: boolean;
243
+ error: string | null;
244
+ }
245
+
246
+ interface SelfTestResult {
247
+ success: boolean;
248
+ sent: number;
249
+ received: number;
250
+ elapsed: number; // ms
251
+ error: string | null;
252
+ }
253
+ ```
254
+
255
+ ---
256
+
257
+ ### sfm.freeScan — Continuous Fingerprint Scanning Mode
258
+
259
+ The device automatically scans fingerprints and delivers identification results via callback.
260
+
261
+ | Method | Description | Return Type |
262
+ | -------------------------- | ---------------------------------------------------------- | ---------------------- |
263
+ | `start(onResult, onLog?)` | Start FreeScan (auto-configures AUTO_RESPONSE + FREE_SCAN) | `{ success, message }` |
264
+ | `stop()` | Stop FreeScan | `{ success, message }` |
265
+ | `isRunning` | Whether FreeScan is active (boolean) | — |
266
+ | `isDeviceFreeScanActive()` | Check if device FREE_SCAN parameter is ON | `boolean` |
267
+ | `onDataHandler(handler)` | Register external data handler | — |
268
+ | `offDataHandler()` | Remove external data handler | — |
269
+ | `onErrorHandler(handler)` | Register external error handler | — |
270
+ | `offErrorHandler()` | Remove external error handler | — |
271
+
272
+ #### Examples
273
+
274
+ ```typescript
275
+ // Start FreeScan
276
+ await sfm.freeScan.start(
277
+ (result) => {
278
+ if (result.success) {
279
+ console.log(`Identified user: ${result.userId}`);
280
+ } else {
281
+ console.log("Unregistered fingerprint");
282
+ }
283
+ },
284
+ (msg) => console.log(msg), // Log callback (optional)
285
+ );
286
+
287
+ // Check status
288
+ console.log(sfm.freeScan.isRunning); // true
289
+
290
+ // Stop FreeScan
291
+ await sfm.freeScan.stop();
292
+ ```
293
+
294
+ #### Callback Types
295
+
296
+ ```typescript
297
+ interface FreeScanResult {
298
+ success: boolean;
299
+ userId?: number; // User ID on successful identification
300
+ flag?: number; // Error flag on failure
301
+ }
302
+
303
+ type FreeScanCallback = (result: FreeScanResult) => void;
304
+ ```
305
+
306
+ ---
307
+
308
+ ### sfm.firmware — Firmware Upgrade
309
+
310
+ | Method | Description |
311
+ | ---------------------------------------------------- | ---------------------------------------- |
312
+ | `upgrade(filePath, options?)` | Firmware upgrade via serial handshake |
313
+ | `upgradeViaProtocol(filePath, chunkSize?, options?)` | Firmware upgrade via SFM packet protocol |
314
+ | `loadFirmware(filePath)` | Load firmware file and build packet |
315
+
316
+ #### Examples
317
+
318
+ ```typescript
319
+ // Serial handshake method (typical)
320
+ await sfm.firmware.upgrade("/path/to/firmware.bin", {
321
+ onProgress: (percent, sent, total) => console.log(`${percent}%`),
322
+ onStatus: (msg) => console.log(msg),
323
+ });
324
+
325
+ // Protocol method
326
+ await sfm.firmware.upgradeViaProtocol("/path/to/firmware.bin");
327
+ ```
328
+
329
+ #### Options Type
330
+
331
+ ```typescript
332
+ interface FirmwareOptions {
333
+ onProgress?: (percent: number, sent: number, total: number) => void;
334
+ onStatus?: (message: string) => void;
335
+ }
336
+ ```
337
+
338
+ ---
339
+
340
+ ### sfm.data — Multi-Packet Data Transfer
341
+
342
+ Low-level multi-packet data transfer. Handles checksum verification and AES256 encryption automatically.
343
+
344
+ | Method | Description |
345
+ | ------------------------------------------- | ------------------------- |
346
+ | `send(command, data, chunkSize?, options?)` | Send multi-packet data |
347
+ | `recv(command, totalSize, options?)` | Receive multi-packet data |
348
+
349
+ ```typescript
350
+ await sfm.data.send(command, buffer, 0x4000, {
351
+ onProgress: (packetIndex, totalPackets) => { ... },
352
+ });
353
+
354
+ const data = await sfm.data.recv(command, totalSize);
355
+ ```
356
+
357
+ ---
358
+
359
+ ## System Parameter Key Reference
360
+
361
+ Keys and available values for `sfm.system.getParam(key)`, `sfm.system.setParam(key, value)`, and `sfm.system.writeConfig(key, value)`.
362
+
363
+ ### Timeout / Timing
364
+
365
+ | Key | Description | Values |
366
+ | ------------------ | -------------------------------------- | ------------------------------------------------------------------------------- |
367
+ | `TIMEOUT` | Fingerprint input wait time | `'INFINITE'`, `'1S'`, `'2S'`, `'3S'`, `'4S'`, `'5S'`, `'10S'`, `'15S'`, `'20S'` |
368
+ | `MATCHING_TIMEOUT` | Matching timeout | `'INFINITE'`, `'1S'`, `'3S'`, `'5S'`, `'10S'`, `'20S'` |
369
+ | `RESPONSE_DELAY` | Response delay | `'NONE'`, `'20MS'`, `'40MS'`, `'60MS'`, `'80MS'`, `'100MS'`, `'200MS'` |
370
+ | `FREE_SCAN_DELAY` | FreeScan consecutive recognition delay | `'NONE'`, `'1S'`, `'2S'`, `'3S'`, `'5S'`, `'10S'` |
371
+
372
+ ### Enrollment / Authentication
373
+
374
+ | Key | Description | Values |
375
+ | --------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------- |
376
+ | `ENROLL_MODE` | Enrollment mode | `'SCAN1'` (single scan), `'SCAN2_MERGE'` (2 scans merged), `'SCAN2_DUAL'` (2 scans stored separately) |
377
+ | `SECURITY_LEVEL` | Security level (FAR) | `'LOW'`, `'NORMAL'`, `'HIGH'`, `'HIGHEST'`, `'AUTO_NORMAL'`, `'AUTO_SECURE'`, `'AUTO_MORE_SECURE'` |
378
+ | `ENROLL_DISPLACEMENT` | Finger displacement during enrollment | `'NONE'`, `'1MM'`, `'3MM'`, `'5MM'`, `'10MM'` |
379
+ | `PROVISIONAL_ENROLL` | Provisional enrollment mode | `'PERMANENT'`, `'TEMPORARY'` |
380
+ | `PASS_WHEN_EMPTY` | Authentication result when DB is empty | `'FAIL'`, `'PASS'` |
381
+
382
+ ### Sensor / Image
383
+
384
+ | Key | Description | Values |
385
+ | -------------------- | --------------------------- | ---------------------------------------------------------------- |
386
+ | `SENSOR_TYPE` | Sensor type (read-only) | `'FC'`, `'OPTICAL'`, `'TC'`, `'OC'`, `'OL'`, `'FOH02'`, `'TS4'` |
387
+ | `SENSITIVITY` | Sensor sensitivity | `'LV0'` ~ `'LV7'` |
388
+ | `IMAGE_FORMAT` | Image transfer format | `'RAW_GRAY'`, `'BINARY'`, `'GRAY_4BIT'`, `'WSQ'` |
389
+ | `IMAGE_QUALITY` | Image quality threshold | `'WEAK'`, `'MODERATE'`, `'STRONG'`, `'STRONGEST'` |
390
+ | `ROTATE_IMAGE` | Sensor image rotation | `'NORMAL'`, `'FLIP'` |
391
+ | `ROTATION` | Matching rotation tolerance | `'DEG15'`, `'DEG30'`, `'DEG45'`, `'DEG60'`, `'DEG75'`, `'DEG90'` |
392
+ | `LIGHTING_CONDITION` | Lighting environment | `'OUTDOOR'`, `'INDOOR'` |
393
+
394
+ ### Communication
395
+
396
+ | Key | Description | Values |
397
+ | ------------------- | -------------------------- | ----------------------------------------------------------------------------------------- |
398
+ | `BAUDRATE` | Baud rate | `'9600'`, `'19200'`, `'38400'`, `'57600'`, `'115200'`, `'230400'`, `'460800'`, `'921600'` |
399
+ | `ENCRYPTION_MODE` | Encryption mode | `'OFF'`, `'ON'` |
400
+ | `ASCII_PACKET` | Packet exchange format | `'HEX'`, `'ASCII'` |
401
+ | `NETWORK_MODE` | Network communication mode | `'SINGLE'`, `'NETWORK'` |
402
+ | `SEND_SCAN_SUCCESS` | Send SCAN_SUCCESS response | `'OFF'`, `'ON'` |
403
+
404
+ ### Operation Mode
405
+
406
+ | Key | Description | Values |
407
+ | --------------- | --------------------------- | ------------------------------------------------- |
408
+ | `FREE_SCAN` | Idle-state auto scan | `'OFF'`, `'ON'` |
409
+ | `AUTO_RESPONSE` | GPIO/FreeScan auto response | `'OFF'`, `'HOST'`, `'AUX'`, `'BOTH'` |
410
+ | `FAST_MODE` | 1:N matching speed boost | `'OFF'`, `'LV1'` ~ `'LV4'`, `'FASTEST'`, `'AUTO'` |
411
+ | `WATCHDOG` | Watchdog timer | `'OFF'`, `'ON'` |
412
+
413
+ ### Template / Security
414
+
415
+ | Key | Description | Values |
416
+ | -------------------------- | ---------------------------- | ----------------------------------------- |
417
+ | `TEMPLATE_TYPE` | Template type | `'SUPREMA'`, `'ISO'`, `'ANSI'` |
418
+ | `ENHANCED_PRIVACY` | Enhanced privacy mode | `'OFF'`, `'ON'` |
419
+ | `FAKE_FINGER_DETECTION` | Fake finger detection | `'OFF'`, `'WEAK'`, `'NORMAL'`, `'STRONG'` |
420
+ | `CHECK_LATENT_FINGERPRINT` | Latent fingerprint detection | `'ENROLL_ONLY'`, `'NEVER'`, `'ALWAYS'` |
421
+
422
+ ### Read-Only Parameters
423
+
424
+ | Key | Description |
425
+ | ------------------ | ------------------------------------- |
426
+ | `TEMPLATE_SIZE` | Template size |
427
+ | `MODULE_ID` | Module ID |
428
+ | `FIRMWARE_VERSION` | Firmware version |
429
+ | `SERIAL_NUMBER` | Serial number |
430
+ | `BUILD_NUMBER` | Build number |
431
+ | `ENROLLED_FINGER` | Number of enrolled fingerprints |
432
+ | `AVAILABLE_FINGER` | Number of available fingerprint slots |
433
+ | `BAUDRATE2` | Secondary baud rate |
434
+ | `VOLTAGE_WARNING` | Voltage warning threshold |
435
+ | `POWER_OFF` | Auto power-off timeout |
436
+
437
+ ---
438
+
439
+ ## Error Codes
440
+
441
+ | Code | Value | Description |
442
+ | ------------------------ | ------ | ------------------------------------ |
443
+ | `SFM_ERROR.SUCCESS` | `0x61` | Success |
444
+ | `SFM_ERROR.SCAN_SUCCESS` | `0x62` | Scan success (intermediate response) |
445
+ | `SFM_ERROR.SCAN_FAIL` | `0x63` | Scan failed |
446
+ | `SFM_ERROR.NOT_FOUND` | `0x69` | Data not found |
447
+ | `SFM_ERROR.NOT_MATCH` | `0x6a` | Mismatch |
448
+ | `SFM_ERROR.TRY_AGAIN` | `0x6b` | Retry needed (poor image quality) |
449
+ | `SFM_ERROR.TIME_OUT` | `0x6c` | Timeout |
450
+ | `SFM_ERROR.MEM_FULL` | `0x6d` | Memory full |
451
+ | `SFM_ERROR.EXIST_ID` | `0x6e` | ID already exists |
452
+ | `SFM_ERROR.CONTINUE` | `0x74` | Continue data transfer |
453
+ | `SFM_ERROR.UNSUPPORTED` | `0x75` | Unsupported command |
454
+
455
+ ## TypeScript
456
+
457
+ All types are exported:
458
+
459
+ ```typescript
460
+ import type {
461
+ SfmClientOptions,
462
+ EnrollResult,
463
+ VerifyResult,
464
+ IdentifyResult,
465
+ CommandResult,
466
+ ListUserIdsResult,
467
+ CaptureImageResult,
468
+ SystemStatusResult,
469
+ ParamResult,
470
+ SelfTestResult,
471
+ FreeScanResult,
472
+ FreeScanCallback,
473
+ FirmwareOptions,
474
+ } from "@samlab-corp/sfm-node";
475
+ ```
476
+
477
+ ## License
478
+
479
+ [MIT](LICENSE)
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Multi-packet data transfer/receive commands
3
+ */
4
+ import type { SfmClient } from "../core";
5
+ export interface MultiPacketOptions {
6
+ onProgress?: (packetIndex: number, totalPackets: number) => void;
7
+ }
8
+ /**
9
+ * Even/Odd byte checksum calculation
10
+ */
11
+ export declare function calcEvenOddChecksum(data: Buffer | Uint8Array): number;
12
+ export declare class DataCommands {
13
+ private client;
14
+ constructor(client: SfmClient);
15
+ /**
16
+ * Multi-packet data send
17
+ */
18
+ send(command: number, data: Buffer, chunkSize?: number, options?: MultiPacketOptions): Promise<void>;
19
+ /**
20
+ * Multi-packet data receive
21
+ */
22
+ recv(command: number, totalSize: number, options?: MultiPacketOptions): Promise<Buffer>;
23
+ private _sendMultiPacket;
24
+ private _recvMultiPacket;
25
+ private _sendResponseFlag;
26
+ private _writeWithTimeout;
27
+ private _readWithTimeout;
28
+ }
29
+ //# sourceMappingURL=data.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data.d.ts","sourceRoot":"","sources":["../../src/commands/data.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;CAClE;AAgBD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,MAAM,CAkBrE;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,SAAS;IAErC;;OAEG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,SAAS,EAClB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC;IAYhB;;OAEG;IACG,IAAI,CACR,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,CAAC;YAQJ,gBAAgB;YAiFhB,gBAAgB;YAwEhB,iBAAiB;YAOjB,iBAAiB;YAYjB,gBAAgB;CAW/B"}