@ecobridge.xyz/devicemanager 3.0.2
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_nottags.yaml +66 -0
- package/.gitea/workflows/default_tags.yaml +124 -0
- package/.vscode/launch.json +11 -0
- package/.vscode/settings.json +26 -0
- package/changelog.md +91 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/device/device.classes.device.d.ts +205 -0
- package/dist_ts/device/device.classes.device.js +344 -0
- package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
- package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
- package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
- package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
- package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
- package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
- package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
- package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
- package/dist_ts/factories/index.d.ts +190 -0
- package/dist_ts/factories/index.js +350 -0
- package/dist_ts/features/feature.abstract.d.ts +118 -0
- package/dist_ts/features/feature.abstract.js +172 -0
- package/dist_ts/features/feature.camera.d.ts +95 -0
- package/dist_ts/features/feature.camera.js +162 -0
- package/dist_ts/features/feature.climate.d.ts +174 -0
- package/dist_ts/features/feature.climate.js +328 -0
- package/dist_ts/features/feature.cover.d.ts +121 -0
- package/dist_ts/features/feature.cover.js +217 -0
- package/dist_ts/features/feature.fan.d.ts +127 -0
- package/dist_ts/features/feature.fan.js +235 -0
- package/dist_ts/features/feature.light.d.ts +156 -0
- package/dist_ts/features/feature.light.js +296 -0
- package/dist_ts/features/feature.lock.d.ts +103 -0
- package/dist_ts/features/feature.lock.js +170 -0
- package/dist_ts/features/feature.playback.d.ts +98 -0
- package/dist_ts/features/feature.playback.js +191 -0
- package/dist_ts/features/feature.power.d.ts +79 -0
- package/dist_ts/features/feature.power.js +173 -0
- package/dist_ts/features/feature.print.d.ts +78 -0
- package/dist_ts/features/feature.print.js +226 -0
- package/dist_ts/features/feature.scan.d.ts +79 -0
- package/dist_ts/features/feature.scan.js +315 -0
- package/dist_ts/features/feature.sensor.d.ts +95 -0
- package/dist_ts/features/feature.sensor.js +147 -0
- package/dist_ts/features/feature.snmp.d.ts +88 -0
- package/dist_ts/features/feature.snmp.js +175 -0
- package/dist_ts/features/feature.switch.d.ts +75 -0
- package/dist_ts/features/feature.switch.js +126 -0
- package/dist_ts/features/feature.volume.d.ts +104 -0
- package/dist_ts/features/feature.volume.js +186 -0
- package/dist_ts/features/index.d.ts +19 -0
- package/dist_ts/features/index.js +23 -0
- package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
- package/dist_ts/helpers/helpers.iprange.js +151 -0
- package/dist_ts/helpers/helpers.retry.d.ts +25 -0
- package/dist_ts/helpers/helpers.retry.js +69 -0
- package/dist_ts/index.d.ts +15 -0
- package/dist_ts/index.js +40 -0
- package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
- package/dist_ts/interfaces/feature.interfaces.js +6 -0
- package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
- package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
- package/dist_ts/interfaces/index.d.ts +330 -0
- package/dist_ts/interfaces/index.js +16 -0
- package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
- package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
- package/dist_ts/paths.d.ts +1 -0
- package/dist_ts/paths.js +3 -0
- package/dist_ts/plugins.d.ts +23 -0
- package/dist_ts/plugins.js +30 -0
- package/dist_ts/protocols/index.d.ts +12 -0
- package/dist_ts/protocols/index.js +21 -0
- package/dist_ts/protocols/protocol.escl.d.ts +58 -0
- package/dist_ts/protocols/protocol.escl.js +364 -0
- package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
- package/dist_ts/protocols/protocol.homeassistant.js +611 -0
- package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
- package/dist_ts/protocols/protocol.ipp.js +284 -0
- package/dist_ts/protocols/protocol.nut.d.ts +160 -0
- package/dist_ts/protocols/protocol.nut.js +364 -0
- package/dist_ts/protocols/protocol.sane.d.ts +104 -0
- package/dist_ts/protocols/protocol.sane.js +597 -0
- package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
- package/dist_ts/protocols/protocol.snmp.js +333 -0
- package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
- package/dist_ts/protocols/protocol.upnp.js +442 -0
- package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
- package/dist_ts/protocols/protocol.upssnmp.js +263 -0
- package/npmextra.json +24 -0
- package/package.json +39 -0
- package/readme.hints.md +115 -0
- package/readme.md +624 -0
- package/test/test.ts +261 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/device/device.classes.device.ts +454 -0
- package/ts/devicemanager.classes.devicemanager.ts +1219 -0
- package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
- package/ts/discovery/discovery.classes.mdns.ts +347 -0
- package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
- package/ts/discovery/discovery.classes.ssdp.ts +357 -0
- package/ts/factories/index.ts +696 -0
- package/ts/features/feature.abstract.ts +251 -0
- package/ts/features/feature.camera.ts +214 -0
- package/ts/features/feature.climate.ts +407 -0
- package/ts/features/feature.cover.ts +278 -0
- package/ts/features/feature.fan.ts +296 -0
- package/ts/features/feature.light.ts +369 -0
- package/ts/features/feature.lock.ts +223 -0
- package/ts/features/feature.playback.ts +246 -0
- package/ts/features/feature.power.ts +231 -0
- package/ts/features/feature.print.ts +297 -0
- package/ts/features/feature.scan.ts +370 -0
- package/ts/features/feature.sensor.ts +202 -0
- package/ts/features/feature.snmp.ts +235 -0
- package/ts/features/feature.switch.ts +170 -0
- package/ts/features/feature.volume.ts +256 -0
- package/ts/features/index.ts +25 -0
- package/ts/helpers/helpers.iprange.ts +172 -0
- package/ts/helpers/helpers.retry.ts +100 -0
- package/ts/index.ts +165 -0
- package/ts/interfaces/feature.interfaces.ts +359 -0
- package/ts/interfaces/homeassistant.interfaces.ts +666 -0
- package/ts/interfaces/index.ts +421 -0
- package/ts/interfaces/smarthome.interfaces.ts +421 -0
- package/ts/paths.ts +5 -0
- package/ts/plugins.ts +41 -0
- package/ts/protocols/index.ts +59 -0
- package/ts/protocols/protocol.escl.ts +439 -0
- package/ts/protocols/protocol.homeassistant.ts +737 -0
- package/ts/protocols/protocol.ipp.ts +329 -0
- package/ts/protocols/protocol.nut.ts +471 -0
- package/ts/protocols/protocol.sane.ts +694 -0
- package/ts/protocols/protocol.snmp.ts +439 -0
- package/ts/protocols/protocol.upnp.ts +627 -0
- package/ts/protocols/protocol.upssnmp.ts +377 -0
- package/tsconfig.json +12 -0
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Universal Device class
|
|
3
|
+
* A device is a network endpoint that can have multiple features (capabilities)
|
|
4
|
+
*/
|
|
5
|
+
import * as plugins from '../plugins.js';
|
|
6
|
+
import { Feature } from '../features/feature.abstract.js';
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Universal Device Class
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Universal Device - represents any network device with composable features
|
|
12
|
+
*
|
|
13
|
+
* Instead of having separate Scanner, Printer, Speaker classes, a Device can have
|
|
14
|
+
* any combination of features (scan, print, playback, volume, etc.)
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* // A multifunction printer/scanner
|
|
19
|
+
* const mfp = new UniversalDevice('192.168.1.100', 80);
|
|
20
|
+
* mfp.addFeature(new ScanFeature(mfp, 80));
|
|
21
|
+
* mfp.addFeature(new PrintFeature(mfp, 631));
|
|
22
|
+
*
|
|
23
|
+
* // Check capabilities
|
|
24
|
+
* if (mfp.hasFeature('scan') && mfp.hasFeature('print')) {
|
|
25
|
+
* const scanFeature = mfp.getFeature<ScanFeature>('scan');
|
|
26
|
+
* await scanFeature.scan({ format: 'pdf' });
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export class UniversalDevice extends plugins.events.EventEmitter {
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Properties
|
|
33
|
+
// ============================================================================
|
|
34
|
+
/**
|
|
35
|
+
* Unique device identifier
|
|
36
|
+
* Format: {address}:{port} or custom ID from discovery
|
|
37
|
+
*/
|
|
38
|
+
id;
|
|
39
|
+
/**
|
|
40
|
+
* Human-readable device name
|
|
41
|
+
*/
|
|
42
|
+
name;
|
|
43
|
+
/**
|
|
44
|
+
* Device network address (IP or hostname)
|
|
45
|
+
*/
|
|
46
|
+
address;
|
|
47
|
+
/**
|
|
48
|
+
* Primary device port
|
|
49
|
+
*/
|
|
50
|
+
port;
|
|
51
|
+
/**
|
|
52
|
+
* Device manufacturer
|
|
53
|
+
*/
|
|
54
|
+
manufacturer;
|
|
55
|
+
/**
|
|
56
|
+
* Device model
|
|
57
|
+
*/
|
|
58
|
+
model;
|
|
59
|
+
/**
|
|
60
|
+
* Device serial number
|
|
61
|
+
*/
|
|
62
|
+
serialNumber;
|
|
63
|
+
/**
|
|
64
|
+
* Device firmware version
|
|
65
|
+
*/
|
|
66
|
+
firmwareVersion;
|
|
67
|
+
/**
|
|
68
|
+
* Current device status
|
|
69
|
+
*/
|
|
70
|
+
_status = 'unknown';
|
|
71
|
+
/**
|
|
72
|
+
* Map of features by type
|
|
73
|
+
*/
|
|
74
|
+
_features = new Map();
|
|
75
|
+
/**
|
|
76
|
+
* Retry options for features
|
|
77
|
+
*/
|
|
78
|
+
_retryOptions;
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// Constructor
|
|
81
|
+
// ============================================================================
|
|
82
|
+
constructor(address, port, options) {
|
|
83
|
+
super();
|
|
84
|
+
this.address = address;
|
|
85
|
+
this.port = port;
|
|
86
|
+
this.id = `${address}:${port}`;
|
|
87
|
+
this.name = options?.name ?? `Device at ${address}`;
|
|
88
|
+
this.manufacturer = options?.manufacturer;
|
|
89
|
+
this.model = options?.model;
|
|
90
|
+
this.serialNumber = options?.serialNumber;
|
|
91
|
+
this.firmwareVersion = options?.firmwareVersion;
|
|
92
|
+
this._retryOptions = options?.retryOptions ?? {};
|
|
93
|
+
}
|
|
94
|
+
// ============================================================================
|
|
95
|
+
// Status Management
|
|
96
|
+
// ============================================================================
|
|
97
|
+
/**
|
|
98
|
+
* Get current device status
|
|
99
|
+
*/
|
|
100
|
+
get status() {
|
|
101
|
+
return this._status;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Set device status
|
|
105
|
+
*/
|
|
106
|
+
set status(value) {
|
|
107
|
+
if (this._status !== value) {
|
|
108
|
+
const oldStatus = this._status;
|
|
109
|
+
this._status = value;
|
|
110
|
+
this.emit('status:changed', { oldStatus, newStatus: value });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Check if device is online
|
|
115
|
+
*/
|
|
116
|
+
get isOnline() {
|
|
117
|
+
return this._status === 'online';
|
|
118
|
+
}
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// Feature Management
|
|
121
|
+
// ============================================================================
|
|
122
|
+
/**
|
|
123
|
+
* Add a feature to the device
|
|
124
|
+
*/
|
|
125
|
+
addFeature(feature) {
|
|
126
|
+
if (this._features.has(feature.type)) {
|
|
127
|
+
throw new Error(`Feature '${feature.type}' already exists on device ${this.id}`);
|
|
128
|
+
}
|
|
129
|
+
this._features.set(feature.type, feature);
|
|
130
|
+
// Forward feature events
|
|
131
|
+
feature.on('connected', () => this.emit('feature:connected', feature.type));
|
|
132
|
+
feature.on('disconnected', () => this.emit('feature:disconnected', feature.type));
|
|
133
|
+
feature.on('error', (error) => this.emit('feature:error', { type: feature.type, error }));
|
|
134
|
+
feature.on('state:changed', (states) => this.emit('feature:state:changed', { type: feature.type, ...states }));
|
|
135
|
+
this.emit('feature:added', feature);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Remove a feature from the device
|
|
139
|
+
*/
|
|
140
|
+
async removeFeature(type) {
|
|
141
|
+
const feature = this._features.get(type);
|
|
142
|
+
if (!feature) {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
// Disconnect the feature first
|
|
146
|
+
try {
|
|
147
|
+
await feature.disconnect();
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
// Ignore disconnect errors
|
|
151
|
+
}
|
|
152
|
+
this._features.delete(type);
|
|
153
|
+
this.emit('feature:removed', type);
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Check if device has a specific feature
|
|
158
|
+
*/
|
|
159
|
+
hasFeature(type) {
|
|
160
|
+
return this._features.has(type);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Check if device has all specified features
|
|
164
|
+
*/
|
|
165
|
+
hasFeatures(types) {
|
|
166
|
+
return types.every((type) => this._features.has(type));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Check if device has any of the specified features
|
|
170
|
+
*/
|
|
171
|
+
hasAnyFeature(types) {
|
|
172
|
+
return types.some((type) => this._features.has(type));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Get a feature by type (returns undefined if not available)
|
|
176
|
+
*/
|
|
177
|
+
getFeature(type) {
|
|
178
|
+
return this._features.get(type);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Select a feature by type (throws if not available).
|
|
182
|
+
* Use this when you expect the device to have this feature and want fail-fast behavior.
|
|
183
|
+
*
|
|
184
|
+
* @param type The feature type to select
|
|
185
|
+
* @returns The feature instance
|
|
186
|
+
* @throws Error if the device does not have this feature
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```typescript
|
|
190
|
+
* const scanFeature = device.selectFeature<ScanFeature>('scan');
|
|
191
|
+
* await scanFeature.connect();
|
|
192
|
+
* const result = await scanFeature.scan({ source: 'flatbed' });
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
selectFeature(type) {
|
|
196
|
+
const feature = this._features.get(type);
|
|
197
|
+
if (!feature) {
|
|
198
|
+
throw new Error(`Device '${this.name}' does not have feature '${type}'`);
|
|
199
|
+
}
|
|
200
|
+
return feature;
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get all features
|
|
204
|
+
*/
|
|
205
|
+
getFeatures() {
|
|
206
|
+
return Array.from(this._features.values());
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Get all feature types
|
|
210
|
+
*/
|
|
211
|
+
getFeatureTypes() {
|
|
212
|
+
return Array.from(this._features.keys());
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get feature count
|
|
216
|
+
*/
|
|
217
|
+
get featureCount() {
|
|
218
|
+
return this._features.size;
|
|
219
|
+
}
|
|
220
|
+
// ============================================================================
|
|
221
|
+
// Connection Management
|
|
222
|
+
// ============================================================================
|
|
223
|
+
/**
|
|
224
|
+
* Connect all features
|
|
225
|
+
*/
|
|
226
|
+
async connect() {
|
|
227
|
+
const features = this.getFeatures();
|
|
228
|
+
const results = await Promise.allSettled(features.map((f) => f.connect()));
|
|
229
|
+
// Check if any connected successfully
|
|
230
|
+
const anyConnected = results.some((r) => r.status === 'fulfilled');
|
|
231
|
+
if (anyConnected) {
|
|
232
|
+
this.status = 'online';
|
|
233
|
+
}
|
|
234
|
+
else if (results.length > 0) {
|
|
235
|
+
// All failed
|
|
236
|
+
this.status = 'error';
|
|
237
|
+
const errors = results
|
|
238
|
+
.filter((r) => r.status === 'rejected')
|
|
239
|
+
.map((r) => r.reason);
|
|
240
|
+
throw new AggregateError(errors, 'Failed to connect any features');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Connect a specific feature
|
|
245
|
+
*/
|
|
246
|
+
async connectFeature(type) {
|
|
247
|
+
const feature = this._features.get(type);
|
|
248
|
+
if (!feature) {
|
|
249
|
+
throw new Error(`Feature '${type}' not found on device ${this.id}`);
|
|
250
|
+
}
|
|
251
|
+
await feature.connect();
|
|
252
|
+
// Update device status if this is the first connected feature
|
|
253
|
+
if (this._status !== 'online') {
|
|
254
|
+
this.status = 'online';
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Disconnect all features
|
|
259
|
+
*/
|
|
260
|
+
async disconnect() {
|
|
261
|
+
const features = this.getFeatures();
|
|
262
|
+
await Promise.allSettled(features.map((f) => f.disconnect()));
|
|
263
|
+
this.status = 'offline';
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Disconnect a specific feature
|
|
267
|
+
*/
|
|
268
|
+
async disconnectFeature(type) {
|
|
269
|
+
const feature = this._features.get(type);
|
|
270
|
+
if (feature) {
|
|
271
|
+
await feature.disconnect();
|
|
272
|
+
}
|
|
273
|
+
// Update device status if all features are disconnected
|
|
274
|
+
const anyConnected = this.getFeatures().some((f) => f.isConnected);
|
|
275
|
+
if (!anyConnected) {
|
|
276
|
+
this.status = 'offline';
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// ============================================================================
|
|
280
|
+
// Serialization
|
|
281
|
+
// ============================================================================
|
|
282
|
+
/**
|
|
283
|
+
* Get device reference for features
|
|
284
|
+
*/
|
|
285
|
+
getDeviceReference() {
|
|
286
|
+
return {
|
|
287
|
+
id: this.id,
|
|
288
|
+
name: this.name,
|
|
289
|
+
address: this.address,
|
|
290
|
+
port: this.port,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Get serializable device info
|
|
295
|
+
*/
|
|
296
|
+
getDeviceInfo() {
|
|
297
|
+
return {
|
|
298
|
+
id: this.id,
|
|
299
|
+
name: this.name,
|
|
300
|
+
address: this.address,
|
|
301
|
+
port: this.port,
|
|
302
|
+
status: this._status,
|
|
303
|
+
manufacturer: this.manufacturer,
|
|
304
|
+
model: this.model,
|
|
305
|
+
serialNumber: this.serialNumber,
|
|
306
|
+
firmwareVersion: this.firmwareVersion,
|
|
307
|
+
features: this.getFeatures().map((f) => f.getFeatureInfo()),
|
|
308
|
+
featureTypes: this.getFeatureTypes(),
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Get retry options for features
|
|
313
|
+
*/
|
|
314
|
+
get retryOptions() {
|
|
315
|
+
return this._retryOptions;
|
|
316
|
+
}
|
|
317
|
+
// ============================================================================
|
|
318
|
+
// Static Factory Methods
|
|
319
|
+
// ============================================================================
|
|
320
|
+
/**
|
|
321
|
+
* Create a device from discovered features
|
|
322
|
+
*/
|
|
323
|
+
static fromDiscovery(id, name, address, port, discoveredFeatures, options) {
|
|
324
|
+
const device = new UniversalDevice(address, port, {
|
|
325
|
+
...options,
|
|
326
|
+
name,
|
|
327
|
+
});
|
|
328
|
+
// Override the generated ID with the discovery ID
|
|
329
|
+
device.id = id;
|
|
330
|
+
// Features will be added by the DeviceManager after creation
|
|
331
|
+
// This is because feature instances need protocol-specific initialization
|
|
332
|
+
return device;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
// ============================================================================
|
|
336
|
+
// Type Guards
|
|
337
|
+
// ============================================================================
|
|
338
|
+
/**
|
|
339
|
+
* Check if a device has a specific feature (type guard)
|
|
340
|
+
*/
|
|
341
|
+
export function deviceHasFeature(device, type) {
|
|
342
|
+
return device.hasFeature(type);
|
|
343
|
+
}
|
|
344
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGV2aWNlLmNsYXNzZXMuZGV2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvZGV2aWNlL2RldmljZS5jbGFzc2VzLmRldmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7O0dBR0c7QUFFSCxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQU96QyxPQUFPLEVBQUUsT0FBTyxFQUF5QixNQUFNLGlDQUFpQyxDQUFDO0FBbUNqRiwrRUFBK0U7QUFDL0UseUJBQXlCO0FBQ3pCLCtFQUErRTtBQUUvRTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW1CRztBQUNILE1BQU0sT0FBTyxlQUFnQixTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQUM5RCwrRUFBK0U7SUFDL0UsYUFBYTtJQUNiLCtFQUErRTtJQUUvRTs7O09BR0c7SUFDYSxFQUFFLENBQVM7SUFFM0I7O09BRUc7SUFDSSxJQUFJLENBQVM7SUFFcEI7O09BRUc7SUFDYSxPQUFPLENBQVM7SUFFaEM7O09BRUc7SUFDYSxJQUFJLENBQVM7SUFFN0I7O09BRUc7SUFDSSxZQUFZLENBQVU7SUFFN0I7O09BRUc7SUFDSSxLQUFLLENBQVU7SUFFdEI7O09BRUc7SUFDSSxZQUFZLENBQVU7SUFFN0I7O09BRUc7SUFDSSxlQUFlLENBQVU7SUFFaEM7O09BRUc7SUFDTyxPQUFPLEdBQWtCLFNBQVMsQ0FBQztJQUU3Qzs7T0FFRztJQUNPLFNBQVMsR0FBK0IsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUU1RDs7T0FFRztJQUNPLGFBQWEsQ0FBZ0I7SUFFdkMsK0VBQStFO0lBQy9FLGNBQWM7SUFDZCwrRUFBK0U7SUFFL0UsWUFDRSxPQUFlLEVBQ2YsSUFBWSxFQUNaLE9BQThCO1FBRTlCLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUM7UUFDakIsSUFBSSxDQUFD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
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device Manager
|
|
3
|
+
* Unified device discovery and management using UniversalDevice with Features
|
|
4
|
+
*/
|
|
5
|
+
import * as plugins from './plugins.js';
|
|
6
|
+
import { MdnsDiscovery, SERVICE_TYPES } from './discovery/discovery.classes.mdns.js';
|
|
7
|
+
import { NetworkScanner } from './discovery/discovery.classes.networkscanner.js';
|
|
8
|
+
import { SsdpDiscovery, SSDP_SERVICE_TYPES } from './discovery/discovery.classes.ssdp.js';
|
|
9
|
+
import { UniversalDevice } from './device/device.classes.device.js';
|
|
10
|
+
import { ScanFeature, PrintFeature, PlaybackFeature, VolumeFeature, PowerFeature, SnmpFeature } from './features/index.js';
|
|
11
|
+
import type { Feature } from './features/index.js';
|
|
12
|
+
import { createScanner, createPrinter, createSnmpDevice, createUpsDevice, createSpeaker, createDlnaRenderer } from './factories/index.js';
|
|
13
|
+
import type { IDeviceManagerOptions, INetworkScanOptions, TFeatureType, IDeviceSelector } from './interfaces/index.js';
|
|
14
|
+
/**
|
|
15
|
+
* Main Device Manager class
|
|
16
|
+
* Discovers and manages network devices using the UniversalDevice architecture
|
|
17
|
+
*
|
|
18
|
+
* Devices are deduplicated by IP address - if the same device is discovered
|
|
19
|
+
* via multiple methods (mDNS, SSDP, IP scan), features are merged into a
|
|
20
|
+
* single UniversalDevice instance.
|
|
21
|
+
*/
|
|
22
|
+
export declare class DeviceManager extends plugins.events.EventEmitter {
|
|
23
|
+
private mdnsDiscovery;
|
|
24
|
+
private ssdpDiscovery;
|
|
25
|
+
private _networkScanner;
|
|
26
|
+
private devicesByIp;
|
|
27
|
+
private nameSourceByIp;
|
|
28
|
+
private options;
|
|
29
|
+
private retryOptions;
|
|
30
|
+
constructor(options?: IDeviceManagerOptions);
|
|
31
|
+
/**
|
|
32
|
+
* Register or merge a device by IP address
|
|
33
|
+
* Returns the device (existing or new) and whether it's newly created
|
|
34
|
+
*/
|
|
35
|
+
private registerDevice;
|
|
36
|
+
private setupDiscoveryEvents;
|
|
37
|
+
private setupSsdpDiscoveryEvents;
|
|
38
|
+
private handleMdnsDeviceFound;
|
|
39
|
+
private handleSsdpDeviceFound;
|
|
40
|
+
private handleDeviceLost;
|
|
41
|
+
private parseScanFormats;
|
|
42
|
+
private parseScanResolutions;
|
|
43
|
+
private parseScanColorModes;
|
|
44
|
+
private parseScanSources;
|
|
45
|
+
startDiscovery(): Promise<void>;
|
|
46
|
+
stopDiscovery(): Promise<void>;
|
|
47
|
+
get isDiscovering(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Get devices matching the selector criteria.
|
|
50
|
+
* Returns all devices if no selector provided, or devices matching all criteria.
|
|
51
|
+
* @param selector Optional criteria to filter devices
|
|
52
|
+
* @returns Array of matching devices (empty if no matches)
|
|
53
|
+
*/
|
|
54
|
+
getDevices(selector?: IDeviceSelector): UniversalDevice[];
|
|
55
|
+
/**
|
|
56
|
+
* Select exactly ONE device matching the criteria.
|
|
57
|
+
* Use this when you expect a specific device and want fail-fast behavior.
|
|
58
|
+
* @param selector Criteria to match the device
|
|
59
|
+
* @returns The matching device
|
|
60
|
+
* @throws Error if no device matches the selector
|
|
61
|
+
*/
|
|
62
|
+
selectDevice(selector: IDeviceSelector): UniversalDevice;
|
|
63
|
+
/**
|
|
64
|
+
* Get device by ID
|
|
65
|
+
* @deprecated Use getDevices({ id }) or selectDevice({ id }) instead
|
|
66
|
+
*/
|
|
67
|
+
getDevice(id: string): UniversalDevice | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Get device by address
|
|
70
|
+
* @deprecated Use getDevices({ address }) or selectDevice({ address }) instead
|
|
71
|
+
*/
|
|
72
|
+
getDeviceByAddress(address: string): UniversalDevice | undefined;
|
|
73
|
+
/**
|
|
74
|
+
* Check if a device matches the selector criteria
|
|
75
|
+
*/
|
|
76
|
+
private matchesSelector;
|
|
77
|
+
/**
|
|
78
|
+
* Get all devices that have a specific feature
|
|
79
|
+
*/
|
|
80
|
+
getDevicesWithFeature(featureType: TFeatureType): UniversalDevice[];
|
|
81
|
+
/**
|
|
82
|
+
* Get all devices that have ALL specified features
|
|
83
|
+
*/
|
|
84
|
+
getDevicesWithFeatures(featureTypes: TFeatureType[]): UniversalDevice[];
|
|
85
|
+
/**
|
|
86
|
+
* Get all devices that have ANY of the specified features
|
|
87
|
+
*/
|
|
88
|
+
getDevicesWithAnyFeature(featureTypes: TFeatureType[]): UniversalDevice[];
|
|
89
|
+
/**
|
|
90
|
+
* Get all scanner devices
|
|
91
|
+
*/
|
|
92
|
+
getScanners(): UniversalDevice[];
|
|
93
|
+
/**
|
|
94
|
+
* Get all printer devices
|
|
95
|
+
*/
|
|
96
|
+
getPrinters(): UniversalDevice[];
|
|
97
|
+
/**
|
|
98
|
+
* Get all speaker devices (playback feature)
|
|
99
|
+
*/
|
|
100
|
+
getSpeakers(): UniversalDevice[];
|
|
101
|
+
/**
|
|
102
|
+
* Get all UPS/power devices
|
|
103
|
+
*/
|
|
104
|
+
getUpsDevices(): UniversalDevice[];
|
|
105
|
+
/**
|
|
106
|
+
* Get all SNMP devices
|
|
107
|
+
*/
|
|
108
|
+
getSnmpDevices(): UniversalDevice[];
|
|
109
|
+
/**
|
|
110
|
+
* Add a device
|
|
111
|
+
*/
|
|
112
|
+
addDevice(device: UniversalDevice): void;
|
|
113
|
+
/**
|
|
114
|
+
* Add a scanner manually
|
|
115
|
+
*/
|
|
116
|
+
addScanner(address: string, port: number, protocol?: 'escl' | 'sane', name?: string): Promise<UniversalDevice>;
|
|
117
|
+
/**
|
|
118
|
+
* Add a printer manually
|
|
119
|
+
*/
|
|
120
|
+
addPrinter(address: string, port?: number, name?: string, ippPath?: string): Promise<UniversalDevice>;
|
|
121
|
+
/**
|
|
122
|
+
* Add an SNMP device manually
|
|
123
|
+
*/
|
|
124
|
+
addSnmpDevice(address: string, port?: number, options?: {
|
|
125
|
+
name?: string;
|
|
126
|
+
community?: string;
|
|
127
|
+
}): Promise<UniversalDevice>;
|
|
128
|
+
/**
|
|
129
|
+
* Add a UPS device manually
|
|
130
|
+
*/
|
|
131
|
+
addUpsDevice(address: string, protocol: 'nut' | 'snmp', options?: {
|
|
132
|
+
name?: string;
|
|
133
|
+
port?: number;
|
|
134
|
+
upsName?: string;
|
|
135
|
+
community?: string;
|
|
136
|
+
}): Promise<UniversalDevice>;
|
|
137
|
+
/**
|
|
138
|
+
* Add a speaker manually
|
|
139
|
+
*/
|
|
140
|
+
addSpeaker(address: string, protocol: 'sonos' | 'airplay' | 'chromecast' | 'dlna', options?: {
|
|
141
|
+
name?: string;
|
|
142
|
+
port?: number;
|
|
143
|
+
}): Promise<UniversalDevice>;
|
|
144
|
+
/**
|
|
145
|
+
* Get a feature from a device
|
|
146
|
+
*/
|
|
147
|
+
getFeature<T extends Feature>(deviceId: string, featureType: TFeatureType): T | undefined;
|
|
148
|
+
/**
|
|
149
|
+
* Add a feature to a device
|
|
150
|
+
*/
|
|
151
|
+
addFeature(deviceId: string, feature: Feature): boolean;
|
|
152
|
+
/**
|
|
153
|
+
* Remove a feature from a device
|
|
154
|
+
*/
|
|
155
|
+
removeFeature(deviceId: string, featureType: TFeatureType): Promise<boolean>;
|
|
156
|
+
get networkScanner(): NetworkScanner;
|
|
157
|
+
private setupNetworkScannerEvents;
|
|
158
|
+
scanNetwork(options: INetworkScanOptions): Promise<UniversalDevice[]>;
|
|
159
|
+
/**
|
|
160
|
+
* Discover scanners in a subnet and add them to the manager.
|
|
161
|
+
* Convenience method that focuses discovery on scanner protocols only (eSCL, SANE).
|
|
162
|
+
*
|
|
163
|
+
* @param subnet CIDR notation subnet (e.g., '192.168.1.0/24')
|
|
164
|
+
* @param options Optional discovery settings
|
|
165
|
+
* @returns Array of discovered scanner devices
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const scanners = await manager.discoverScanners('192.168.190.0/24');
|
|
170
|
+
* for (const scanner of scanners) {
|
|
171
|
+
* console.log(`Found: ${scanner.name} at ${scanner.address}`);
|
|
172
|
+
* }
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
discoverScanners(subnet: string, options?: {
|
|
176
|
+
timeout?: number;
|
|
177
|
+
concurrency?: number;
|
|
178
|
+
}): Promise<UniversalDevice[]>;
|
|
179
|
+
/**
|
|
180
|
+
* Discover printers in a subnet and add them to the manager.
|
|
181
|
+
* Convenience method that focuses discovery on printer protocols only (IPP).
|
|
182
|
+
*
|
|
183
|
+
* @param subnet CIDR notation subnet (e.g., '192.168.1.0/24')
|
|
184
|
+
* @param options Optional discovery settings
|
|
185
|
+
* @returns Array of discovered printer devices
|
|
186
|
+
*/
|
|
187
|
+
discoverPrinters(subnet: string, options?: {
|
|
188
|
+
timeout?: number;
|
|
189
|
+
concurrency?: number;
|
|
190
|
+
}): Promise<UniversalDevice[]>;
|
|
191
|
+
cancelNetworkScan(): Promise<void>;
|
|
192
|
+
get isNetworkScanning(): boolean;
|
|
193
|
+
/**
|
|
194
|
+
* Remove a device by ID
|
|
195
|
+
*/
|
|
196
|
+
removeDevice(id: string): Promise<boolean>;
|
|
197
|
+
/**
|
|
198
|
+
* Remove a device by address
|
|
199
|
+
*/
|
|
200
|
+
removeDeviceByAddress(address: string): Promise<boolean>;
|
|
201
|
+
/**
|
|
202
|
+
* Disconnect all devices
|
|
203
|
+
*/
|
|
204
|
+
disconnectAll(): Promise<void>;
|
|
205
|
+
/**
|
|
206
|
+
* Stop discovery and disconnect all devices
|
|
207
|
+
*/
|
|
208
|
+
shutdown(): Promise<void>;
|
|
209
|
+
}
|
|
210
|
+
export { MdnsDiscovery, NetworkScanner, SsdpDiscovery, SERVICE_TYPES, SSDP_SERVICE_TYPES, UniversalDevice, ScanFeature, PrintFeature, PlaybackFeature, VolumeFeature, PowerFeature, SnmpFeature, createScanner, createPrinter, createSnmpDevice, createUpsDevice, createSpeaker, createDlnaRenderer, };
|