@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.
Files changed (137) hide show
  1. package/.gitea/workflows/default_nottags.yaml +66 -0
  2. package/.gitea/workflows/default_tags.yaml +124 -0
  3. package/.vscode/launch.json +11 -0
  4. package/.vscode/settings.json +26 -0
  5. package/changelog.md +91 -0
  6. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  7. package/dist_ts/00_commitinfo_data.js +9 -0
  8. package/dist_ts/device/device.classes.device.d.ts +205 -0
  9. package/dist_ts/device/device.classes.device.js +344 -0
  10. package/dist_ts/devicemanager.classes.devicemanager.d.ts +210 -0
  11. package/dist_ts/devicemanager.classes.devicemanager.js +835 -0
  12. package/dist_ts/discovery/discovery.classes.homeassistant.d.ts +101 -0
  13. package/dist_ts/discovery/discovery.classes.homeassistant.js +313 -0
  14. package/dist_ts/discovery/discovery.classes.mdns.d.ts +90 -0
  15. package/dist_ts/discovery/discovery.classes.mdns.js +291 -0
  16. package/dist_ts/discovery/discovery.classes.networkscanner.d.ts +64 -0
  17. package/dist_ts/discovery/discovery.classes.networkscanner.js +535 -0
  18. package/dist_ts/discovery/discovery.classes.ssdp.d.ts +112 -0
  19. package/dist_ts/discovery/discovery.classes.ssdp.js +255 -0
  20. package/dist_ts/factories/index.d.ts +190 -0
  21. package/dist_ts/factories/index.js +350 -0
  22. package/dist_ts/features/feature.abstract.d.ts +118 -0
  23. package/dist_ts/features/feature.abstract.js +172 -0
  24. package/dist_ts/features/feature.camera.d.ts +95 -0
  25. package/dist_ts/features/feature.camera.js +162 -0
  26. package/dist_ts/features/feature.climate.d.ts +174 -0
  27. package/dist_ts/features/feature.climate.js +328 -0
  28. package/dist_ts/features/feature.cover.d.ts +121 -0
  29. package/dist_ts/features/feature.cover.js +217 -0
  30. package/dist_ts/features/feature.fan.d.ts +127 -0
  31. package/dist_ts/features/feature.fan.js +235 -0
  32. package/dist_ts/features/feature.light.d.ts +156 -0
  33. package/dist_ts/features/feature.light.js +296 -0
  34. package/dist_ts/features/feature.lock.d.ts +103 -0
  35. package/dist_ts/features/feature.lock.js +170 -0
  36. package/dist_ts/features/feature.playback.d.ts +98 -0
  37. package/dist_ts/features/feature.playback.js +191 -0
  38. package/dist_ts/features/feature.power.d.ts +79 -0
  39. package/dist_ts/features/feature.power.js +173 -0
  40. package/dist_ts/features/feature.print.d.ts +78 -0
  41. package/dist_ts/features/feature.print.js +226 -0
  42. package/dist_ts/features/feature.scan.d.ts +79 -0
  43. package/dist_ts/features/feature.scan.js +315 -0
  44. package/dist_ts/features/feature.sensor.d.ts +95 -0
  45. package/dist_ts/features/feature.sensor.js +147 -0
  46. package/dist_ts/features/feature.snmp.d.ts +88 -0
  47. package/dist_ts/features/feature.snmp.js +175 -0
  48. package/dist_ts/features/feature.switch.d.ts +75 -0
  49. package/dist_ts/features/feature.switch.js +126 -0
  50. package/dist_ts/features/feature.volume.d.ts +104 -0
  51. package/dist_ts/features/feature.volume.js +186 -0
  52. package/dist_ts/features/index.d.ts +19 -0
  53. package/dist_ts/features/index.js +23 -0
  54. package/dist_ts/helpers/helpers.iprange.d.ts +35 -0
  55. package/dist_ts/helpers/helpers.iprange.js +151 -0
  56. package/dist_ts/helpers/helpers.retry.d.ts +25 -0
  57. package/dist_ts/helpers/helpers.retry.js +69 -0
  58. package/dist_ts/index.d.ts +15 -0
  59. package/dist_ts/index.js +40 -0
  60. package/dist_ts/interfaces/feature.interfaces.d.ts +255 -0
  61. package/dist_ts/interfaces/feature.interfaces.js +6 -0
  62. package/dist_ts/interfaces/homeassistant.interfaces.d.ts +550 -0
  63. package/dist_ts/interfaces/homeassistant.interfaces.js +111 -0
  64. package/dist_ts/interfaces/index.d.ts +330 -0
  65. package/dist_ts/interfaces/index.js +16 -0
  66. package/dist_ts/interfaces/smarthome.interfaces.d.ts +282 -0
  67. package/dist_ts/interfaces/smarthome.interfaces.js +7 -0
  68. package/dist_ts/paths.d.ts +1 -0
  69. package/dist_ts/paths.js +3 -0
  70. package/dist_ts/plugins.d.ts +23 -0
  71. package/dist_ts/plugins.js +30 -0
  72. package/dist_ts/protocols/index.d.ts +12 -0
  73. package/dist_ts/protocols/index.js +21 -0
  74. package/dist_ts/protocols/protocol.escl.d.ts +58 -0
  75. package/dist_ts/protocols/protocol.escl.js +364 -0
  76. package/dist_ts/protocols/protocol.homeassistant.d.ts +248 -0
  77. package/dist_ts/protocols/protocol.homeassistant.js +611 -0
  78. package/dist_ts/protocols/protocol.ipp.d.ts +45 -0
  79. package/dist_ts/protocols/protocol.ipp.js +284 -0
  80. package/dist_ts/protocols/protocol.nut.d.ts +160 -0
  81. package/dist_ts/protocols/protocol.nut.js +364 -0
  82. package/dist_ts/protocols/protocol.sane.d.ts +104 -0
  83. package/dist_ts/protocols/protocol.sane.js +597 -0
  84. package/dist_ts/protocols/protocol.snmp.d.ts +133 -0
  85. package/dist_ts/protocols/protocol.snmp.js +333 -0
  86. package/dist_ts/protocols/protocol.upnp.d.ts +207 -0
  87. package/dist_ts/protocols/protocol.upnp.js +442 -0
  88. package/dist_ts/protocols/protocol.upssnmp.d.ts +160 -0
  89. package/dist_ts/protocols/protocol.upssnmp.js +263 -0
  90. package/npmextra.json +24 -0
  91. package/package.json +39 -0
  92. package/readme.hints.md +115 -0
  93. package/readme.md +624 -0
  94. package/test/test.ts +261 -0
  95. package/ts/00_commitinfo_data.ts +8 -0
  96. package/ts/device/device.classes.device.ts +454 -0
  97. package/ts/devicemanager.classes.devicemanager.ts +1219 -0
  98. package/ts/discovery/discovery.classes.homeassistant.ts +376 -0
  99. package/ts/discovery/discovery.classes.mdns.ts +347 -0
  100. package/ts/discovery/discovery.classes.networkscanner.ts +648 -0
  101. package/ts/discovery/discovery.classes.ssdp.ts +357 -0
  102. package/ts/factories/index.ts +696 -0
  103. package/ts/features/feature.abstract.ts +251 -0
  104. package/ts/features/feature.camera.ts +214 -0
  105. package/ts/features/feature.climate.ts +407 -0
  106. package/ts/features/feature.cover.ts +278 -0
  107. package/ts/features/feature.fan.ts +296 -0
  108. package/ts/features/feature.light.ts +369 -0
  109. package/ts/features/feature.lock.ts +223 -0
  110. package/ts/features/feature.playback.ts +246 -0
  111. package/ts/features/feature.power.ts +231 -0
  112. package/ts/features/feature.print.ts +297 -0
  113. package/ts/features/feature.scan.ts +370 -0
  114. package/ts/features/feature.sensor.ts +202 -0
  115. package/ts/features/feature.snmp.ts +235 -0
  116. package/ts/features/feature.switch.ts +170 -0
  117. package/ts/features/feature.volume.ts +256 -0
  118. package/ts/features/index.ts +25 -0
  119. package/ts/helpers/helpers.iprange.ts +172 -0
  120. package/ts/helpers/helpers.retry.ts +100 -0
  121. package/ts/index.ts +165 -0
  122. package/ts/interfaces/feature.interfaces.ts +359 -0
  123. package/ts/interfaces/homeassistant.interfaces.ts +666 -0
  124. package/ts/interfaces/index.ts +421 -0
  125. package/ts/interfaces/smarthome.interfaces.ts +421 -0
  126. package/ts/paths.ts +5 -0
  127. package/ts/plugins.ts +41 -0
  128. package/ts/protocols/index.ts +59 -0
  129. package/ts/protocols/protocol.escl.ts +439 -0
  130. package/ts/protocols/protocol.homeassistant.ts +737 -0
  131. package/ts/protocols/protocol.ipp.ts +329 -0
  132. package/ts/protocols/protocol.nut.ts +471 -0
  133. package/ts/protocols/protocol.sane.ts +694 -0
  134. package/ts/protocols/protocol.snmp.ts +439 -0
  135. package/ts/protocols/protocol.upnp.ts +627 -0
  136. package/ts/protocols/protocol.upssnmp.ts +377 -0
  137. 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, };