@ecobridge.xyz/devicemanager 3.1.1 → 3.2.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.
- package/changelog.md +25 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/device/device.classes.device.d.ts +2 -2
- package/dist_ts/device/device.classes.device.js +3 -3
- package/dist_ts/devicemanager.classes.devicemanager.d.ts +17 -4
- package/dist_ts/devicemanager.classes.devicemanager.js +67 -5
- package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +4 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.js +43 -2
- package/dist_ts/events/events.observable.d.ts +15 -0
- package/dist_ts/events/events.observable.js +22 -0
- package/dist_ts/events/index.d.ts +1 -0
- package/dist_ts/events/index.js +2 -0
- package/dist_ts/factories/index.js +7 -5
- package/dist_ts/features/feature.abstract.d.ts +2 -2
- package/dist_ts/features/feature.abstract.js +3 -3
- package/dist_ts/features/feature.print.d.ts +3 -0
- package/dist_ts/features/feature.print.js +17 -2
- package/dist_ts/features/feature.scan.d.ts +5 -2
- package/dist_ts/features/feature.scan.js +98 -27
- package/dist_ts/index.d.ts +3 -1
- package/dist_ts/index.js +4 -2
- package/dist_ts/interfaces/feature.interfaces.d.ts +21 -1
- package/dist_ts/interfaces/index.d.ts +21 -3
- package/dist_ts/interfaces/index.js +1 -1
- package/dist_ts/plugins.d.ts +2 -1
- package/dist_ts/plugins.js +3 -2
- package/dist_ts/protocols/index.d.ts +2 -1
- package/dist_ts/protocols/index.js +4 -2
- package/dist_ts/protocols/protocol.brother.d.ts +67 -0
- package/dist_ts/protocols/protocol.brother.js +560 -0
- package/dist_ts/protocols/protocol.escl.d.ts +13 -4
- package/dist_ts/protocols/protocol.escl.js +344 -177
- package/dist_ts/protocols/protocol.ipp.d.ts +2 -0
- package/dist_ts/protocols/protocol.ipp.js +22 -2
- package/dist_ts/providers/index.d.ts +1 -0
- package/dist_ts/providers/index.js +2 -0
- package/dist_ts/providers/provider.smb.d.ts +60 -0
- package/dist_ts/providers/provider.smb.js +224 -0
- package/package.json +11 -7
- package/pnpm-workspace.yaml +2 -0
- package/readme.md +98 -4
- package/test/test.brother.node.ts +306 -0
- package/test/test.escl.node.ts +233 -0
- package/test/test.ipp.node.ts +75 -0
- package/test/test.node.ts +17 -0
- package/test/test.smb.node.ts +123 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/device/device.classes.device.ts +2 -2
- package/ts/devicemanager.classes.devicemanager.ts +81 -6
- package/ts/discovery/discovery.classes.networkscanner.ts +50 -1
- package/ts/events/events.observable.ts +31 -0
- package/ts/events/index.ts +4 -0
- package/ts/factories/index.ts +7 -5
- package/ts/features/feature.abstract.ts +2 -2
- package/ts/features/feature.print.ts +16 -1
- package/ts/features/feature.scan.ts +93 -27
- package/ts/index.ts +20 -0
- package/ts/interfaces/feature.interfaces.ts +22 -1
- package/ts/interfaces/index.ts +22 -3
- package/ts/plugins.ts +2 -1
- package/ts/protocols/index.ts +11 -1
- package/ts/protocols/protocol.brother.ts +648 -0
- package/ts/protocols/protocol.escl.ts +347 -190
- package/ts/protocols/protocol.ipp.ts +24 -1
- package/ts/providers/index.ts +7 -0
- package/ts/providers/provider.smb.ts +326 -0
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
const BROTHER_SCAN_PORT = 54921;
|
|
3
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
4
|
+
const DEFAULT_SCAN_TIMEOUT_MS = 10 * 60_000;
|
|
5
|
+
const DEFAULT_BUSY_RETRY_INTERVAL_MS = 1_000;
|
|
6
|
+
const DEFAULT_BUSY_TIMEOUT_MS = 30_000;
|
|
7
|
+
const MAX_PAGES = 500;
|
|
8
|
+
const MAX_PAGE_BYTES = 256 * 1024 * 1024;
|
|
9
|
+
const TERMINATOR = 0x80;
|
|
10
|
+
export class BrotherScanError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
statusCode;
|
|
13
|
+
constructor(message, code, statusCode) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.code = code;
|
|
16
|
+
this.statusCode = statusCode;
|
|
17
|
+
this.name = 'BrotherScanError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
class SocketBuffer {
|
|
21
|
+
socket;
|
|
22
|
+
buffer = Buffer.alloc(0);
|
|
23
|
+
error = null;
|
|
24
|
+
ended = false;
|
|
25
|
+
constructor(socket) {
|
|
26
|
+
this.socket = socket;
|
|
27
|
+
socket.on('data', (data) => {
|
|
28
|
+
this.buffer = Buffer.concat([this.buffer, data]);
|
|
29
|
+
});
|
|
30
|
+
socket.on('error', (error) => {
|
|
31
|
+
this.error = error;
|
|
32
|
+
});
|
|
33
|
+
socket.on('end', () => {
|
|
34
|
+
this.ended = true;
|
|
35
|
+
});
|
|
36
|
+
socket.on('close', () => {
|
|
37
|
+
this.ended = true;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
discard() {
|
|
41
|
+
this.buffer = Buffer.alloc(0);
|
|
42
|
+
}
|
|
43
|
+
async readExactly(length, timeout) {
|
|
44
|
+
await this.waitForLength(length, timeout);
|
|
45
|
+
const result = this.buffer.subarray(0, length);
|
|
46
|
+
this.buffer = this.buffer.subarray(length);
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
async peekExactly(length, timeout) {
|
|
50
|
+
await this.waitForLength(length, timeout);
|
|
51
|
+
return this.buffer.subarray(0, length);
|
|
52
|
+
}
|
|
53
|
+
async readUntil(delimiter, timeout, maxLength) {
|
|
54
|
+
const deadline = Date.now() + timeout;
|
|
55
|
+
while (true) {
|
|
56
|
+
const index = this.buffer.indexOf(delimiter);
|
|
57
|
+
if (index >= 0) {
|
|
58
|
+
const end = index + delimiter.length;
|
|
59
|
+
const result = this.buffer.subarray(0, end);
|
|
60
|
+
this.buffer = this.buffer.subarray(end);
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
63
|
+
if (this.buffer.length > maxLength) {
|
|
64
|
+
throw new BrotherScanError('Brother scanner response exceeded the expected length', 'invalid-response');
|
|
65
|
+
}
|
|
66
|
+
await this.waitForData(deadline);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
async readMatch(pattern, timeout, maxLength) {
|
|
70
|
+
const deadline = Date.now() + timeout;
|
|
71
|
+
while (true) {
|
|
72
|
+
const match = this.buffer.toString('latin1').match(pattern);
|
|
73
|
+
if (match)
|
|
74
|
+
return match;
|
|
75
|
+
if (this.buffer.length > maxLength) {
|
|
76
|
+
throw new BrotherScanError('Brother scanner lease response was malformed', 'invalid-response');
|
|
77
|
+
}
|
|
78
|
+
await this.waitForData(deadline);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
async waitForLength(length, timeout) {
|
|
82
|
+
const deadline = Date.now() + timeout;
|
|
83
|
+
while (this.buffer.length < length) {
|
|
84
|
+
await this.waitForData(deadline);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
async waitForData(deadline) {
|
|
88
|
+
if (this.error)
|
|
89
|
+
throw this.error;
|
|
90
|
+
if (this.ended) {
|
|
91
|
+
throw new BrotherScanError('Brother scanner closed the connection', 'invalid-response');
|
|
92
|
+
}
|
|
93
|
+
const remaining = deadline - Date.now();
|
|
94
|
+
if (remaining <= 0) {
|
|
95
|
+
throw new BrotherScanError('Timed out waiting for the Brother scanner', 'timeout');
|
|
96
|
+
}
|
|
97
|
+
await new Promise((resolve, reject) => {
|
|
98
|
+
const cleanup = () => {
|
|
99
|
+
clearTimeout(timer);
|
|
100
|
+
this.socket.off('data', onData);
|
|
101
|
+
this.socket.off('error', onError);
|
|
102
|
+
this.socket.off('end', onEnd);
|
|
103
|
+
this.socket.off('close', onEnd);
|
|
104
|
+
};
|
|
105
|
+
const onData = () => {
|
|
106
|
+
cleanup();
|
|
107
|
+
resolve();
|
|
108
|
+
};
|
|
109
|
+
const onError = (error) => {
|
|
110
|
+
cleanup();
|
|
111
|
+
reject(error);
|
|
112
|
+
};
|
|
113
|
+
const onEnd = () => {
|
|
114
|
+
cleanup();
|
|
115
|
+
reject(new BrotherScanError('Brother scanner closed the connection', 'invalid-response'));
|
|
116
|
+
};
|
|
117
|
+
const timer = setTimeout(() => {
|
|
118
|
+
cleanup();
|
|
119
|
+
reject(new BrotherScanError('Timed out waiting for the Brother scanner', 'timeout'));
|
|
120
|
+
}, remaining);
|
|
121
|
+
this.socket.once('data', onData);
|
|
122
|
+
this.socket.once('error', onError);
|
|
123
|
+
this.socket.once('end', onEnd);
|
|
124
|
+
this.socket.once('close', onEnd);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Brother's native network scan protocol on TCP 54921.
|
|
130
|
+
*
|
|
131
|
+
* Brother devices expose richer scan control here than they do through some
|
|
132
|
+
* eSCL implementations. The protocol returns one JPEG stream per sheet/side.
|
|
133
|
+
*/
|
|
134
|
+
export class BrotherScanProtocol {
|
|
135
|
+
address;
|
|
136
|
+
port;
|
|
137
|
+
socket = null;
|
|
138
|
+
reader = null;
|
|
139
|
+
scanning = false;
|
|
140
|
+
cancelled = false;
|
|
141
|
+
timeout;
|
|
142
|
+
scanTimeout;
|
|
143
|
+
busyRetryInterval;
|
|
144
|
+
busyTimeout;
|
|
145
|
+
constructor(address, port = BROTHER_SCAN_PORT, options = {}) {
|
|
146
|
+
this.address = address;
|
|
147
|
+
this.port = port;
|
|
148
|
+
this.timeout = options.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
149
|
+
this.scanTimeout = options.scanTimeout ?? DEFAULT_SCAN_TIMEOUT_MS;
|
|
150
|
+
this.busyRetryInterval = options.busyRetryInterval ?? DEFAULT_BUSY_RETRY_INTERVAL_MS;
|
|
151
|
+
this.busyTimeout = options.busyTimeout ?? DEFAULT_BUSY_TIMEOUT_MS;
|
|
152
|
+
}
|
|
153
|
+
async connect() {
|
|
154
|
+
if (this.socket && !this.socket.destroyed)
|
|
155
|
+
return;
|
|
156
|
+
const busyDeadline = Date.now() + this.busyTimeout;
|
|
157
|
+
while (true) {
|
|
158
|
+
try {
|
|
159
|
+
await this.connectOnce();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
await this.disconnect();
|
|
164
|
+
if (!(error instanceof BrotherScanError) ||
|
|
165
|
+
error.code !== 'busy' ||
|
|
166
|
+
Date.now() >= busyDeadline) {
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
await delay(Math.min(this.busyRetryInterval, Math.max(0, busyDeadline - Date.now())));
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async connectOnce() {
|
|
174
|
+
const socket = new plugins.net.Socket();
|
|
175
|
+
socket.setNoDelay(true);
|
|
176
|
+
this.socket = socket;
|
|
177
|
+
this.reader = new SocketBuffer(socket);
|
|
178
|
+
await new Promise((resolve, reject) => {
|
|
179
|
+
const timer = setTimeout(() => {
|
|
180
|
+
socket.destroy();
|
|
181
|
+
reject(new BrotherScanError('Timed out connecting to the Brother scanner', 'timeout'));
|
|
182
|
+
}, this.timeout);
|
|
183
|
+
const cleanup = () => {
|
|
184
|
+
clearTimeout(timer);
|
|
185
|
+
socket.off('connect', onConnect);
|
|
186
|
+
socket.off('error', onError);
|
|
187
|
+
};
|
|
188
|
+
const onConnect = () => {
|
|
189
|
+
cleanup();
|
|
190
|
+
resolve();
|
|
191
|
+
};
|
|
192
|
+
const onError = (error) => {
|
|
193
|
+
cleanup();
|
|
194
|
+
reject(error);
|
|
195
|
+
};
|
|
196
|
+
socket.once('connect', onConnect);
|
|
197
|
+
socket.once('error', onError);
|
|
198
|
+
socket.connect(this.port, this.address);
|
|
199
|
+
});
|
|
200
|
+
const banner = (await this.requireReader().readUntil(Buffer.from('\r\n'), this.timeout, 128))
|
|
201
|
+
.toString('ascii')
|
|
202
|
+
.trim();
|
|
203
|
+
if (banner.startsWith('+OK 200'))
|
|
204
|
+
return;
|
|
205
|
+
if (banner.startsWith('-NG 401')) {
|
|
206
|
+
throw new BrotherScanError('Brother scanner is busy', 'busy');
|
|
207
|
+
}
|
|
208
|
+
throw new BrotherScanError(`Unexpected Brother scanner banner: ${banner}`, 'invalid-response');
|
|
209
|
+
}
|
|
210
|
+
async disconnect() {
|
|
211
|
+
const socket = this.socket;
|
|
212
|
+
this.socket = null;
|
|
213
|
+
this.reader = null;
|
|
214
|
+
this.scanning = false;
|
|
215
|
+
if (!socket || socket.destroyed)
|
|
216
|
+
return;
|
|
217
|
+
await new Promise((resolve) => {
|
|
218
|
+
let settled = false;
|
|
219
|
+
const finish = () => {
|
|
220
|
+
if (settled)
|
|
221
|
+
return;
|
|
222
|
+
settled = true;
|
|
223
|
+
clearTimeout(timer);
|
|
224
|
+
socket.off('close', finish);
|
|
225
|
+
socket.off('error', finish);
|
|
226
|
+
if (!socket.destroyed)
|
|
227
|
+
socket.destroy();
|
|
228
|
+
resolve();
|
|
229
|
+
};
|
|
230
|
+
const timer = setTimeout(finish, 250);
|
|
231
|
+
socket.once('close', finish);
|
|
232
|
+
socket.once('error', finish);
|
|
233
|
+
socket.end();
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
getCapabilities() {
|
|
237
|
+
return {
|
|
238
|
+
resolutions: [100, 150, 200, 300, 600],
|
|
239
|
+
formats: ['jpeg'],
|
|
240
|
+
colorModes: ['color'],
|
|
241
|
+
sources: ['flatbed', 'adf', 'adf-duplex'],
|
|
242
|
+
maxWidth: 215.9,
|
|
243
|
+
maxHeight: 355.6,
|
|
244
|
+
minWidth: 10,
|
|
245
|
+
minHeight: 10,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
async scan(options) {
|
|
249
|
+
if (!this.socket || !this.reader) {
|
|
250
|
+
throw new Error('Brother scanner is not connected');
|
|
251
|
+
}
|
|
252
|
+
if (this.scanning) {
|
|
253
|
+
throw new BrotherScanError('A Brother scan is already in progress', 'busy');
|
|
254
|
+
}
|
|
255
|
+
this.validateOptions(options);
|
|
256
|
+
this.scanning = true;
|
|
257
|
+
this.cancelled = false;
|
|
258
|
+
try {
|
|
259
|
+
await this.selectSource(options.source);
|
|
260
|
+
const lease = await this.requestLease(options.resolution);
|
|
261
|
+
this.assertLease(lease, options);
|
|
262
|
+
const area = this.resolveScanArea(options.area, lease);
|
|
263
|
+
await this.writeCommand([
|
|
264
|
+
'\x1bX',
|
|
265
|
+
`R=${lease.resolutionX},${lease.resolutionY}`,
|
|
266
|
+
'M=CGRAY',
|
|
267
|
+
'C=JPEG',
|
|
268
|
+
'J=MID',
|
|
269
|
+
'B=50',
|
|
270
|
+
'N=50',
|
|
271
|
+
`A=${area.x},${area.y},${area.x + area.width},${area.y + area.height}`,
|
|
272
|
+
options.source === 'adf-duplex' ? 'D=DUP' : 'D=SIN',
|
|
273
|
+
]);
|
|
274
|
+
const pages = await this.readPages();
|
|
275
|
+
if (pages.length === 0) {
|
|
276
|
+
throw new BrotherScanError('Brother scanner returned no document data', 'no-document');
|
|
277
|
+
}
|
|
278
|
+
const firstMetadata = readJpegMetadata(pages[0]);
|
|
279
|
+
return {
|
|
280
|
+
data: pages[0],
|
|
281
|
+
format: 'jpeg',
|
|
282
|
+
width: firstMetadata.width ?? area.width,
|
|
283
|
+
height: firstMetadata.height ?? area.height,
|
|
284
|
+
resolution: firstMetadata.resolution ?? lease.resolutionX,
|
|
285
|
+
colorMode: 'color',
|
|
286
|
+
mimeType: 'image/jpeg',
|
|
287
|
+
pageCount: pages.length,
|
|
288
|
+
pages: pages.map((data) => {
|
|
289
|
+
const metadata = readJpegMetadata(data);
|
|
290
|
+
return {
|
|
291
|
+
data,
|
|
292
|
+
width: metadata.width ?? area.width,
|
|
293
|
+
height: metadata.height ?? area.height,
|
|
294
|
+
mimeType: 'image/jpeg',
|
|
295
|
+
};
|
|
296
|
+
}),
|
|
297
|
+
isComplete: true,
|
|
298
|
+
settingsWarnings: [],
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
catch (error) {
|
|
302
|
+
if (this.cancelled) {
|
|
303
|
+
throw new BrotherScanError('Brother scan was cancelled', 'cancelled');
|
|
304
|
+
}
|
|
305
|
+
try {
|
|
306
|
+
await this.write(Buffer.from([0x1b, 0x52]));
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
// Preserve the scan error if the connection is already gone.
|
|
310
|
+
}
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
finally {
|
|
314
|
+
this.scanning = false;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
async cancel() {
|
|
318
|
+
if (!this.socket || !this.scanning)
|
|
319
|
+
return;
|
|
320
|
+
this.cancelled = true;
|
|
321
|
+
await this.write(Buffer.from([0x1b, 0x52]));
|
|
322
|
+
}
|
|
323
|
+
validateOptions(options) {
|
|
324
|
+
if (options.format !== 'jpeg') {
|
|
325
|
+
throw new BrotherScanError(`Brother native scanning returns JPEG pages, not ${options.format}`, 'unsupported');
|
|
326
|
+
}
|
|
327
|
+
if (options.colorMode !== 'color') {
|
|
328
|
+
throw new BrotherScanError(`Brother native ${options.colorMode} decoding is not implemented`, 'unsupported');
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
async selectSource(source) {
|
|
332
|
+
const brotherSource = source === 'flatbed' ? 'FB' : 'AUTO';
|
|
333
|
+
await this.writeCommand(['\x1bS', brotherSource]);
|
|
334
|
+
const response = await this.requireReader().readExactly(1, this.timeout);
|
|
335
|
+
if (response[0] !== TERMINATOR) {
|
|
336
|
+
throw this.statusError(response[0], 'Brother scanner rejected the requested source');
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
async requestLease(resolution) {
|
|
340
|
+
await this.writeCommand(['\x1bI', `R=${resolution},${resolution}`, 'M=CGRAY']);
|
|
341
|
+
const match = await this.requireReader().readMatch(/(\d+),(\d+),(\d+),(\d+),(\d+),(\d+),(\d+)/, this.timeout, 256);
|
|
342
|
+
this.requireReader().discard();
|
|
343
|
+
const values = match.slice(1).map((value) => Number.parseInt(value, 10));
|
|
344
|
+
return {
|
|
345
|
+
resolutionX: values[0],
|
|
346
|
+
resolutionY: values[1],
|
|
347
|
+
adfStatus: values[2],
|
|
348
|
+
planeWidth: values[3],
|
|
349
|
+
width: values[4],
|
|
350
|
+
planeHeight: values[5],
|
|
351
|
+
height: values[6],
|
|
352
|
+
};
|
|
353
|
+
}
|
|
354
|
+
assertLease(lease, options) {
|
|
355
|
+
if (lease.resolutionX !== options.resolution || lease.resolutionY !== options.resolution) {
|
|
356
|
+
throw new BrotherScanError(`Brother scanner rejected ${options.resolution} dpi and offered ${lease.resolutionX}x${lease.resolutionY} dpi`, 'settings-rejected');
|
|
357
|
+
}
|
|
358
|
+
if (lease.width <= 0 || lease.height < 0) {
|
|
359
|
+
throw new BrotherScanError('Brother scanner returned an invalid scan area', 'invalid-response');
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
resolveScanArea(area, lease) {
|
|
363
|
+
const mmToPixels = (millimetres, dpi) => Math.round((millimetres * dpi) / 25.4);
|
|
364
|
+
const x = Math.max(0, mmToPixels(area.x, lease.resolutionX));
|
|
365
|
+
const y = Math.max(0, mmToPixels(area.y, lease.resolutionY));
|
|
366
|
+
const requestedWidth = mmToPixels(area.width, lease.resolutionX);
|
|
367
|
+
const requestedHeight = mmToPixels(area.height, lease.resolutionY);
|
|
368
|
+
const width = Math.max(1, Math.min(requestedWidth, lease.width - x));
|
|
369
|
+
// Brother ADF leases report zero height because page length is determined
|
|
370
|
+
// while feeding. Platen leases provide a fixed pixel height.
|
|
371
|
+
const height = lease.height === 0
|
|
372
|
+
? Math.max(1, requestedHeight)
|
|
373
|
+
: Math.max(1, Math.min(requestedHeight, lease.height - y));
|
|
374
|
+
if (x >= lease.width || (lease.height > 0 && y >= lease.height)) {
|
|
375
|
+
throw new BrotherScanError('Requested scan area is outside the scanner bed', 'settings-rejected');
|
|
376
|
+
}
|
|
377
|
+
return { x, y, width, height };
|
|
378
|
+
}
|
|
379
|
+
async readPages() {
|
|
380
|
+
const pages = [];
|
|
381
|
+
let chunks = [];
|
|
382
|
+
let pageBytes = 0;
|
|
383
|
+
const wrappedChunks = new Map();
|
|
384
|
+
const wrappedPageBytes = new Map();
|
|
385
|
+
const wrappedPages = new Map();
|
|
386
|
+
let frameMode;
|
|
387
|
+
while (pages.length + wrappedPages.size < MAX_PAGES) {
|
|
388
|
+
const header = (await this.requireReader().readExactly(1, this.scanTimeout))[0];
|
|
389
|
+
if (header < 0x80) {
|
|
390
|
+
const lengthBytes = await this.requireReader().readExactly(2, this.scanTimeout);
|
|
391
|
+
const firstLength = lengthBytes.readUInt16LE(0);
|
|
392
|
+
if (!frameMode) {
|
|
393
|
+
const startsWithJpeg = firstLength >= 2 &&
|
|
394
|
+
(await this.requireReader().peekExactly(2, this.scanTimeout)).equals(Buffer.from([0xff, 0xd8]));
|
|
395
|
+
frameMode = firstLength <= 64 && !startsWithJpeg ? 'wrapped' : 'simple';
|
|
396
|
+
}
|
|
397
|
+
if (frameMode === 'wrapped') {
|
|
398
|
+
const metadata = await this.requireReader().readExactly(firstLength, this.scanTimeout);
|
|
399
|
+
const dataLengthBytes = await this.requireReader().readExactly(2, this.scanTimeout);
|
|
400
|
+
const dataLength = dataLengthBytes.readUInt16LE(0);
|
|
401
|
+
const imageNumber = metadata.length >= 2 ? metadata.readUInt16LE(0) : 0;
|
|
402
|
+
const imageChunks = wrappedChunks.get(imageNumber) ?? [];
|
|
403
|
+
imageChunks.push(await this.requireReader().readExactly(dataLength, this.scanTimeout));
|
|
404
|
+
wrappedChunks.set(imageNumber, imageChunks);
|
|
405
|
+
const imageBytes = (wrappedPageBytes.get(imageNumber) ?? 0) + dataLength;
|
|
406
|
+
wrappedPageBytes.set(imageNumber, imageBytes);
|
|
407
|
+
if (imageBytes > MAX_PAGE_BYTES) {
|
|
408
|
+
throw new BrotherScanError('Brother scanner page exceeded the safety limit', 'invalid-response');
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
else {
|
|
412
|
+
chunks.push(await this.requireReader().readExactly(firstLength, this.scanTimeout));
|
|
413
|
+
pageBytes += firstLength;
|
|
414
|
+
if (pageBytes > MAX_PAGE_BYTES) {
|
|
415
|
+
throw new BrotherScanError('Brother scanner page exceeded the safety limit', 'invalid-response');
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (header === 0x84 || header === 0x85) {
|
|
421
|
+
await this.requireReader().readExactly(1, this.scanTimeout);
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
if (header === 0x81) {
|
|
425
|
+
this.finishPage(chunks, pages);
|
|
426
|
+
chunks = [];
|
|
427
|
+
pageBytes = 0;
|
|
428
|
+
frameMode = undefined;
|
|
429
|
+
await this.writeCommand(['\x1bX']);
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
if (header === 0x82) {
|
|
433
|
+
const metadata = await this.requireReader().readExactly(9, this.scanTimeout);
|
|
434
|
+
const imageNumber = metadata.readUInt16LE(2);
|
|
435
|
+
let imageChunks = wrappedChunks.get(imageNumber);
|
|
436
|
+
let resolvedImageNumber = imageNumber;
|
|
437
|
+
if (!imageChunks && wrappedChunks.size === 1) {
|
|
438
|
+
const onlyImage = wrappedChunks.entries().next().value;
|
|
439
|
+
resolvedImageNumber = onlyImage[0];
|
|
440
|
+
imageChunks = onlyImage[1];
|
|
441
|
+
}
|
|
442
|
+
const page = this.makePage(imageChunks ?? []);
|
|
443
|
+
if (page)
|
|
444
|
+
wrappedPages.set(resolvedImageNumber, page);
|
|
445
|
+
wrappedChunks.delete(resolvedImageNumber);
|
|
446
|
+
wrappedPageBytes.delete(resolvedImageNumber);
|
|
447
|
+
frameMode = undefined;
|
|
448
|
+
continue;
|
|
449
|
+
}
|
|
450
|
+
if (header === TERMINATOR) {
|
|
451
|
+
this.finishPage(chunks, pages);
|
|
452
|
+
for (const [imageNumber, imageChunks] of wrappedChunks) {
|
|
453
|
+
const page = this.makePage(imageChunks);
|
|
454
|
+
if (page)
|
|
455
|
+
wrappedPages.set(imageNumber, page);
|
|
456
|
+
}
|
|
457
|
+
pages.push(...[...wrappedPages.entries()]
|
|
458
|
+
.sort(([left], [right]) => left - right)
|
|
459
|
+
.map(([, page]) => page));
|
|
460
|
+
return pages;
|
|
461
|
+
}
|
|
462
|
+
throw this.statusError(header, 'Brother scanner stopped the scan');
|
|
463
|
+
}
|
|
464
|
+
throw new BrotherScanError(`Brother scanner exceeded the ${MAX_PAGES}-page safety limit`, 'invalid-response');
|
|
465
|
+
}
|
|
466
|
+
finishPage(chunks, pages) {
|
|
467
|
+
const page = this.makePage(chunks);
|
|
468
|
+
if (page)
|
|
469
|
+
pages.push(page);
|
|
470
|
+
}
|
|
471
|
+
makePage(chunks) {
|
|
472
|
+
if (chunks.length === 0)
|
|
473
|
+
return undefined;
|
|
474
|
+
const page = Buffer.concat(chunks);
|
|
475
|
+
if (page[0] !== 0xff || page[1] !== 0xd8) {
|
|
476
|
+
const firstBytes = page.subarray(0, 8).toString('hex');
|
|
477
|
+
const lastBytes = page.subarray(Math.max(0, page.length - 8)).toString('hex');
|
|
478
|
+
throw new BrotherScanError(`Brother scanner returned an invalid JPEG page (${page.length} bytes, first ${firstBytes}, last ${lastBytes})`, 'invalid-response');
|
|
479
|
+
}
|
|
480
|
+
const endMarker = page.lastIndexOf(Buffer.from([0xff, 0xd9]));
|
|
481
|
+
return endMarker >= 0
|
|
482
|
+
? page.subarray(0, endMarker + 2)
|
|
483
|
+
: Buffer.concat([page, Buffer.from([0xff, 0xd9])]);
|
|
484
|
+
}
|
|
485
|
+
statusError(status, prefix) {
|
|
486
|
+
if (status === 0xc2)
|
|
487
|
+
return new BrotherScanError(`${prefix}: no document in feeder`, 'no-document', status);
|
|
488
|
+
if (status === 0xc3)
|
|
489
|
+
return new BrotherScanError(`${prefix}: document jam`, 'document-jam', status);
|
|
490
|
+
if (status === 0xc4)
|
|
491
|
+
return new BrotherScanError(`${prefix}: cover open`, 'cover-open', status);
|
|
492
|
+
if (status === 0xc5)
|
|
493
|
+
return new BrotherScanError(`${prefix}: service error`, 'service-error', status);
|
|
494
|
+
if (status === 0xc6) {
|
|
495
|
+
return new BrotherScanError(`${prefix}: device is stuck and must be restarted`, 'device-stuck', status);
|
|
496
|
+
}
|
|
497
|
+
if (status === 0x83 || status === 0x86 || status === 0xe3) {
|
|
498
|
+
return new BrotherScanError(`${prefix}: cancelled`, 'cancelled', status);
|
|
499
|
+
}
|
|
500
|
+
return new BrotherScanError(`${prefix}: status 0x${status.toString(16)}`, 'invalid-response', status);
|
|
501
|
+
}
|
|
502
|
+
async writeCommand(lines) {
|
|
503
|
+
const command = `${lines.join('\n')}\n`;
|
|
504
|
+
await this.write(Buffer.concat([Buffer.from(command, 'ascii'), Buffer.from([TERMINATOR])]));
|
|
505
|
+
}
|
|
506
|
+
async write(data) {
|
|
507
|
+
const socket = this.socket;
|
|
508
|
+
if (!socket || socket.destroyed) {
|
|
509
|
+
throw new BrotherScanError('Brother scanner is not connected', 'invalid-response');
|
|
510
|
+
}
|
|
511
|
+
await new Promise((resolve, reject) => {
|
|
512
|
+
socket.write(data, (error) => error ? reject(error) : resolve());
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
requireReader() {
|
|
516
|
+
if (!this.reader)
|
|
517
|
+
throw new BrotherScanError('Brother scanner is not connected', 'invalid-response');
|
|
518
|
+
return this.reader;
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
function delay(milliseconds) {
|
|
522
|
+
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
523
|
+
}
|
|
524
|
+
function readJpegMetadata(data) {
|
|
525
|
+
if (data.length < 4 || data[0] !== 0xff || data[1] !== 0xd8)
|
|
526
|
+
return {};
|
|
527
|
+
const metadata = {};
|
|
528
|
+
const startOfFrameMarkers = new Set([0xc0, 0xc1, 0xc2, 0xc3, 0xc5, 0xc6, 0xc7, 0xc9, 0xca, 0xcb, 0xcd, 0xce, 0xcf]);
|
|
529
|
+
let offset = 2;
|
|
530
|
+
while (offset + 4 <= data.length) {
|
|
531
|
+
while (offset < data.length && data[offset] === 0xff)
|
|
532
|
+
offset++;
|
|
533
|
+
const marker = data[offset++];
|
|
534
|
+
if (marker === 0xd9 || marker === 0xda)
|
|
535
|
+
break;
|
|
536
|
+
if (marker === 0x01 || (marker >= 0xd0 && marker <= 0xd7))
|
|
537
|
+
continue;
|
|
538
|
+
if (offset + 2 > data.length)
|
|
539
|
+
break;
|
|
540
|
+
const length = data.readUInt16BE(offset);
|
|
541
|
+
if (length < 2 || offset + length > data.length)
|
|
542
|
+
break;
|
|
543
|
+
const content = offset + 2;
|
|
544
|
+
if (marker === 0xe0 && length >= 16 && data.toString('ascii', content, content + 5) === 'JFIF\0') {
|
|
545
|
+
const units = data[content + 7];
|
|
546
|
+
const density = data.readUInt16BE(content + 8);
|
|
547
|
+
if (units === 1 && density > 0)
|
|
548
|
+
metadata.resolution = density;
|
|
549
|
+
if (units === 2 && density > 0)
|
|
550
|
+
metadata.resolution = Math.round(density * 2.54);
|
|
551
|
+
}
|
|
552
|
+
if (startOfFrameMarkers.has(marker) && length >= 7) {
|
|
553
|
+
metadata.height = data.readUInt16BE(content + 1);
|
|
554
|
+
metadata.width = data.readUInt16BE(content + 3);
|
|
555
|
+
}
|
|
556
|
+
offset += length;
|
|
557
|
+
}
|
|
558
|
+
return metadata;
|
|
559
|
+
}
|
|
560
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdG9jb2wuYnJvdGhlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL3Byb3RvY29scy9wcm90b2NvbC5icm90aGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBVXpDLE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDO0FBQ2hDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDO0FBQ2xDLE1BQU0sdUJBQXVCLEdBQUcsRUFBRSxHQUFHLE1BQU0sQ0FBQztBQUM1QyxNQUFNLDhCQUE4QixHQUFHLEtBQUssQ0FBQztBQUM3QyxNQUFNLHVCQUF1QixHQUFHLE1BQU0sQ0FBQztBQUN2QyxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUM7QUFDdEIsTUFBTSxjQUFjLEdBQUcsR0FBRyxHQUFHLElBQUksR0FBRyxJQUFJLENBQUM7QUFDekMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDO0FBZXhCLE1BQU0sT0FBTyxnQkFBaUIsU0FBUSxLQUFLO0lBR3ZCO0lBQ0E7SUFIbEIsWUFDRSxPQUFlLEVBQ0MsSUFBMkIsRUFDM0IsVUFBbUI7UUFFbkMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBSEMsU0FBSSxHQUFKLElBQUksQ0FBdUI7UUFDM0IsZUFBVSxHQUFWLFVBQVUsQ0FBUztRQUduQyxJQUFJLENBQUMsSUFBSSxHQUFHLGtCQUFrQixDQUFDO0lBQ2pDLENBQUM7Q0FDRjtBQThCRCxNQUFNLFlBQVk7SUFLYTtJQUpyQixNQUFNLEdBQUcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN6QixLQUFLLEdBQWlCLElBQUksQ0FBQztJQUMzQixLQUFLLEdBQUcsS0FBSyxDQUFDO0lBRXRCLFlBQTZCLE1BQTBCO1FBQTFCLFdBQU0sR0FBTixNQUFNLENBQW9CO1FBQ3JELE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBWSxFQUFFLEVB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
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import type { IEsclCapabilities, IEsclScanStatus, IScanOptions, IScanResult } from '../interfaces/index.js';
|
|
2
|
+
export declare class EsclScanError extends Error {
|
|
3
|
+
readonly partialResult?: IScanResult | undefined;
|
|
4
|
+
constructor(message: string, partialResult?: IScanResult | undefined);
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
7
|
* eSCL/AirScan protocol client for network scanners
|
|
4
8
|
*/
|
|
5
9
|
export declare class EsclProtocol {
|
|
6
10
|
private baseUrl;
|
|
7
11
|
private capabilities;
|
|
12
|
+
private activeJobUri;
|
|
8
13
|
constructor(address: string, port: number, secure?: boolean);
|
|
9
14
|
/**
|
|
10
15
|
* Get scanner capabilities
|
|
@@ -27,30 +32,34 @@ export declare class EsclProtocol {
|
|
|
27
32
|
* until complete. We try direct download first, then fall back to polling.
|
|
28
33
|
*/
|
|
29
34
|
waitForScanComplete(jobUri: string, options: IScanOptions, pollInterval?: number): Promise<IScanResult>;
|
|
35
|
+
private combinePages;
|
|
30
36
|
/**
|
|
31
37
|
* Download scanned document
|
|
32
38
|
*/
|
|
33
39
|
downloadScan(jobUri: string, options: IScanOptions): Promise<IScanResult>;
|
|
40
|
+
private downloadNextDocument;
|
|
34
41
|
/**
|
|
35
42
|
* Cancel a scan job
|
|
36
43
|
*/
|
|
37
44
|
cancelJob(jobUri: string): Promise<void>;
|
|
45
|
+
cancelCurrentScan(): Promise<void>;
|
|
38
46
|
/**
|
|
39
47
|
* Build XML scan settings
|
|
40
48
|
*/
|
|
41
49
|
private buildScanSettings;
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
*/
|
|
45
|
-
private mapSource;
|
|
50
|
+
private mapIntent;
|
|
51
|
+
private nextDocumentDelay;
|
|
46
52
|
/**
|
|
47
53
|
* Parse capabilities XML response
|
|
48
54
|
*/
|
|
49
55
|
private parseCapabilities;
|
|
56
|
+
private parseInputSource;
|
|
50
57
|
/**
|
|
51
58
|
* Parse status XML response
|
|
52
59
|
*/
|
|
53
60
|
private parseStatus;
|
|
61
|
+
private resolveJobUri;
|
|
62
|
+
private findJob;
|
|
54
63
|
/**
|
|
55
64
|
* Perform a complete scan operation
|
|
56
65
|
*/
|