@ecobridge.xyz/devicemanager 3.0.2 → 3.1.1
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/.gitea/workflows/default_tags.yaml +0 -21
- package/.smartconfig.json +69 -0
- package/changelog.md +23 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/devicemanager.classes.devicemanager.js +33 -7
- package/dist_ts/discovery/discovery.classes.mdns.js +46 -11
- package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +1 -1
- package/dist_ts/discovery/discovery.classes.networkscanner.js +1 -1
- package/dist_ts/discovery/discovery.classes.ssdp.d.ts +52 -21
- package/dist_ts/discovery/discovery.classes.ssdp.js +407 -117
- package/dist_ts/features/feature.print.d.ts +4 -2
- package/dist_ts/features/feature.print.js +48 -38
- package/dist_ts/index.d.ts +1 -1
- package/dist_ts/interfaces/feature.interfaces.d.ts +1 -1
- package/dist_ts/interfaces/index.d.ts +1 -1
- package/dist_ts/plugins.d.ts +5 -15
- package/dist_ts/plugins.js +6 -19
- package/dist_ts/protocols/index.d.ts +1 -1
- package/dist_ts/protocols/index.js +2 -2
- package/dist_ts/protocols/protocol.escl.js +2 -2
- package/dist_ts/protocols/protocol.ipp.d.ts +144 -33
- package/dist_ts/protocols/protocol.ipp.js +942 -239
- package/license.md +21 -0
- package/package.json +16 -25
- package/pnpm-workspace.yaml +4 -0
- package/readme.md +61 -76
- package/test/{test.ts → test.node.ts} +20 -45
- package/test/test.ssdp.node.ts +978 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/devicemanager.classes.devicemanager.ts +44 -6
- package/ts/discovery/discovery.classes.mdns.ts +40 -11
- package/ts/discovery/discovery.classes.networkscanner.ts +1 -1
- package/ts/discovery/discovery.classes.ssdp.ts +493 -130
- package/ts/features/feature.print.ts +53 -45
- package/ts/index.ts +1 -0
- package/ts/interfaces/feature.interfaces.ts +1 -1
- package/ts/interfaces/index.ts +1 -1
- package/ts/plugins.ts +5 -25
- package/ts/protocols/index.ts +6 -1
- package/ts/protocols/protocol.escl.ts +1 -1
- package/ts/protocols/protocol.ipp.ts +1183 -260
- package/npmextra.json +0 -24
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { Feature, type TDeviceReference } from './feature.abstract.js';
|
|
7
|
-
import { IppProtocol } from '../protocols/index.js';
|
|
7
|
+
import { IppProtocol, type IIppPrinterCapabilities, type IIppJob } from '../protocols/index.js';
|
|
8
8
|
import type {
|
|
9
9
|
TPrintProtocol,
|
|
10
10
|
TPrintSides,
|
|
@@ -16,7 +16,6 @@ import type {
|
|
|
16
16
|
IPrintFeatureInfo,
|
|
17
17
|
IFeatureOptions,
|
|
18
18
|
} from '../interfaces/feature.interfaces.js';
|
|
19
|
-
import type { IPrinterCapabilities } from '../interfaces/index.js';
|
|
20
19
|
|
|
21
20
|
/**
|
|
22
21
|
* Options for creating a PrintFeature
|
|
@@ -101,7 +100,7 @@ export class PrintFeature extends Feature {
|
|
|
101
100
|
|
|
102
101
|
this.ippClient = new IppProtocol(address, port, path);
|
|
103
102
|
// Verify connection by getting printer attributes
|
|
104
|
-
const attrs = await this.ippClient.
|
|
103
|
+
const attrs = await this.ippClient.getPrinterAttributes();
|
|
105
104
|
this.updateCapabilitiesFromIpp(attrs);
|
|
106
105
|
}
|
|
107
106
|
// JetDirect and LPD don't need connection verification
|
|
@@ -154,7 +153,8 @@ export class PrintFeature extends Feature {
|
|
|
154
153
|
throw new Error('Print feature not connected');
|
|
155
154
|
}
|
|
156
155
|
|
|
157
|
-
|
|
156
|
+
const jobs = await this.ippClient.getJobs();
|
|
157
|
+
return jobs.map(job => this.mapIppJobToInternal(job));
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
/**
|
|
@@ -165,7 +165,8 @@ export class PrintFeature extends Feature {
|
|
|
165
165
|
throw new Error('Print feature not connected');
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
const job = await this.ippClient.getJobAttributes(jobId);
|
|
169
|
+
return this.mapIppJobToInternal(job);
|
|
169
170
|
}
|
|
170
171
|
|
|
171
172
|
/**
|
|
@@ -191,9 +192,17 @@ export class PrintFeature extends Feature {
|
|
|
191
192
|
|
|
192
193
|
this.emit('print:started', options);
|
|
193
194
|
|
|
194
|
-
//
|
|
195
|
-
const
|
|
195
|
+
// Use smartPrint for auto format detection and conversion
|
|
196
|
+
const ippJob = await this.ippClient.smartPrint(data, {
|
|
197
|
+
jobName: options?.jobName,
|
|
198
|
+
copies: options?.copies,
|
|
199
|
+
media: options?.mediaSize,
|
|
200
|
+
sides: options?.sides,
|
|
201
|
+
printQuality: options?.quality,
|
|
202
|
+
colorMode: options?.colorMode,
|
|
203
|
+
});
|
|
196
204
|
|
|
205
|
+
const job = this.mapIppJobToInternal(ippJob);
|
|
197
206
|
this.emit('print:submitted', job);
|
|
198
207
|
return job;
|
|
199
208
|
}
|
|
@@ -202,58 +211,57 @@ export class PrintFeature extends Feature {
|
|
|
202
211
|
// Helper Methods
|
|
203
212
|
// ============================================================================
|
|
204
213
|
|
|
205
|
-
private updateCapabilitiesFromIpp(caps:
|
|
214
|
+
private updateCapabilitiesFromIpp(caps: IIppPrinterCapabilities): void {
|
|
206
215
|
this.supportsColor = caps.colorSupported;
|
|
207
|
-
|
|
208
|
-
this.
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
216
|
+
// Derive duplexSupported from sidesSupported
|
|
217
|
+
this.supportsDuplex = caps.sidesSupported?.some(s =>
|
|
218
|
+
s.includes('two-sided')
|
|
219
|
+
) ?? false;
|
|
220
|
+
// Get max copies from range
|
|
221
|
+
this.maxCopies = caps.copiesSupported?.upper ?? 99;
|
|
222
|
+
|
|
223
|
+
if (caps.mediaSizeSupported && caps.mediaSizeSupported.length > 0) {
|
|
224
|
+
this.supportedMediaSizes = caps.mediaSizeSupported;
|
|
212
225
|
}
|
|
213
|
-
if (caps.
|
|
214
|
-
this.supportedMediaTypes = caps.
|
|
226
|
+
if (caps.mediaTypeSupported && caps.mediaTypeSupported.length > 0) {
|
|
227
|
+
this.supportedMediaTypes = caps.mediaTypeSupported;
|
|
215
228
|
}
|
|
216
229
|
if (caps.sidesSupported && caps.sidesSupported.length > 0) {
|
|
217
230
|
this.supportedSides = caps.sidesSupported.filter((s): s is TPrintSides =>
|
|
218
231
|
['one-sided', 'two-sided-long-edge', 'two-sided-short-edge'].includes(s)
|
|
219
232
|
);
|
|
220
233
|
}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
private qualityToIpp(quality: TPrintQuality): number {
|
|
229
|
-
switch (quality) {
|
|
230
|
-
case 'draft': return 3;
|
|
231
|
-
case 'normal': return 4;
|
|
232
|
-
case 'high': return 5;
|
|
233
|
-
default: return 4;
|
|
234
|
+
// Map IPP quality values (3=draft, 4=normal, 5=high) to strings
|
|
235
|
+
if (caps.printQualitySupported && caps.printQualitySupported.length > 0) {
|
|
236
|
+
const qualityMap: Record<number, TPrintQuality> = { 3: 'draft', 4: 'normal', 5: 'high' };
|
|
237
|
+
this.supportedQualities = caps.printQualitySupported
|
|
238
|
+
.map(q => qualityMap[q])
|
|
239
|
+
.filter((q): q is TPrintQuality => q !== undefined);
|
|
234
240
|
}
|
|
235
241
|
}
|
|
236
242
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
243
|
+
/**
|
|
244
|
+
* Map IIppJob to IPrintJob, normalizing extended states
|
|
245
|
+
*/
|
|
246
|
+
private mapIppJobToInternal(job: IIppJob): IPrintJob {
|
|
247
|
+
// Map extended IPP states to simpler internal states
|
|
248
|
+
const stateMap: Record<IIppJob['state'], IPrintJob['state']> = {
|
|
249
|
+
'pending': 'pending',
|
|
250
|
+
'pending-held': 'pending',
|
|
251
|
+
'processing': 'processing',
|
|
252
|
+
'processing-stopped': 'processing',
|
|
253
|
+
'canceled': 'canceled',
|
|
254
|
+
'aborted': 'aborted',
|
|
255
|
+
'completed': 'completed',
|
|
246
256
|
};
|
|
247
257
|
|
|
248
258
|
return {
|
|
249
|
-
id: job
|
|
250
|
-
name: job
|
|
251
|
-
state: stateMap[
|
|
252
|
-
stateReason:
|
|
253
|
-
createdAt:
|
|
254
|
-
completedAt: job
|
|
255
|
-
? new Date((job['time-at-completed'] as number) * 1000)
|
|
256
|
-
: undefined,
|
|
259
|
+
id: job.id,
|
|
260
|
+
name: job.name,
|
|
261
|
+
state: stateMap[job.state],
|
|
262
|
+
stateReason: job.stateReasons?.[0],
|
|
263
|
+
createdAt: job.createdAt,
|
|
264
|
+
completedAt: job.completedAt,
|
|
257
265
|
};
|
|
258
266
|
}
|
|
259
267
|
|
package/ts/index.ts
CHANGED
|
@@ -168,7 +168,7 @@ export interface IPrintJob {
|
|
|
168
168
|
name: string;
|
|
169
169
|
state: 'pending' | 'processing' | 'completed' | 'canceled' | 'aborted';
|
|
170
170
|
stateReason?: string;
|
|
171
|
-
createdAt
|
|
171
|
+
createdAt?: Date;
|
|
172
172
|
completedAt?: Date;
|
|
173
173
|
pagesPrinted?: number;
|
|
174
174
|
pagesTotal?: number;
|
package/ts/interfaces/index.ts
CHANGED
|
@@ -154,7 +154,7 @@ export interface IPrintJob {
|
|
|
154
154
|
name: string;
|
|
155
155
|
state: 'pending' | 'processing' | 'completed' | 'canceled' | 'aborted';
|
|
156
156
|
stateReason?: string;
|
|
157
|
-
createdAt
|
|
157
|
+
createdAt?: Date;
|
|
158
158
|
completedAt?: Date;
|
|
159
159
|
pagesPrinted?: number;
|
|
160
160
|
pagesTotal?: number;
|
package/ts/plugins.ts
CHANGED
|
@@ -1,41 +1,21 @@
|
|
|
1
1
|
// native scope
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import * as net from 'net';
|
|
4
|
-
import * as dgram from 'dgram';
|
|
4
|
+
import * as dgram from 'node:dgram';
|
|
5
|
+
import * as os from 'node:os';
|
|
5
6
|
import * as events from 'events';
|
|
6
7
|
|
|
7
|
-
export { path, net, dgram, events };
|
|
8
|
+
export { path, net, dgram, os, events };
|
|
8
9
|
|
|
9
10
|
// @push.rocks scope
|
|
10
11
|
import * as smartpath from '@push.rocks/smartpath';
|
|
11
|
-
import * as smartpromise from '@push.rocks/smartpromise';
|
|
12
12
|
import * as smartdelay from '@push.rocks/smartdelay';
|
|
13
|
-
import * as smartnetwork from '@push.rocks/smartnetwork';
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
import { SmartRequest } from '@push.rocks/smartrequest';
|
|
17
|
-
export { SmartRequest };
|
|
18
|
-
|
|
19
|
-
export {
|
|
20
|
-
smartpath,
|
|
21
|
-
smartpromise,
|
|
22
|
-
smartdelay,
|
|
23
|
-
smartnetwork,
|
|
24
|
-
};
|
|
14
|
+
export { smartpath, smartdelay };
|
|
25
15
|
|
|
26
16
|
// third party
|
|
27
17
|
import * as bonjourService from 'bonjour-service';
|
|
28
|
-
import ipp from 'ipp';
|
|
29
|
-
import nodeSsdpModule from 'node-ssdp';
|
|
30
18
|
import * as netSnmp from 'net-snmp';
|
|
31
|
-
import * as sonos from 'sonos';
|
|
32
|
-
import * as castv2Client from 'castv2-client';
|
|
33
19
|
import WebSocket from 'ws';
|
|
34
20
|
|
|
35
|
-
|
|
36
|
-
const nodeSsdp = {
|
|
37
|
-
Client: nodeSsdpModule.Client,
|
|
38
|
-
Server: nodeSsdpModule.Server,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
export { bonjourService, ipp, nodeSsdp, netSnmp, sonos, castv2Client, WebSocket };
|
|
21
|
+
export { bonjourService, netSnmp, WebSocket };
|
package/ts/protocols/index.ts
CHANGED
|
@@ -10,7 +10,12 @@ export { EsclProtocol } from './protocol.escl.js';
|
|
|
10
10
|
export { SaneProtocol } from './protocol.sane.js';
|
|
11
11
|
|
|
12
12
|
// IPP printer protocol
|
|
13
|
-
export {
|
|
13
|
+
export {
|
|
14
|
+
IppProtocol,
|
|
15
|
+
type IIppPrinterCapabilities,
|
|
16
|
+
type IIppJob,
|
|
17
|
+
type IIppPrintOptions,
|
|
18
|
+
} from './protocol.ipp.js';
|
|
14
19
|
|
|
15
20
|
// SNMP query protocol
|
|
16
21
|
export {
|
|
@@ -118,7 +118,7 @@ export class EsclProtocol {
|
|
|
118
118
|
public async submitScanJob(options: IScanOptions): Promise<string> {
|
|
119
119
|
const scanSettings = this.buildScanSettings(options);
|
|
120
120
|
|
|
121
|
-
// Use fetch for
|
|
121
|
+
// Use fetch for the raw XML request body.
|
|
122
122
|
const response = await fetch(`${this.baseUrl}/ScanJobs`, {
|
|
123
123
|
method: 'POST',
|
|
124
124
|
headers: {
|