@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
@@ -0,0 +1,580 @@
1
+ /**
2
+ * Fingerprint enroll/verify/identify/capture commands
3
+ */
4
+ import { SFM_ERROR, SFM_FLAG, SFM_CMD } from "../constants";
5
+ import { buildNormalPacket } from "../core/packet";
6
+ export class FingerprintCommands {
7
+ constructor(client) {
8
+ this.client = client;
9
+ this.system = null;
10
+ }
11
+ /** @internal Set SystemCommands reference */
12
+ _setSystemCommands(system) {
13
+ this.system = system;
14
+ }
15
+ /**
16
+ * Enroll scan 1 - send ES command + read 0x62 (scan success) + 0x61 (template 1 saved)
17
+ */
18
+ async enrollScan1(userId, flag = SFM_FLAG.NONE, { onLog } = {}) {
19
+ if (userId == null) {
20
+ return { success: false, step: 1, error: "userId is required" };
21
+ }
22
+ const log = (msg) => {
23
+ onLog?.(msg);
24
+ };
25
+ log(`[ENROLL] Scan 1 started - userId: ${userId}`);
26
+ const response = await this.client.sendCommand(SFM_CMD.ES, userId, 0, flag);
27
+ log(`[ENROLL] Response: flag=0x${response.flag?.toString(16)}, param=${response.param}, valid=${response.valid}`);
28
+ if (!response.valid) {
29
+ return { success: false, step: 1, error: response.error || "unknown error" };
30
+ }
31
+ if (response.flag !== SFM_ERROR.SCAN_SUCCESS) {
32
+ return {
33
+ success: false,
34
+ step: 1,
35
+ error: `Scan 1 failed: 0x${response.flag?.toString(16) ?? "??"}`,
36
+ };
37
+ }
38
+ log(`[ENROLL] Scan 1 success (0x62), waiting for template save...`);
39
+ const saveResponse = await this.client.receiveResponse(this.client.commandTimeout);
40
+ log(`[ENROLL] Save 1 response: flag=0x${saveResponse.flag?.toString(16)}, valid=${saveResponse.valid}`);
41
+ if (!saveResponse.valid || saveResponse.flag !== SFM_ERROR.SUCCESS) {
42
+ return {
43
+ success: false,
44
+ step: 1,
45
+ error: saveResponse.error ||
46
+ `Save 1 failed: 0x${saveResponse.flag?.toString(16)}`,
47
+ };
48
+ }
49
+ log(`[ENROLL] Template 1 saved`);
50
+ return { success: true, step: 1, userId: saveResponse.param ?? 0 };
51
+ }
52
+ /**
53
+ * Enroll scan 2 - read 0x62 (scan success) + 0x61 (template 2 saved)
54
+ */
55
+ async enrollScan2({ onLog } = {}) {
56
+ const log = (msg) => {
57
+ onLog?.(msg);
58
+ };
59
+ log(`[ENROLL] Waiting for scan 2...`);
60
+ const scanResponse = await this.client.receiveResponse(this.client.commandTimeout);
61
+ log(`[ENROLL] Scan 2 response: flag=0x${scanResponse.flag?.toString(16)}, valid=${scanResponse.valid}`);
62
+ if (!scanResponse.valid) {
63
+ return { success: false, step: 2, error: scanResponse.error || "unknown error" };
64
+ }
65
+ if (scanResponse.flag !== SFM_ERROR.SCAN_SUCCESS) {
66
+ return {
67
+ success: false,
68
+ step: 2,
69
+ error: `Scan 2 failed: 0x${scanResponse.flag?.toString(16) ?? "??"}`,
70
+ };
71
+ }
72
+ log(`[ENROLL] Scan 2 success (0x62), waiting for template save...`);
73
+ const saveResponse = await this.client.receiveResponse(this.client.commandTimeout);
74
+ log(`[ENROLL] Save 2 response: flag=0x${saveResponse.flag?.toString(16)}, valid=${saveResponse.valid}`);
75
+ if (!saveResponse.valid || saveResponse.flag !== SFM_ERROR.SUCCESS) {
76
+ return {
77
+ success: false,
78
+ step: 2,
79
+ error: saveResponse.error ||
80
+ `Save 2 failed: 0x${saveResponse.flag?.toString(16)}`,
81
+ };
82
+ }
83
+ log(`[ENROLL] Template 2 saved - enrollment complete`);
84
+ return { success: true, step: 2, userId: saveResponse.param ?? 0 };
85
+ }
86
+ /**
87
+ * Enroll (automatically adapts to current ENROLL_MODE setting)
88
+ *
89
+ * - SCAN1 (0x30): 1 scan only
90
+ * - SCAN2_MERGE (0x31) / SCAN2_DUAL (0x41): scan 1 + scan 2
91
+ */
92
+ async enroll(userId, flag = SFM_FLAG.NONE, { onLog } = {}) {
93
+ const log = (msg) => {
94
+ onLog?.(msg);
95
+ };
96
+ // Read current ENROLL_MODE from device
97
+ let enrollMode = 0x31; // default: SCAN2_MERGE
98
+ if (this.system) {
99
+ const param = await this.system.getParam("ENROLL_MODE");
100
+ if (!param.error && param.value != null) {
101
+ enrollMode = param.value;
102
+ log(`[ENROLL] ENROLL_MODE: 0x${enrollMode.toString(16)}`);
103
+ }
104
+ }
105
+ const result1 = await this.enrollScan1(userId, flag, { onLog });
106
+ if (!result1.success)
107
+ return result1;
108
+ // SCAN1 mode: single scan is enough
109
+ if (enrollMode === 0x30) {
110
+ log("[ENROLL] SCAN1 mode — enrollment complete");
111
+ return result1;
112
+ }
113
+ // SCAN2_MERGE / SCAN2_DUAL: need second scan
114
+ return this.enrollScan2({ onLog });
115
+ }
116
+ /**
117
+ * 1:1 검증 (VS: 0x08)
118
+ */
119
+ async verify(userId, { onLog } = {}) {
120
+ if (userId == null) {
121
+ return { success: false, error: "userId is required" };
122
+ }
123
+ const log = (msg) => {
124
+ onLog?.(msg);
125
+ };
126
+ log(`[VERIFY] 1:1 verification started - userId: ${userId}`);
127
+ const response = await this.client.sendCommand(SFM_CMD.VS, userId, 0, 0);
128
+ log(`[VERIFY] Response: flag=0x${response.flag?.toString(16)}, param=${response.param}, valid=${response.valid}`);
129
+ if (!response.valid) {
130
+ return { success: false, error: response.error || "unknown error" };
131
+ }
132
+ let lastResponse = response;
133
+ let scanCount = 1;
134
+ while (lastResponse.flag === SFM_ERROR.SCAN_SUCCESS) {
135
+ log(`[VERIFY] Scan #${scanCount} success (0x62), waiting for match...`);
136
+ lastResponse = await this.client.receiveResponse(this.client.commandTimeout);
137
+ scanCount++;
138
+ log(`[VERIFY] Response #${scanCount}: flag=0x${lastResponse.flag?.toString(16)}, param=${lastResponse.param}, valid=${lastResponse.valid}`);
139
+ if (!lastResponse.valid) {
140
+ return { success: false, error: lastResponse.error || "unknown error" };
141
+ }
142
+ }
143
+ return {
144
+ success: lastResponse.flag === SFM_ERROR.SUCCESS,
145
+ userId: lastResponse.param,
146
+ error: lastResponse.flag !== SFM_ERROR.SUCCESS
147
+ ? `Verification failed: 0x${lastResponse.flag?.toString(16) ?? "??"}`
148
+ : null,
149
+ };
150
+ }
151
+ /**
152
+ * 1:N 식별 (IS: 0x11)
153
+ */
154
+ async identify({ onLog } = {}) {
155
+ const log = (msg) => {
156
+ onLog?.(msg);
157
+ };
158
+ log(`[IDENTIFY] 1:N identification started`);
159
+ const response = await this.client.sendCommand(SFM_CMD.IS, 0, 0, 0);
160
+ log(`[IDENTIFY] Response: flag=0x${response.flag?.toString(16)}, param=${response.param}, valid=${response.valid}`);
161
+ if (!response.valid) {
162
+ return { success: false, userId: 0, error: response.error || "unknown error" };
163
+ }
164
+ let lastResponse = response;
165
+ let scanCount = 1;
166
+ while (lastResponse.flag === SFM_ERROR.SCAN_SUCCESS) {
167
+ log(`[IDENTIFY] Scan #${scanCount} success (0x62), waiting for match...`);
168
+ lastResponse = await this.client.receiveResponse(this.client.commandTimeout);
169
+ scanCount++;
170
+ log(`[IDENTIFY] Response #${scanCount}: flag=0x${lastResponse.flag?.toString(16)}, param=${lastResponse.param}, valid=${lastResponse.valid}`);
171
+ if (!lastResponse.valid) {
172
+ return { success: false, userId: 0, error: lastResponse.error || "unknown error" };
173
+ }
174
+ }
175
+ return {
176
+ success: lastResponse.flag === SFM_ERROR.SUCCESS,
177
+ userId: lastResponse.param ?? 0,
178
+ error: lastResponse.flag !== SFM_ERROR.SUCCESS
179
+ ? `Identification failed: 0x${lastResponse.flag?.toString(16) ?? "??"}`
180
+ : null,
181
+ };
182
+ }
183
+ /**
184
+ * Delete specific template (DT: 0x16)
185
+ */
186
+ async deleteTemplate(userId) {
187
+ if (userId == null) {
188
+ return { success: false, error: "userId is required" };
189
+ }
190
+ const response = await this.client.sendCommand(SFM_CMD.DT, userId, 0, 0);
191
+ if (!response.valid) {
192
+ return { success: false, error: response.error || "unknown error" };
193
+ }
194
+ return {
195
+ success: response.flag === SFM_ERROR.SUCCESS,
196
+ error: response.flag !== SFM_ERROR.SUCCESS
197
+ ? `Delete failed: 0x${response.flag?.toString(16) ?? "??"}`
198
+ : null,
199
+ };
200
+ }
201
+ /**
202
+ * Delete all templates (DA: 0x17)
203
+ */
204
+ async deleteAllTemplates() {
205
+ const response = await this.client.sendCommand(SFM_CMD.DA, 0, 0, 0);
206
+ if (!response.valid) {
207
+ return { success: false, error: response.error || "unknown error" };
208
+ }
209
+ return {
210
+ success: response.flag === SFM_ERROR.SUCCESS,
211
+ error: response.flag !== SFM_ERROR.SUCCESS ? "Delete all failed" : null,
212
+ };
213
+ }
214
+ /**
215
+ * List enrolled user IDs (LT: 0x18)
216
+ */
217
+ async listUserIds({ onLog } = {}) {
218
+ const log = (msg) => {
219
+ onLog?.(msg);
220
+ };
221
+ log("[LIST] Fetching user ID list");
222
+ const response = await this.client.sendCommand(SFM_CMD.LT, 0, 0, 0);
223
+ if (!response.valid) {
224
+ return { success: false, userIds: [], count: 0, error: response.error || "unknown error" };
225
+ }
226
+ if (response.flag !== SFM_ERROR.SUCCESS) {
227
+ return {
228
+ success: false,
229
+ userIds: [],
230
+ count: 0,
231
+ error: `List failed: 0x${response.flag?.toString(16) ?? "??"}`,
232
+ };
233
+ }
234
+ const count = response.param ?? 0;
235
+ const dataSize = response.size ?? 0;
236
+ log(`[LIST] Enrolled users: ${count}, data size: ${dataSize}`);
237
+ if (count === 0 || dataSize === 0) {
238
+ return { success: true, userIds: [], count: 0, error: null };
239
+ }
240
+ const rawData = await this.client.serial.read(dataSize, this.client.commandTimeout);
241
+ if (rawData.length < dataSize) {
242
+ return { success: false, userIds: [], count: 0, error: `Incomplete data: received ${rawData.length}/${dataSize} bytes` };
243
+ }
244
+ log(`[LIST] Raw data (hex): ${Buffer.from(rawData).toString("hex").match(/../g)?.join(" ") ?? ""}`);
245
+ const allIds = [];
246
+ for (let i = 0; i + 4 <= rawData.length; i += 4) {
247
+ allIds.push(rawData.readUInt32LE(i));
248
+ }
249
+ const userIds = [...new Set(allIds)];
250
+ log(`[LIST] Templates: ${count}, unique users: ${userIds.length}, IDs: [${userIds.join(", ")}]`);
251
+ return { success: true, userIds, count, error: null };
252
+ }
253
+ /**
254
+ * Read template from device (RTX: 0x89, ping-pong protocol)
255
+ *
256
+ * RTX response Size field: (templateCount << 16) | templateSize
257
+ * e.g. 131456 = 0x00020180 → count=2, size=384
258
+ *
259
+ * Flow: send RTX → read 384B data → send ACK (RTX) → read 384B data → ...
260
+ * Device flag: 0x74 (CONTINUE) = more chunks, 0x61 (SUCCESS) = last chunk.
261
+ */
262
+ async readTemplate(userId, { onLog } = {}) {
263
+ if (userId == null) {
264
+ return { success: false, templateData: null, error: "userId is required" };
265
+ }
266
+ const log = (msg) => {
267
+ onLog?.(msg);
268
+ };
269
+ // Flag=0: read all templates for this userId
270
+ log(`[RTX] Reading template for userId: ${userId}`);
271
+ const response = await this.client.sendCommand(SFM_CMD.RTX, userId, 384, 0);
272
+ log(`[RTX] Response: flag=0x${response.flag?.toString(16)}, param=${response.param}, size=${response.size}, valid=${response.valid}`);
273
+ if (!response.valid) {
274
+ return { success: false, templateData: null, error: response.error || "unknown error" };
275
+ }
276
+ if (response.flag !== SFM_ERROR.CONTINUE && response.flag !== SFM_ERROR.SUCCESS) {
277
+ return {
278
+ success: false,
279
+ templateData: null,
280
+ error: `Read template failed: 0x${response.flag?.toString(16) ?? "??"}`,
281
+ };
282
+ }
283
+ // Parse RTX response size: (templateCount << 16) | templateSize
284
+ const rawSize = response.size ?? 0;
285
+ const templateCount = (rawSize >>> 16) & 0xffff;
286
+ const templateSize = rawSize & 0xffff;
287
+ log(`[RTX] templateCount=${templateCount}, templateSize=${templateSize}B`);
288
+ if (templateSize === 0) {
289
+ return { success: false, templateData: null, error: "No template data (size=0)" };
290
+ }
291
+ const chunks = [];
292
+ const MAX_TEMPLATE_CHUNKS = 100;
293
+ const totalChunks = templateCount || 1;
294
+ if (totalChunks > MAX_TEMPLATE_CHUNKS) {
295
+ return { success: false, templateData: null, error: `Unreasonable chunk count: ${totalChunks} (max ${MAX_TEMPLATE_CHUNKS})` };
296
+ }
297
+ for (let i = 0; i < totalChunks; i++) {
298
+ log(`[RTX] Receiving chunk ${i + 1}/${totalChunks}...`);
299
+ const readTimeout = Math.max(this.client.commandTimeout, Math.ceil(templateSize / 100) + 5000);
300
+ // Extended Data Transfer Protocol:
301
+ // Data Packet Header(13B) + Data Body(templateSize) + Data Checksum(4B)
302
+ const dataPacketHeader = await this.client.serial.read(13, readTimeout);
303
+ log(`[RTX] Data packet header: ${Buffer.from(dataPacketHeader).toString("hex")}`);
304
+ const chunkData = await this.client.serial.read(templateSize, readTimeout);
305
+ if (!chunkData || chunkData.length < templateSize) {
306
+ return {
307
+ success: false,
308
+ templateData: null,
309
+ error: `Incomplete read: ${chunkData?.length ?? 0}/${templateSize}B`,
310
+ };
311
+ }
312
+ // Read and validate 4-byte checksum
313
+ const checksumData = await this.client.serial.read(4, readTimeout);
314
+ const receivedChecksum = checksumData.readUInt32LE(0);
315
+ let calculatedChecksum = 0;
316
+ for (let j = 0; j < chunkData.length; j++) {
317
+ calculatedChecksum += chunkData[j];
318
+ }
319
+ calculatedChecksum = calculatedChecksum >>> 0;
320
+ log(`[RTX] Chunk ${i + 1} received: ${chunkData.length}B, checksum: received=0x${receivedChecksum.toString(16)}, calculated=0x${calculatedChecksum.toString(16)}`);
321
+ if (receivedChecksum !== calculatedChecksum) {
322
+ return {
323
+ success: false,
324
+ templateData: null,
325
+ error: `Checksum mismatch at chunk ${i + 1}: received=0x${receivedChecksum.toString(16)}, calculated=0x${calculatedChecksum.toString(16)}`,
326
+ };
327
+ }
328
+ chunks.push(chunkData.subarray(0, templateSize));
329
+ // Send DATA_OK(0x83) ACK to trigger next data packet
330
+ const DATA_OK = 0x83;
331
+ log(`[RTX] Sending DATA_OK ACK...`);
332
+ const ackPacket = buildNormalPacket(SFM_CMD.RTX, 0, 0, DATA_OK);
333
+ await this.client._writePacket(ackPacket);
334
+ log(`[RTX] ACK sent: ${Buffer.from(ackPacket).toString("hex")}`);
335
+ }
336
+ const templateData = Buffer.concat(chunks);
337
+ log(`[RTX] Template received: ${templateData.length}B (${chunks.length} chunks)`);
338
+ return { success: true, templateData, error: null };
339
+ }
340
+ /**
341
+ * Write template to device (ET: 0x07 — Simple Template Enrollment)
342
+ *
343
+ * Kiosk 호환 프로토콜 (rs232/fingerPrinter.js enrollByTemplate):
344
+ * 1. [Command Packet 13B] + [Template Data] + [END 0x0A] 를 한 번에 전송
345
+ * 2. 디바이스로부터 2개 응답 수신 (스캔 처리 + 최종 결과)
346
+ *
347
+ * Size field = templateData.length (원본 크기 그대로)
348
+ * 384B 단위 chunk를 각각 별도의 ET 호출로 전송
349
+ */
350
+ async writeTemplate(userId, templateData, flag = SFM_FLAG.ADD_NEW, { onLog } = {}) {
351
+ if (userId == null) {
352
+ return { success: false, error: "userId is required" };
353
+ }
354
+ const log = (msg) => {
355
+ onLog?.(msg);
356
+ };
357
+ const CHUNK = 384;
358
+ const totalSize = templateData.length;
359
+ const chunkCount = Math.ceil(totalSize / CHUNK);
360
+ log(`[ET] Writing template for userId: ${userId}, totalSize: ${totalSize}B, chunks: ${chunkCount}`);
361
+ let lastResponseParam = userId;
362
+ for (let i = 0; i < chunkCount; i++) {
363
+ const offset = i * CHUNK;
364
+ const currentChunkSize = Math.min(CHUNK, totalSize - offset);
365
+ const chunkData = templateData.subarray(offset, offset + currentChunkSize);
366
+ log(`[ET] Sending chunk ${i + 1}/${chunkCount}: ${currentChunkSize}B`);
367
+ // Build command packet (13B)
368
+ const cmdPacket = buildNormalPacket(SFM_CMD.ET, userId, currentChunkSize, flag);
369
+ // ET 프로토콜: [Command 13B] + [Template Data] + [END 0x0A]
370
+ const endByte = Buffer.from([0x0a]);
371
+ const combined = Buffer.concat([cmdPacket, chunkData, endByte]);
372
+ log(`[ET] Packet: ${Buffer.from(combined).toString("hex")}`);
373
+ await this.client.serial.write(combined);
374
+ // ET는 2개 응답을 수신
375
+ // 응답 1: 처리 중간 응답
376
+ const response1 = await this.client.receiveResponse(this.client.commandTimeout);
377
+ log(`[ET] Response 1: flag=0x${response1.flag?.toString(16)}, param=${response1.param}, valid=${response1.valid}`);
378
+ if (!response1.valid) {
379
+ return { success: false, error: `ET chunk ${i + 1} response 1 invalid: ${response1.error}` };
380
+ }
381
+ // 응답 2: 최종 결과
382
+ const response2 = await this.client.receiveResponse(this.client.commandTimeout);
383
+ log(`[ET] Response 2: flag=0x${response2.flag?.toString(16)}, param=${response2.param}, valid=${response2.valid}`);
384
+ if (!response2.valid) {
385
+ return { success: false, error: `ET chunk ${i + 1} response 2 invalid: ${response2.error}` };
386
+ }
387
+ if (response2.flag !== SFM_ERROR.SUCCESS) {
388
+ return {
389
+ success: false,
390
+ error: `ET chunk ${i + 1} failed: 0x${response2.flag?.toString(16) ?? "??"}`,
391
+ };
392
+ }
393
+ lastResponseParam = response2.param ?? userId;
394
+ log(`[ET] Chunk ${i + 1}/${chunkCount} enrolled successfully`);
395
+ }
396
+ log(`[ET] Template written successfully (${chunkCount} chunks, ${totalSize}B)`);
397
+ return { success: true, userId: lastResponseParam, error: null };
398
+ }
399
+ /**
400
+ * Write template to device (ETX: 0x87 — Extended Template Enrollment)
401
+ *
402
+ * Extended Data Transfer Protocol (Appendix B):
403
+ * Supports multi-chunk: 768B → 2 chunks of 384B sent in one ETX session.
404
+ *
405
+ * 1. sendCommand(ETX, userId, sizeField, flag) → SUCCESS(0x61)
406
+ * sizeField: (templateCount << 24) | (enrollCount << 16) | chunkSize
407
+ * 2. For each chunk:
408
+ * Data Packet Header(13B) + Data Body(384B) + Data Checksum(4B)
409
+ * → DATA_OK(0x83) 응답 수신
410
+ */
411
+ async writeTemplateMulti(userId, templateData, flag = SFM_FLAG.NONE, { onLog } = {}) {
412
+ if (userId == null) {
413
+ return { success: false, error: "userId is required" };
414
+ }
415
+ const log = (msg) => {
416
+ onLog?.(msg);
417
+ };
418
+ const CHUNK = 384;
419
+ const totalSize = templateData.length;
420
+ const templateCount = Math.ceil(totalSize / CHUNK);
421
+ const chunkSize = Math.min(totalSize, CHUNK);
422
+ if (templateCount > 255) {
423
+ return { success: false, error: `Template too large: ${templateCount} chunks exceeds 255 max` };
424
+ }
425
+ // ETX Size: (templateCount << 24) | (enrollCount << 16) | chunkSize
426
+ // enrollCount=1: 각 템플릿을 1번씩만 저장
427
+ const sizeField = (templateCount << 24) | (1 << 16) | chunkSize;
428
+ log(`[ETX] Writing template for userId: ${userId}, totalSize: ${totalSize}B, chunks: ${templateCount}, sizeField=0x${sizeField.toString(16)}`);
429
+ // Step 1: ETX 명령 패킷 전송 + SUCCESS(0x61) 응답 대기
430
+ const cmdResponse = await this.client.sendCommand(SFM_CMD.ETX, userId, sizeField, flag);
431
+ log(`[ETX] Command response: flag=0x${cmdResponse.flag?.toString(16)}, param=${cmdResponse.param}, valid=${cmdResponse.valid}`);
432
+ if (!cmdResponse.valid) {
433
+ return { success: false, error: cmdResponse.error || "unknown error" };
434
+ }
435
+ if (cmdResponse.flag !== SFM_ERROR.SUCCESS) {
436
+ return {
437
+ success: false,
438
+ error: `ETX command failed: 0x${cmdResponse.flag?.toString(16) ?? "??"}`,
439
+ };
440
+ }
441
+ // Step 2: Send each chunk with Extended Data Transfer Protocol
442
+ const DATA_OK = 0x83;
443
+ for (let i = 0; i < templateCount; i++) {
444
+ const offset = i * CHUNK;
445
+ const currentChunkSize = Math.min(CHUNK, totalSize - offset);
446
+ const chunkData = templateData.subarray(offset, offset + currentChunkSize);
447
+ // Data Packet Header param: (totalPackets & 0xFFFF) | ((packetIndex & 0xFFFF) << 16)
448
+ const dataPacketParam = (templateCount & 0xFFFF) | ((i & 0xFFFF) << 16);
449
+ const dataHeader = buildNormalPacket(SFM_CMD.ETX, dataPacketParam, currentChunkSize, 0);
450
+ // Data Checksum: full byte sum (NOT & 0xFF)
451
+ let checksum = 0;
452
+ for (let j = 0; j < currentChunkSize; j++) {
453
+ checksum += chunkData[j];
454
+ }
455
+ const checksumBuf = Buffer.alloc(4);
456
+ checksumBuf.writeUInt32LE(checksum >>> 0, 0);
457
+ const combined = Buffer.concat([dataHeader, chunkData, checksumBuf]);
458
+ log(`[ETX] Sending chunk ${i + 1}/${templateCount}: ${combined.length}B (header:13 + data:${currentChunkSize} + checksum:4, checksum=${checksum})`);
459
+ await this.client.serial.write(combined);
460
+ // Wait for DATA_OK(0x83) response
461
+ const ackResponse = await this.client.receiveResponse(this.client.commandTimeout);
462
+ log(`[ETX] Chunk ${i + 1} ACK: flag=0x${ackResponse.flag?.toString(16)}, param=${ackResponse.param}, valid=${ackResponse.valid}`);
463
+ if (!ackResponse.valid) {
464
+ return { success: false, error: `Chunk ${i + 1} ACK invalid: ${ackResponse.error}` };
465
+ }
466
+ if (ackResponse.flag !== SFM_ERROR.SUCCESS && ackResponse.flag !== DATA_OK) {
467
+ return {
468
+ success: false,
469
+ error: `ETX chunk ${i + 1} failed: 0x${ackResponse.flag?.toString(16) ?? "??"}`,
470
+ };
471
+ }
472
+ }
473
+ log(`[ETX] Template written successfully (${templateCount} chunks, ${totalSize}B)`);
474
+ // Drain residual responses from device (e.g. SCAN_SUCCESS after write)
475
+ await new Promise((r) => setTimeout(r, 100));
476
+ await this.client.serial.purgeRX();
477
+ return { success: true, userId: cmdResponse.param, error: null };
478
+ }
479
+ /**
480
+ * Capture fingerprint image (SI: 0x15)
481
+ */
482
+ async captureImage({ onLog } = {}) {
483
+ const log = (msg) => {
484
+ onLog?.(msg);
485
+ };
486
+ log("[CAPTURE] Fingerprint scan started (SI: 0x15)");
487
+ const siResponse = await this.client.sendCommand(SFM_CMD.SI, 0, 0, 0);
488
+ log(`[CAPTURE] SI 응답: flag=0x${siResponse.flag?.toString(16)}, param=${siResponse.param}, size=${siResponse.size}, valid=${siResponse.valid}`);
489
+ if (!siResponse.valid) {
490
+ return {
491
+ success: false,
492
+ imageData: null,
493
+ width: 0,
494
+ height: 0,
495
+ error: siResponse.error || "unknown error",
496
+ };
497
+ }
498
+ let lastResponse = siResponse;
499
+ while (lastResponse.flag === SFM_ERROR.SCAN_SUCCESS) {
500
+ log("[CAPTURE] Scan success (0x62), waiting for next response...");
501
+ lastResponse = await this.client.receiveResponse(this.client.commandTimeout);
502
+ log(`[CAPTURE] Response: flag=0x${lastResponse.flag?.toString(16)}, param=${lastResponse.param}, size=${lastResponse.size}, valid=${lastResponse.valid}`);
503
+ if (!lastResponse.valid) {
504
+ return {
505
+ success: false,
506
+ imageData: null,
507
+ width: 0,
508
+ height: 0,
509
+ error: lastResponse.error || "unknown error",
510
+ };
511
+ }
512
+ }
513
+ if (lastResponse.flag !== SFM_ERROR.SUCCESS) {
514
+ return {
515
+ success: false,
516
+ imageData: null,
517
+ width: 0,
518
+ height: 0,
519
+ error: `Scan failed: 0x${lastResponse.flag?.toString(16) ?? "??"}`,
520
+ };
521
+ }
522
+ const imageSize = lastResponse.size ?? 0;
523
+ log(`[CAPTURE] SI 최종: param=0x${((lastResponse.param ?? 0) >>> 0).toString(16)}, size=${imageSize}`);
524
+ if (imageSize === 0) {
525
+ return {
526
+ success: false,
527
+ imageData: null,
528
+ width: 0,
529
+ height: 0,
530
+ error: "No image data (size=0)",
531
+ };
532
+ }
533
+ log(`[CAPTURE] Receiving image data: ${imageSize}B`);
534
+ const readTimeout = Math.max(this.client.commandTimeout, Math.ceil(imageSize / 100) + 5000);
535
+ const imageData = await this.client.serial.read(imageSize, readTimeout);
536
+ if (!imageData || imageData.length < imageSize) {
537
+ return {
538
+ success: false,
539
+ imageData: null,
540
+ width: 0,
541
+ height: 0,
542
+ error: `Incomplete read: ${imageData?.length ?? 0}/${imageSize}B`,
543
+ };
544
+ }
545
+ log(`[CAPTURE] Image received: ${imageData.length}B`);
546
+ const sqrt = Math.sqrt(imageSize);
547
+ let width, height;
548
+ if (Number.isInteger(sqrt)) {
549
+ width = sqrt;
550
+ height = sqrt;
551
+ }
552
+ else {
553
+ const candidates = [
554
+ [160, 160],
555
+ [200, 200],
556
+ [256, 256],
557
+ [288, 288],
558
+ [256, 360],
559
+ [160, 120],
560
+ [240, 320],
561
+ ];
562
+ const match = candidates.find(([w, h]) => w * h === imageSize);
563
+ if (match) {
564
+ [width, height] = match;
565
+ }
566
+ else {
567
+ const paramVal = lastResponse.param ?? 0;
568
+ width = (paramVal >> 16) & 0xffff;
569
+ height = paramVal & 0xffff;
570
+ if (width === 0 || height === 0) {
571
+ width = Math.ceil(sqrt);
572
+ height = width > 0 ? Math.floor(imageSize / width) : 0;
573
+ }
574
+ }
575
+ }
576
+ log(`[CAPTURE] Image resolution: ${width}x${height} (${width * height} vs ${imageSize})`);
577
+ return { success: true, imageData, width, height, error: null };
578
+ }
579
+ }
580
+ //# sourceMappingURL=fingerprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../src/commands/fingerprint.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Firmware upgrade commands
3
+ */
4
+ import type { SfmClient } from "../core";
5
+ import type { DataCommands } from "./data";
6
+ export interface FirmwareOptions {
7
+ onProgress?: (percent: number, sent: number, total: number) => void;
8
+ onStatus?: (message: string) => void;
9
+ }
10
+ interface FirmwareData {
11
+ data: Buffer;
12
+ packet: Buffer;
13
+ totalLen: number;
14
+ checksum: number;
15
+ }
16
+ export declare class FirmwareCommands {
17
+ private client;
18
+ private data;
19
+ constructor(client: SfmClient);
20
+ /** @internal Set DataCommands reference (avoid circular dependency) */
21
+ _setDataCommands(data: DataCommands): void;
22
+ /**
23
+ * Load firmware file and build packet
24
+ */
25
+ loadFirmware(filePath: string): FirmwareData;
26
+ /**
27
+ * Firmware upgrade (serial direct handshake)
28
+ */
29
+ upgrade(filePath: string, { onProgress, onStatus }?: FirmwareOptions): Promise<void>;
30
+ /**
31
+ * Protocol-level firmware upgrade (SFM packet protocol)
32
+ */
33
+ upgradeViaProtocol(filePath: string, chunkSize?: number, { onProgress, onStatus }?: FirmwareOptions): Promise<void>;
34
+ private _handshake;
35
+ }
36
+ export {};
37
+ //# sourceMappingURL=firmware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firmware.d.ts","sourceRoot":"","sources":["../../src/commands/firmware.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,MAAM,WAAW,eAAe;IAC9B,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACpE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AAED,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAcD,qBAAa,gBAAgB;IAGf,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,IAAI,CAA6B;gBAErB,MAAM,EAAE,SAAS;IAErC,uEAAuE;IACvE,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAI1C;;OAEG;IACH,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY;IAa5C;;OAEG;IACG,OAAO,CACX,QAAQ,EAAE,MAAM,EAChB,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAE,eAAoB,GAC7C,OAAO,CAAC,IAAI,CAAC;IAyDhB;;OAEG;IACG,kBAAkB,CACtB,QAAQ,EAAE,MAAM,EAChB,SAAS,SAAS,EAClB,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAE,eAAoB,GAC7C,OAAO,CAAC,IAAI,CAAC;YAqDF,UAAU;CA0BzB"}