@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,101 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IHomeAssistantInstanceConfig, IHomeAssistantEntity, IHomeAssistantDiscoveredInstance, THomeAssistantDomain } from '../interfaces/homeassistant.interfaces.js';
3
+ import { HomeAssistantProtocol } from '../protocols/protocol.homeassistant.js';
4
+ /**
5
+ * mDNS service type for Home Assistant discovery
6
+ */
7
+ declare const HA_SERVICE_TYPE = "_home-assistant._tcp";
8
+ /**
9
+ * Home Assistant Discovery
10
+ * Discovers HA instances via mDNS and/or manual configuration,
11
+ * connects to them, and enumerates all entities
12
+ */
13
+ export declare class HomeAssistantDiscovery extends plugins.events.EventEmitter {
14
+ private bonjour;
15
+ private browser;
16
+ private discoveredInstances;
17
+ private connectedProtocols;
18
+ private entityCache;
19
+ private enabledDomains;
20
+ private isRunning;
21
+ constructor(options?: {
22
+ enabledDomains?: THomeAssistantDomain[];
23
+ });
24
+ /**
25
+ * Check if discovery is running
26
+ */
27
+ get running(): boolean;
28
+ /**
29
+ * Get all discovered HA instances
30
+ */
31
+ getInstances(): IHomeAssistantDiscoveredInstance[];
32
+ /**
33
+ * Get connected protocol for an instance
34
+ */
35
+ getProtocol(instanceId: string): HomeAssistantProtocol | undefined;
36
+ /**
37
+ * Get all connected protocols
38
+ */
39
+ getProtocols(): Map<string, HomeAssistantProtocol>;
40
+ /**
41
+ * Get all cached entities
42
+ */
43
+ getEntities(): IHomeAssistantEntity[];
44
+ /**
45
+ * Get entities by domain
46
+ */
47
+ getEntitiesByDomain(domain: THomeAssistantDomain): IHomeAssistantEntity[];
48
+ /**
49
+ * Get entities for a specific instance
50
+ */
51
+ getEntitiesForInstance(instanceId: string): IHomeAssistantEntity[];
52
+ /**
53
+ * Start mDNS discovery for Home Assistant instances
54
+ */
55
+ startMdnsDiscovery(): Promise<void>;
56
+ /**
57
+ * Stop mDNS discovery
58
+ */
59
+ stopMdnsDiscovery(): Promise<void>;
60
+ /**
61
+ * Add a manually configured HA instance
62
+ */
63
+ addInstance(config: IHomeAssistantInstanceConfig): Promise<HomeAssistantProtocol>;
64
+ /**
65
+ * Remove an HA instance
66
+ */
67
+ removeInstance(instanceId: string): Promise<void>;
68
+ /**
69
+ * Stop all and cleanup
70
+ */
71
+ stop(): Promise<void>;
72
+ /**
73
+ * Handle mDNS service found
74
+ */
75
+ private handleInstanceFound;
76
+ /**
77
+ * Handle mDNS service lost
78
+ */
79
+ private handleInstanceLost;
80
+ /**
81
+ * Set up event handlers for a protocol
82
+ */
83
+ private setupProtocolHandlers;
84
+ /**
85
+ * Check if entity domain is enabled
86
+ */
87
+ private isEnabledDomain;
88
+ /**
89
+ * Generate unique instance ID
90
+ */
91
+ private generateInstanceId;
92
+ /**
93
+ * Parse TXT records from mDNS service
94
+ */
95
+ private parseTxtRecords;
96
+ /**
97
+ * Probe if a host has Home Assistant running
98
+ */
99
+ static probe(host: string, port?: number, secure?: boolean, timeout?: number): Promise<boolean>;
100
+ }
101
+ export { HA_SERVICE_TYPE };
@@ -0,0 +1,313 @@
1
+ import * as plugins from '../plugins.js';
2
+ import { HomeAssistantProtocol } from '../protocols/protocol.homeassistant.js';
3
+ /**
4
+ * mDNS service type for Home Assistant discovery
5
+ */
6
+ const HA_SERVICE_TYPE = '_home-assistant._tcp';
7
+ /**
8
+ * Default domains to discover
9
+ */
10
+ const DEFAULT_DOMAINS = [
11
+ 'light',
12
+ 'switch',
13
+ 'sensor',
14
+ 'binary_sensor',
15
+ 'climate',
16
+ 'fan',
17
+ 'cover',
18
+ 'lock',
19
+ 'camera',
20
+ 'media_player',
21
+ ];
22
+ /**
23
+ * Home Assistant Discovery
24
+ * Discovers HA instances via mDNS and/or manual configuration,
25
+ * connects to them, and enumerates all entities
26
+ */
27
+ export class HomeAssistantDiscovery extends plugins.events.EventEmitter {
28
+ bonjour = null;
29
+ browser = null;
30
+ discoveredInstances = new Map();
31
+ connectedProtocols = new Map();
32
+ entityCache = new Map();
33
+ enabledDomains;
34
+ isRunning = false;
35
+ constructor(options) {
36
+ super();
37
+ this.enabledDomains = options?.enabledDomains || DEFAULT_DOMAINS;
38
+ }
39
+ /**
40
+ * Check if discovery is running
41
+ */
42
+ get running() {
43
+ return this.isRunning;
44
+ }
45
+ /**
46
+ * Get all discovered HA instances
47
+ */
48
+ getInstances() {
49
+ return Array.from(this.discoveredInstances.values());
50
+ }
51
+ /**
52
+ * Get connected protocol for an instance
53
+ */
54
+ getProtocol(instanceId) {
55
+ return this.connectedProtocols.get(instanceId);
56
+ }
57
+ /**
58
+ * Get all connected protocols
59
+ */
60
+ getProtocols() {
61
+ return this.connectedProtocols;
62
+ }
63
+ /**
64
+ * Get all cached entities
65
+ */
66
+ getEntities() {
67
+ return Array.from(this.entityCache.values());
68
+ }
69
+ /**
70
+ * Get entities by domain
71
+ */
72
+ getEntitiesByDomain(domain) {
73
+ return this.getEntities().filter((e) => e.entity_id.startsWith(`${domain}.`));
74
+ }
75
+ /**
76
+ * Get entities for a specific instance
77
+ */
78
+ getEntitiesForInstance(instanceId) {
79
+ const protocol = this.connectedProtocols.get(instanceId);
80
+ if (!protocol)
81
+ return [];
82
+ return Array.from(protocol.entities.values());
83
+ }
84
+ /**
85
+ * Start mDNS discovery for Home Assistant instances
86
+ */
87
+ async startMdnsDiscovery() {
88
+ if (this.isRunning) {
89
+ return;
90
+ }
91
+ this.bonjour = new plugins.bonjourService.Bonjour();
92
+ this.isRunning = true;
93
+ this.browser = this.bonjour.find({ type: HA_SERVICE_TYPE }, (service) => {
94
+ this.handleInstanceFound(service);
95
+ });
96
+ this.browser.on('down', (service) => {
97
+ this.handleInstanceLost(service);
98
+ });
99
+ }
100
+ /**
101
+ * Stop mDNS discovery
102
+ */
103
+ async stopMdnsDiscovery() {
104
+ if (!this.isRunning) {
105
+ return;
106
+ }
107
+ if (this.browser) {
108
+ this.browser.stop();
109
+ this.browser = null;
110
+ }
111
+ if (this.bonjour) {
112
+ this.bonjour.destroy();
113
+ this.bonjour = null;
114
+ }
115
+ this.isRunning = false;
116
+ }
117
+ /**
118
+ * Add a manually configured HA instance
119
+ */
120
+ async addInstance(config) {
121
+ const instanceId = this.generateInstanceId(config.host, config.port || 8123);
122
+ // Check if already connected
123
+ if (this.connectedProtocols.has(instanceId)) {
124
+ return this.connectedProtocols.get(instanceId);
125
+ }
126
+ // Create protocol and connect
127
+ const protocol = new HomeAssistantProtocol(config);
128
+ // Set up event handlers
129
+ this.setupProtocolHandlers(protocol, instanceId);
130
+ // Connect
131
+ await protocol.connect();
132
+ // Subscribe to state changes
133
+ await protocol.subscribeToStateChanges();
134
+ // Cache entities
135
+ const entities = await protocol.getStates();
136
+ for (const entity of entities) {
137
+ if (this.isEnabledDomain(entity.entity_id)) {
138
+ const cacheKey = `${instanceId}:${entity.entity_id}`;
139
+ this.entityCache.set(cacheKey, entity);
140
+ this.emit('entity:found', entity);
141
+ }
142
+ }
143
+ // Store protocol
144
+ this.connectedProtocols.set(instanceId, protocol);
145
+ // Also store as discovered instance
146
+ this.discoveredInstances.set(instanceId, {
147
+ id: instanceId,
148
+ host: config.host,
149
+ port: config.port || 8123,
150
+ base_url: `http://${config.host}:${config.port || 8123}`,
151
+ txtRecords: {},
152
+ requires_api_password: true,
153
+ friendlyName: config.friendlyName,
154
+ });
155
+ return protocol;
156
+ }
157
+ /**
158
+ * Remove an HA instance
159
+ */
160
+ async removeInstance(instanceId) {
161
+ const protocol = this.connectedProtocols.get(instanceId);
162
+ if (protocol) {
163
+ await protocol.disconnect();
164
+ this.connectedProtocols.delete(instanceId);
165
+ }
166
+ this.discoveredInstances.delete(instanceId);
167
+ // Remove cached entities for this instance
168
+ for (const key of this.entityCache.keys()) {
169
+ if (key.startsWith(`${instanceId}:`)) {
170
+ this.entityCache.delete(key);
171
+ }
172
+ }
173
+ this.emit('instance:lost', instanceId);
174
+ }
175
+ /**
176
+ * Stop all and cleanup
177
+ */
178
+ async stop() {
179
+ await this.stopMdnsDiscovery();
180
+ // Disconnect all protocols
181
+ for (const [instanceId, protocol] of this.connectedProtocols) {
182
+ await protocol.disconnect();
183
+ }
184
+ this.connectedProtocols.clear();
185
+ this.discoveredInstances.clear();
186
+ this.entityCache.clear();
187
+ }
188
+ /**
189
+ * Handle mDNS service found
190
+ */
191
+ handleInstanceFound(service) {
192
+ const addresses = service.addresses ?? [];
193
+ const address = addresses.find((a) => !a.includes(':')) ?? addresses[0] ?? service.host;
194
+ if (!address) {
195
+ return;
196
+ }
197
+ const instanceId = this.generateInstanceId(address, service.port);
198
+ const txtRecords = this.parseTxtRecords(service.txt);
199
+ const instance = {
200
+ id: instanceId,
201
+ host: address,
202
+ port: service.port,
203
+ base_url: txtRecords['base_url'] || `http://${address}:${service.port}`,
204
+ txtRecords,
205
+ requires_api_password: txtRecords['requires_api_password'] === 'true',
206
+ friendlyName: service.name,
207
+ };
208
+ // Check if this is a new instance
209
+ const existing = this.discoveredInstances.get(instanceId);
210
+ if (!existing) {
211
+ this.discoveredInstances.set(instanceId, instance);
212
+ this.emit('instance:found', instance);
213
+ }
214
+ }
215
+ /**
216
+ * Handle mDNS service lost
217
+ */
218
+ handleInstanceLost(service) {
219
+ const addresses = service.addresses ?? [];
220
+ const address = addresses.find((a) => !a.includes(':')) ?? addresses[0] ?? service.host;
221
+ if (!address) {
222
+ return;
223
+ }
224
+ const instanceId = this.generateInstanceId(address, service.port);
225
+ if (this.discoveredInstances.has(instanceId)) {
226
+ // Don't remove if we have an active connection (manually added)
227
+ if (!this.connectedProtocols.has(instanceId)) {
228
+ this.discoveredInstances.delete(instanceId);
229
+ }
230
+ this.emit('instance:lost', instanceId);
231
+ }
232
+ }
233
+ /**
234
+ * Set up event handlers for a protocol
235
+ */
236
+ setupProtocolHandlers(protocol, instanceId) {
237
+ protocol.on('state:changed', (event) => {
238
+ const cacheKey = `${instanceId}:${event.entity_id}`;
239
+ if (event.new_state) {
240
+ if (this.isEnabledDomain(event.entity_id)) {
241
+ const existing = this.entityCache.has(cacheKey);
242
+ this.entityCache.set(cacheKey, event.new_state);
243
+ if (existing) {
244
+ this.emit('entity:updated', event.new_state);
245
+ }
246
+ else {
247
+ this.emit('entity:found', event.new_state);
248
+ }
249
+ }
250
+ }
251
+ else {
252
+ // Entity removed
253
+ if (this.entityCache.has(cacheKey)) {
254
+ this.entityCache.delete(cacheKey);
255
+ this.emit('entity:removed', event.entity_id);
256
+ }
257
+ }
258
+ });
259
+ protocol.on('disconnected', () => {
260
+ // Clear cached entities for this instance on disconnect
261
+ for (const key of this.entityCache.keys()) {
262
+ if (key.startsWith(`${instanceId}:`)) {
263
+ this.entityCache.delete(key);
264
+ }
265
+ }
266
+ });
267
+ protocol.on('error', (error) => {
268
+ this.emit('error', error);
269
+ });
270
+ }
271
+ /**
272
+ * Check if entity domain is enabled
273
+ */
274
+ isEnabledDomain(entityId) {
275
+ const domain = entityId.split('.')[0];
276
+ return this.enabledDomains.includes(domain);
277
+ }
278
+ /**
279
+ * Generate unique instance ID
280
+ */
281
+ generateInstanceId(host, port) {
282
+ return `ha:${host}:${port}`;
283
+ }
284
+ /**
285
+ * Parse TXT records from mDNS service
286
+ */
287
+ parseTxtRecords(txt) {
288
+ const records = {};
289
+ if (!txt) {
290
+ return records;
291
+ }
292
+ for (const [key, value] of Object.entries(txt)) {
293
+ if (typeof value === 'string') {
294
+ records[key] = value;
295
+ }
296
+ else if (Buffer.isBuffer(value)) {
297
+ records[key] = value.toString('utf-8');
298
+ }
299
+ else if (value !== undefined && value !== null) {
300
+ records[key] = String(value);
301
+ }
302
+ }
303
+ return records;
304
+ }
305
+ /**
306
+ * Probe if a host has Home Assistant running
307
+ */
308
+ static async probe(host, port = 8123, secure = false, timeout = 5000) {
309
+ return HomeAssistantProtocol.probe(host, port, secure, timeout);
310
+ }
311
+ }
312
+ export { HA_SERVICE_TYPE };
313
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzY292ZXJ5LmNsYXNzZXMuaG9tZWFzc2lzdGFudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3RzL2Rpc2NvdmVyeS9kaXNjb3ZlcnkuY2xhc3Nlcy5ob21lYXNzaXN0YW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sZUFBZSxDQUFDO0FBUXpDLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHdDQUF3QyxDQUFDO0FBRS9FOztHQUVHO0FBQ0gsTUFBTSxlQUFlLEdBQUcsc0JBQXNCLENBQUM7QUFFL0M7O0dBRUc7QUFDSCxNQUFNLGVBQWUsR0FBMkI7SUFDOUMsT0FBTztJQUNQLFFBQVE7SUFDUixRQUFRO0lBQ1IsZUFBZTtJQUNmLFNBQVM7SUFDVCxLQUFLO0lBQ0wsT0FBTztJQUNQLE1BQU07SUFDTixRQUFRO0lBQ1IsY0FBYztDQUNmLENBQUM7QUFFRjs7OztHQUlHO0FBQ0gsTUFBTSxPQUFPLHNCQUF1QixTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQUM3RCxPQUFPLEdBQTBDLElBQUksQ0FBQztJQUN0RCxPQUFPLEdBQTBDLElBQUksQ0FBQztJQUN0RCxtQkFBbUIsR0FBa0QsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUMvRSxrQkFBa0IsR0FBdUMsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNuRSxXQUFXLEdBQXNDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDM0QsY0FBYyxDQUF5QjtJQUN2QyxTQUFTLEdBQVksS0FBSyxDQUFDO0lBRW5DLFlBQVksT0FBcUQ7UUFDL0QsS0FBSyxFQUFFLENBQUM7UUFDUixJQUFJLENBQUMsY0FBYyxHQUFHLE9BQU8sRUFBRSxjQUFjLElBQUksZUFBZSxDQUFDO0lBQ25FLENBQUM7SUFFRDs7T0FFRztJQUNILElBQVcsT0FBTztRQUNoQixPQUFPLElBQUksQ0FBQyxTQUFTLENBQUM7SUFDeEIsQ0FBQztJQUVEOztPQUVHO0lBQ0ksWUFB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
@@ -0,0 +1,90 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type { IDiscoveredDevice, IDiscoveryOptions } from '../interfaces/index.js';
3
+ /**
4
+ * Service type definitions for mDNS discovery
5
+ */
6
+ declare const SERVICE_TYPES: {
7
+ readonly ESCL: "_uscan._tcp";
8
+ readonly ESCL_SECURE: "_uscans._tcp";
9
+ readonly SANE: "_scanner._tcp";
10
+ readonly IPP: "_ipp._tcp";
11
+ readonly IPPS: "_ipps._tcp";
12
+ readonly PDL: "_pdl-datastream._tcp";
13
+ readonly AIRPLAY: "_airplay._tcp";
14
+ readonly RAOP: "_raop._tcp";
15
+ readonly SONOS: "_sonos._tcp";
16
+ readonly GOOGLECAST: "_googlecast._tcp";
17
+ readonly SPOTIFY: "_spotify-connect._tcp";
18
+ };
19
+ /**
20
+ * mDNS/Bonjour discovery service for network devices
21
+ */
22
+ export declare class MdnsDiscovery extends plugins.events.EventEmitter {
23
+ private bonjour;
24
+ private browsers;
25
+ private discoveredDevices;
26
+ private options;
27
+ private isRunning;
28
+ constructor(options?: IDiscoveryOptions);
29
+ /**
30
+ * Check if discovery is currently running
31
+ */
32
+ get running(): boolean;
33
+ /**
34
+ * Get all discovered devices
35
+ */
36
+ getDevices(): IDiscoveredDevice[];
37
+ /**
38
+ * Get discovered scanners only
39
+ */
40
+ getScanners(): IDiscoveredDevice[];
41
+ /**
42
+ * Get discovered printers only
43
+ */
44
+ getPrinters(): IDiscoveredDevice[];
45
+ /**
46
+ * Start mDNS discovery
47
+ */
48
+ start(): Promise<void>;
49
+ /**
50
+ * Stop mDNS discovery
51
+ */
52
+ stop(): Promise<void>;
53
+ /**
54
+ * Clear discovered devices
55
+ */
56
+ clear(): void;
57
+ /**
58
+ * Browse for a specific service type
59
+ */
60
+ private browseService;
61
+ /**
62
+ * Handle discovered service
63
+ */
64
+ private handleServiceFound;
65
+ /**
66
+ * Handle lost service
67
+ */
68
+ private handleServiceLost;
69
+ /**
70
+ * Parse Bonjour service into device info
71
+ */
72
+ private parseService;
73
+ /**
74
+ * Generate unique device ID
75
+ */
76
+ private generateDeviceId;
77
+ /**
78
+ * Parse TXT records from service
79
+ */
80
+ private parseTxtRecords;
81
+ /**
82
+ * Determine device type from service type
83
+ */
84
+ private getDeviceType;
85
+ /**
86
+ * Determine protocol from service type
87
+ */
88
+ private getProtocol;
89
+ }
90
+ export { SERVICE_TYPES };