@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,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 };
|