@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,152 @@
1
+ /**
2
+ * Firmware upgrade commands
3
+ */
4
+ import fs from "node:fs";
5
+ import { SFM_CMD } from "../constants";
6
+ import { calcChecksum16 } from "../core/packet";
7
+ const FW_HANDSHAKE = {
8
+ PING: 0x31,
9
+ UPGRADE_CONFIRM: 0x75,
10
+ };
11
+ const FIRMWARE_MAGIC = 0x1f2f3f4f;
12
+ const FIRMWARE_CHUNK_SIZE = 0x1000;
13
+ const HANDSHAKE_TIMEOUT_MS = 5000;
14
+ const DOWNLOAD_TIMEOUT_MS = 1000;
15
+ const COMPLETION_TIMEOUT_MS = 12000;
16
+ const HANDSHAKE_RETRY_DELAY_MS = 10;
17
+ export class FirmwareCommands {
18
+ constructor(client) {
19
+ this.client = client;
20
+ this.data = null;
21
+ }
22
+ /** @internal Set DataCommands reference (avoid circular dependency) */
23
+ _setDataCommands(data) {
24
+ this.data = data;
25
+ }
26
+ /**
27
+ * Load firmware file and build packet
28
+ */
29
+ loadFirmware(filePath) {
30
+ const data = fs.readFileSync(filePath);
31
+ const totalLen = data.length + 6;
32
+ const packet = Buffer.alloc(totalLen);
33
+ packet.writeUInt32LE(totalLen, 0);
34
+ data.copy(packet, 4);
35
+ const checksum = calcChecksum16(data);
36
+ packet.writeUInt16LE(checksum, 4 + data.length);
37
+ return { data, packet, totalLen, checksum };
38
+ }
39
+ /**
40
+ * Firmware upgrade (serial direct handshake)
41
+ */
42
+ async upgrade(filePath, { onProgress, onStatus } = {}) {
43
+ if (!filePath) {
44
+ throw new Error("filePath is required");
45
+ }
46
+ const progress = onProgress || (() => { });
47
+ const status = onStatus || (() => { });
48
+ const fw = this.loadFirmware(filePath);
49
+ status(`Firmware loaded: ${filePath} (${fw.data.length} bytes)`);
50
+ status("=== Firmware upgrade started ===");
51
+ status("Handshake started...");
52
+ const handshakeOk = await this._handshake(this.client.serial, status);
53
+ if (!handshakeOk) {
54
+ throw new Error("Handshake failed: no device response");
55
+ }
56
+ status("Sending upgrade confirm...");
57
+ await this.client.serial.write(Buffer.from([FW_HANDSHAKE.UPGRADE_CONFIRM]));
58
+ status('Waiting for "download" response...');
59
+ try {
60
+ await this.client.serial.readUntil("download", DOWNLOAD_TIMEOUT_MS);
61
+ }
62
+ catch {
63
+ throw new Error('No "download" response from device');
64
+ }
65
+ await this.client.serial.write(Buffer.alloc(0));
66
+ status(`Firmware transfer started: ${fw.totalLen} bytes`);
67
+ let sent = 0;
68
+ while (sent < fw.totalLen) {
69
+ const chunkSize = Math.min(FIRMWARE_CHUNK_SIZE, fw.totalLen - sent);
70
+ const chunk = fw.packet.subarray(sent, sent + chunkSize);
71
+ await this.client.serial.write(chunk);
72
+ sent += chunkSize;
73
+ const percent = Math.floor((sent * 100) / fw.totalLen);
74
+ progress(percent, sent, fw.totalLen);
75
+ status(`Written ${sent}/${fw.totalLen} bytes (${percent}%)`);
76
+ }
77
+ status('Waiting for "Started" response...');
78
+ try {
79
+ await this.client.serial.readUntil("Started", COMPLETION_TIMEOUT_MS);
80
+ status("Firmware apply started!");
81
+ }
82
+ catch {
83
+ status('Warning: "Started" response timeout (device may be rebooting)');
84
+ }
85
+ await new Promise((resolve) => setTimeout(resolve, 1000));
86
+ status("=== Firmware upgrade complete ===");
87
+ }
88
+ /**
89
+ * Protocol-level firmware upgrade (SFM packet protocol)
90
+ */
91
+ async upgradeViaProtocol(filePath, chunkSize = 0x4000, { onProgress, onStatus } = {}) {
92
+ if (!filePath) {
93
+ throw new Error("filePath is required");
94
+ }
95
+ if (!this.data) {
96
+ throw new Error("DataCommands not initialized");
97
+ }
98
+ const progress = onProgress || (() => { });
99
+ const status = onStatus || (() => { });
100
+ const data = fs.readFileSync(filePath);
101
+ status(`Firmware loaded: ${filePath} (${data.length} bytes)`);
102
+ if (data.length >= 4) {
103
+ const magic = data.readUInt32LE(0);
104
+ if (magic !== FIRMWARE_MAGIC) {
105
+ status(`Warning: firmware magic mismatch (got=0x${magic.toString(16)}, expected=0x${FIRMWARE_MAGIC.toString(16)})`);
106
+ }
107
+ }
108
+ status("Checking system status...");
109
+ const statusResponse = await this.client.sendCommand(SFM_CMD.SS, 0, 0, 0);
110
+ if (!statusResponse.valid) {
111
+ throw new Error(`Status check failed: ${statusResponse.error}`);
112
+ }
113
+ status("System status OK");
114
+ status("Saving database...");
115
+ const saveResponse = await this.client.sendCommand(SFM_CMD.SDB, 0, 0, 0);
116
+ if (!saveResponse.valid) {
117
+ throw new Error(`Database save failed before firmware upgrade: ${saveResponse.error || "unknown error"}`);
118
+ }
119
+ status(`Firmware data transfer started: ${data.length} bytes`);
120
+ await this.data.send(SFM_CMD.SDB, data, chunkSize, {
121
+ onProgress: (idx, total) => {
122
+ const percent = Math.floor(((idx + 1) * 100) / total);
123
+ progress(percent, idx + 1, total);
124
+ status(`Transfer ${idx + 1}/${total} (${percent}%)`);
125
+ },
126
+ });
127
+ status("Module reset...");
128
+ await this.client.sendCommand(SFM_CMD.RS, 0, 0, 0);
129
+ status("Waiting for firmware apply...");
130
+ await new Promise((resolve) => setTimeout(resolve, 1000));
131
+ status("=== Protocol-level firmware upgrade complete ===");
132
+ }
133
+ async _handshake(serial, status) {
134
+ const startTime = Date.now();
135
+ while (Date.now() - startTime < HANDSHAKE_TIMEOUT_MS) {
136
+ await serial.write(Buffer.from([FW_HANDSHAKE.PING]));
137
+ try {
138
+ const response = await serial.readByte(100);
139
+ if (response === FW_HANDSHAKE.PING) {
140
+ status("Handshake success!");
141
+ return true;
142
+ }
143
+ }
144
+ catch {
145
+ // timeout, retry
146
+ }
147
+ await new Promise((resolve) => setTimeout(resolve, HANDSHAKE_RETRY_DELAY_MS));
148
+ }
149
+ return false;
150
+ }
151
+ }
152
+ //# sourceMappingURL=firmware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"firmware.js","sourceRoot":"","sources":["../../src/commands/firmware.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * FreeScan commands - automatic fingerprint recognition mode
3
+ *
4
+ * In FreeScan mode, the device automatically scans fingerprints
5
+ * and sends IS(0x11) response packets.
6
+ */
7
+ import type { SfmClient } from "../core";
8
+ import type { SystemCommands } from "./system";
9
+ export interface FreeScanResult {
10
+ success: boolean;
11
+ userId?: number;
12
+ flag?: number;
13
+ }
14
+ export type FreeScanCallback = (result: FreeScanResult) => void;
15
+ export type FreeScanDataHandler = (data: Buffer) => void;
16
+ export type FreeScanErrorHandler = (error?: Error) => void;
17
+ export declare class FreeScanCommands {
18
+ private client;
19
+ private system;
20
+ private running;
21
+ private dataHandler;
22
+ private errorHandler;
23
+ private buffer;
24
+ private callback;
25
+ private logFn;
26
+ private externalDataHandler;
27
+ private externalErrorHandler;
28
+ constructor(client: SfmClient);
29
+ /** @internal Set SystemCommands reference */
30
+ _setSystemCommands(system: SystemCommands): void;
31
+ get isRunning(): boolean;
32
+ /** Register an external data handler (can be swapped at any time) */
33
+ onDataHandler(handler: FreeScanDataHandler): void;
34
+ /** Remove the external data handler */
35
+ offDataHandler(): void;
36
+ /** Register an external error handler (can be swapped at any time) */
37
+ onErrorHandler(handler: FreeScanErrorHandler): void;
38
+ /** Remove the external error handler */
39
+ offErrorHandler(): void;
40
+ /** Clean up internal state (remove listeners, reset flags) */
41
+ private cleanup;
42
+ /**
43
+ * Check if device FreeScan parameter (0x84) is active
44
+ */
45
+ isDeviceFreeScanActive(): Promise<boolean>;
46
+ /**
47
+ * Start FreeScan
48
+ * @param onResult identification result callback
49
+ * @param onLog log callback (optional)
50
+ */
51
+ start(onResult: FreeScanCallback, onLog?: (msg: string) => void): Promise<{
52
+ success: boolean;
53
+ message: string;
54
+ }>;
55
+ /**
56
+ * Stop FreeScan
57
+ */
58
+ stop(): Promise<{
59
+ success: boolean;
60
+ message: string;
61
+ }>;
62
+ /**
63
+ * Serial data event handler
64
+ * Parses 13-byte packets and processes IS(0x11) responses
65
+ */
66
+ private handleData;
67
+ }
68
+ //# sourceMappingURL=freescan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freescan.d.ts","sourceRoot":"","sources":["../../src/commands/freescan.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;AAChE,MAAM,MAAM,mBAAmB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AACzD,MAAM,MAAM,oBAAoB,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;AAE3D,qBAAa,gBAAgB;IAWf,OAAO,CAAC,MAAM;IAV1B,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,WAAW,CAAyC;IAC5D,OAAO,CAAC,YAAY,CAAwC;IAC5D,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,QAAQ,CAAiC;IACjD,OAAO,CAAC,KAAK,CAAwC;IACrD,OAAO,CAAC,mBAAmB,CAAoC;IAC/D,OAAO,CAAC,oBAAoB,CAAqC;gBAE7C,MAAM,EAAE,SAAS;IAErC,6CAA6C;IAC7C,kBAAkB,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAIhD,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED,qEAAqE;IACrE,aAAa,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI;IAIjD,uCAAuC;IACvC,cAAc,IAAI,IAAI;IAItB,sEAAsE;IACtE,cAAc,CAAC,OAAO,EAAE,oBAAoB,GAAG,IAAI;IAInD,wCAAwC;IACxC,eAAe,IAAI,IAAI;IAIvB,8DAA8D;IAC9D,OAAO,CAAC,OAAO;IAsBf;;OAEG;IACG,sBAAsB,IAAI,OAAO,CAAC,OAAO,CAAC;IAOhD;;;;OAIG;IACG,KAAK,CACT,QAAQ,EAAE,gBAAgB,EAC1B,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC5B,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IA2DjD;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAiB5D;;;OAGG;IACH,OAAO,CAAC,UAAU;CAiDnB"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * FreeScan commands - automatic fingerprint recognition mode
3
+ *
4
+ * In FreeScan mode, the device automatically scans fingerprints
5
+ * and sends IS(0x11) response packets.
6
+ */
7
+ import { SFM_ERROR, SFM_CMD, SFM_PARAM, START_CODE, PACKET_SIZE } from "../constants";
8
+ import { parseNormalPacket } from "../core";
9
+ export class FreeScanCommands {
10
+ constructor(client) {
11
+ this.client = client;
12
+ this.system = null;
13
+ this.running = false;
14
+ this.dataHandler = null;
15
+ this.errorHandler = null;
16
+ this.buffer = Buffer.alloc(0);
17
+ this.callback = null;
18
+ this.logFn = null;
19
+ this.externalDataHandler = null;
20
+ this.externalErrorHandler = null;
21
+ }
22
+ /** @internal Set SystemCommands reference */
23
+ _setSystemCommands(system) {
24
+ this.system = system;
25
+ }
26
+ get isRunning() {
27
+ return this.running;
28
+ }
29
+ /** Register an external data handler (can be swapped at any time) */
30
+ onDataHandler(handler) {
31
+ this.externalDataHandler = handler;
32
+ }
33
+ /** Remove the external data handler */
34
+ offDataHandler() {
35
+ this.externalDataHandler = null;
36
+ }
37
+ /** Register an external error handler (can be swapped at any time) */
38
+ onErrorHandler(handler) {
39
+ this.externalErrorHandler = handler;
40
+ }
41
+ /** Remove the external error handler */
42
+ offErrorHandler() {
43
+ this.externalErrorHandler = null;
44
+ }
45
+ /** Clean up internal state (remove listeners, reset flags) */
46
+ cleanup() {
47
+ try {
48
+ if (this.client.serial?.port) {
49
+ if (this.dataHandler) {
50
+ this.client.serial.port.removeListener("data", this.dataHandler);
51
+ }
52
+ if (this.errorHandler) {
53
+ this.client.serial.port.removeListener("error", this.errorHandler);
54
+ this.client.serial.port.removeListener("close", this.errorHandler);
55
+ }
56
+ }
57
+ }
58
+ catch {
59
+ // Port may already be destroyed; ignore listener removal errors
60
+ }
61
+ this.dataHandler = null;
62
+ this.errorHandler = null;
63
+ this.running = false;
64
+ this.buffer = Buffer.alloc(0);
65
+ this.callback = null;
66
+ this.logFn = null;
67
+ }
68
+ /**
69
+ * Check if device FreeScan parameter (0x84) is active
70
+ */
71
+ async isDeviceFreeScanActive() {
72
+ if (!this.system)
73
+ throw new Error("SystemCommands not initialized");
74
+ const result = await this.system.getParam("FREE_SCAN");
75
+ const FREE_SCAN_ON = SFM_PARAM.FREE_SCAN.options.find((o) => o.alias === "ON").value;
76
+ return result.value === FREE_SCAN_ON;
77
+ }
78
+ /**
79
+ * Start FreeScan
80
+ * @param onResult identification result callback
81
+ * @param onLog log callback (optional)
82
+ */
83
+ async start(onResult, onLog) {
84
+ if (!this.system)
85
+ throw new Error("SystemCommands not initialized");
86
+ // If running flag is true but device is OFF (stale state) -> cleanup
87
+ if (this.running) {
88
+ const deviceActive = await this.isDeviceFreeScanActive();
89
+ if (!deviceActive) {
90
+ onLog?.("[FreeScan] Stale state detected — cleaning up and restarting");
91
+ this.cleanup();
92
+ }
93
+ else {
94
+ return { success: false, message: "Already running" };
95
+ }
96
+ }
97
+ const log = (msg) => {
98
+ onLog?.(msg);
99
+ };
100
+ this.logFn = log;
101
+ this.callback = onResult;
102
+ log("[FreeScan] Enabling Auto Response...");
103
+ const arResult = await this.system.setParam("AUTO_RESPONSE", "HOST");
104
+ if (!arResult.success) {
105
+ log(`[FreeScan] Auto Response setup failed: ${JSON.stringify(arResult)}`);
106
+ return { success: false, message: "Auto Response setup failed" };
107
+ }
108
+ log("[FreeScan] Enabling FreeScan...");
109
+ const fsResult = await this.system.setParam("FREE_SCAN", "ON");
110
+ if (!fsResult.success) {
111
+ log(`[FreeScan] Enable failed: ${JSON.stringify(fsResult)}`);
112
+ return { success: false, message: "FreeScan setup failed" };
113
+ }
114
+ if (!this.client.serial?.port) {
115
+ return { success: false, message: "Serial port not connected" };
116
+ }
117
+ this.running = true;
118
+ this.buffer = Buffer.alloc(0);
119
+ // Serial port event listening
120
+ this.dataHandler = (data) => {
121
+ this.externalDataHandler?.(data);
122
+ this.handleData(data);
123
+ };
124
+ this.errorHandler = (err) => {
125
+ this.logFn?.("[FreeScan] Port error/close detected — auto cleanup");
126
+ this.externalErrorHandler?.(err);
127
+ this.cleanup();
128
+ };
129
+ this.client.serial.port.on("data", this.dataHandler);
130
+ this.client.serial.port.on("error", this.errorHandler);
131
+ this.client.serial.port.on("close", this.errorHandler);
132
+ log("[FreeScan] FreeScan ON — serial data event listening started");
133
+ return { success: true, message: "FreeScan enabled" };
134
+ }
135
+ /**
136
+ * Stop FreeScan
137
+ */
138
+ async stop() {
139
+ if (!this.system)
140
+ throw new Error("SystemCommands not initialized");
141
+ const log = this.logFn || (() => { });
142
+ log("[FreeScan] Disabling FreeScan...");
143
+ await this.system.setParam("FREE_SCAN", "OFF");
144
+ log("[FreeScan] Disabling Auto Response...");
145
+ await this.system.setParam("AUTO_RESPONSE", "OFF");
146
+ this.cleanup();
147
+ log("[FreeScan] FreeScan OFF");
148
+ return { success: true, message: "FreeScan disabled" };
149
+ }
150
+ /**
151
+ * Serial data event handler
152
+ * Parses 13-byte packets and processes IS(0x11) responses
153
+ */
154
+ handleData(data) {
155
+ try {
156
+ const hex = Buffer.from(data).toString("hex").match(/../g)?.join(" ") || "";
157
+ this.logFn?.(`[FreeScan RX] +${data.length}B | ${hex}`);
158
+ this.buffer = Buffer.concat([this.buffer, data]);
159
+ while (this.buffer.length >= PACKET_SIZE.NORMAL) {
160
+ const startIdx = this.buffer.indexOf(START_CODE.NORMAL);
161
+ if (startIdx === -1) {
162
+ this.buffer = Buffer.alloc(0);
163
+ break;
164
+ }
165
+ if (startIdx > 0) {
166
+ this.buffer = this.buffer.subarray(startIdx);
167
+ }
168
+ if (this.buffer.length < PACKET_SIZE.NORMAL)
169
+ break;
170
+ const packet = this.buffer.subarray(0, PACKET_SIZE.NORMAL);
171
+ this.buffer = this.buffer.subarray(PACKET_SIZE.NORMAL);
172
+ const parsed = parseNormalPacket(packet);
173
+ if (!parsed.valid)
174
+ continue;
175
+ // IS response handling
176
+ if (parsed.command === SFM_CMD.IS) {
177
+ const flag = parsed.flag;
178
+ const userId = parsed.param;
179
+ if (flag === SFM_ERROR.SUCCESS) {
180
+ this.logFn?.(`[FreeScan] Identified! UserID: ${userId}`);
181
+ this.callback?.({ success: true, userId });
182
+ }
183
+ else if (flag === SFM_ERROR.NOT_FOUND) {
184
+ this.logFn?.("[FreeScan] Unregistered fingerprint");
185
+ this.callback?.({ success: false, flag });
186
+ }
187
+ else if (flag === SFM_ERROR.SCAN_SUCCESS) {
188
+ this.logFn?.("[FreeScan] Fingerprint scanned, matching...");
189
+ }
190
+ else {
191
+ this.logFn?.(`[FreeScan] Unknown response: flag=0x${flag?.toString(16) ?? "??"}`);
192
+ }
193
+ }
194
+ }
195
+ }
196
+ catch (err) {
197
+ this.logFn?.(`[FreeScan] Data processing error: ${err.message}`);
198
+ this.externalErrorHandler?.(err instanceof Error ? err : new Error(String(err)));
199
+ }
200
+ }
201
+ }
202
+ //# sourceMappingURL=freescan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freescan.js","sourceRoot":"","sources":["../../src/commands/freescan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * SfmCommands - Unified command class (composition)
3
+ *
4
+ * Usage:
5
+ * const finger = new SfmCommands({ baudRate: 115200 });
6
+ * await finger.connect('/dev/ttyUSB0');
7
+ *
8
+ * await finger.fingerprint.enroll(userId);
9
+ * await finger.fingerprint.verify(userId);
10
+ * await finger.fingerprint.identify();
11
+ *
12
+ * await finger.system.getParam(0x01);
13
+ * await finger.system.reset();
14
+ * await finger.system.selfTest();
15
+ *
16
+ * await finger.data.send(cmd, buf);
17
+ * await finger.data.recv(cmd, size);
18
+ *
19
+ * await finger.firmware.upgrade(filePath);
20
+ *
21
+ * await finger.disconnect();
22
+ */
23
+ import type { SfmClientOptions, SerialPortInfo } from "../core";
24
+ import type { EncryptionMode } from "../constants";
25
+ import { FingerprintCommands } from "./fingerprint";
26
+ import { SystemCommands } from "./system";
27
+ import { DataCommands } from "./data";
28
+ import { FirmwareCommands } from "./firmware";
29
+ import { FreeScanCommands } from "./freescan";
30
+ export declare class SfmCommands {
31
+ private readonly client;
32
+ readonly fingerprint: FingerprintCommands;
33
+ readonly system: SystemCommands;
34
+ readonly data: DataCommands;
35
+ readonly firmware: FirmwareCommands;
36
+ readonly freeScan: FreeScanCommands;
37
+ constructor(options?: SfmClientOptions);
38
+ /**
39
+ * Create instance and connect to device
40
+ */
41
+ static create(options: SfmClientOptions & {
42
+ portPath: string;
43
+ }): Promise<SfmCommands>;
44
+ /**
45
+ * List available serial ports
46
+ */
47
+ static listPorts(): Promise<SerialPortInfo[]>;
48
+ /**
49
+ * Connect to device
50
+ */
51
+ connect(portPath?: string): Promise<void>;
52
+ /**
53
+ * Disconnect from device
54
+ */
55
+ disconnect(): Promise<void>;
56
+ /**
57
+ * Switch secure mode
58
+ */
59
+ setSecureMode(enabled: boolean, options?: {
60
+ key?: Buffer | string;
61
+ iv?: Buffer | string;
62
+ secureCode?: Buffer | string;
63
+ mode?: EncryptionMode;
64
+ }): void;
65
+ /**
66
+ * Switch network protocol mode (RS422/485)
67
+ */
68
+ setNetworkMode(enabled: boolean, terminalId?: number): void;
69
+ /** Set disconnect callback */
70
+ setOnDisconnect(callback: ((error?: Error) => void) | null): void;
71
+ /** Set auto-reconnect options */
72
+ setAutoReconnect(options: import("../core/serial").AutoReconnectOptions | null): void;
73
+ /** Set auto-reconnect callbacks only */
74
+ setAutoReconnectCallbacks(callbacks: import("../core/serial").AutoReconnectCallbacks): void;
75
+ /** Whether reconnection is in progress */
76
+ get isReconnecting(): boolean;
77
+ }
78
+ export { FingerprintCommands } from "./fingerprint";
79
+ export { SystemCommands } from "./system";
80
+ export { DataCommands, calcEvenOddChecksum } from "./data";
81
+ export { FirmwareCommands } from "./firmware";
82
+ export { FreeScanCommands } from "./freescan";
83
+ export type { EnrollResult, VerifyResult, IdentifyResult, CommandResult, ListUserIdsResult, CaptureImageResult, } from "./fingerprint";
84
+ export type { SystemStatusResult, ParamResult, SelfTestResult } from "./system";
85
+ export type { MultiPacketOptions } from "./data";
86
+ export type { FirmwareOptions } from "./firmware";
87
+ export type { FreeScanResult, FreeScanCallback } from "./freescan";
88
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * SfmCommands - Unified command class (composition)
3
+ *
4
+ * Usage:
5
+ * const finger = new SfmCommands({ baudRate: 115200 });
6
+ * await finger.connect('/dev/ttyUSB0');
7
+ *
8
+ * await finger.fingerprint.enroll(userId);
9
+ * await finger.fingerprint.verify(userId);
10
+ * await finger.fingerprint.identify();
11
+ *
12
+ * await finger.system.getParam(0x01);
13
+ * await finger.system.reset();
14
+ * await finger.system.selfTest();
15
+ *
16
+ * await finger.data.send(cmd, buf);
17
+ * await finger.data.recv(cmd, size);
18
+ *
19
+ * await finger.firmware.upgrade(filePath);
20
+ *
21
+ * await finger.disconnect();
22
+ */
23
+ import { SfmClient, SfmSerial } from "../core";
24
+ import { FingerprintCommands } from "./fingerprint";
25
+ import { SystemCommands } from "./system";
26
+ import { DataCommands } from "./data";
27
+ import { FirmwareCommands } from "./firmware";
28
+ import { FreeScanCommands } from "./freescan";
29
+ export class SfmCommands {
30
+ constructor(options = {}) {
31
+ this.client = new SfmClient(options);
32
+ this.fingerprint = new FingerprintCommands(this.client);
33
+ this.system = new SystemCommands(this.client);
34
+ this.data = new DataCommands(this.client);
35
+ this.firmware = new FirmwareCommands(this.client);
36
+ this.freeScan = new FreeScanCommands(this.client);
37
+ // Set cross-references between sub-classes
38
+ this.system._setDataCommands(this.data);
39
+ this.firmware._setDataCommands(this.data);
40
+ this.fingerprint._setSystemCommands(this.system);
41
+ this.freeScan._setSystemCommands(this.system);
42
+ }
43
+ /**
44
+ * Create instance and connect to device
45
+ */
46
+ static async create(options) {
47
+ const instance = new SfmCommands(options);
48
+ await instance.connect();
49
+ return instance;
50
+ }
51
+ /**
52
+ * List available serial ports
53
+ */
54
+ static async listPorts() {
55
+ return SfmSerial.listPorts();
56
+ }
57
+ /**
58
+ * Connect to device
59
+ */
60
+ async connect(portPath) {
61
+ await this.client.connect(portPath);
62
+ }
63
+ /**
64
+ * Disconnect from device
65
+ */
66
+ async disconnect() {
67
+ await this.client.disconnect();
68
+ }
69
+ /**
70
+ * Switch secure mode
71
+ */
72
+ setSecureMode(enabled, options = {}) {
73
+ this.client.setSecureMode(enabled, options);
74
+ }
75
+ /**
76
+ * Switch network protocol mode (RS422/485)
77
+ */
78
+ setNetworkMode(enabled, terminalId) {
79
+ this.client.setNetworkMode(enabled, terminalId);
80
+ }
81
+ /** Set disconnect callback */
82
+ setOnDisconnect(callback) {
83
+ this.client.setOnDisconnect(callback);
84
+ }
85
+ /** Set auto-reconnect options */
86
+ setAutoReconnect(options) {
87
+ this.client.setAutoReconnect(options);
88
+ }
89
+ /** Set auto-reconnect callbacks only */
90
+ setAutoReconnectCallbacks(callbacks) {
91
+ this.client.setAutoReconnectCallbacks(callbacks);
92
+ }
93
+ /** Whether reconnection is in progress */
94
+ get isReconnecting() {
95
+ return this.client.isReconnecting;
96
+ }
97
+ }
98
+ // Sub-class re-exports
99
+ export { FingerprintCommands } from "./fingerprint";
100
+ export { SystemCommands } from "./system";
101
+ export { DataCommands, calcEvenOddChecksum } from "./data";
102
+ export { FirmwareCommands } from "./firmware";
103
+ export { FreeScanCommands } from "./freescan";
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"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"}