@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,666 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Home Assistant Specific Interfaces
|
|
3
|
+
* Types for Home Assistant WebSocket API, entities, and configuration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// ============================================================================
|
|
7
|
+
// Configuration
|
|
8
|
+
// ============================================================================
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Configuration for connecting to a Home Assistant instance
|
|
12
|
+
*/
|
|
13
|
+
export interface IHomeAssistantInstanceConfig {
|
|
14
|
+
/** Home Assistant host (IP or hostname) */
|
|
15
|
+
host: string;
|
|
16
|
+
/** Port number (default: 8123) */
|
|
17
|
+
port?: number;
|
|
18
|
+
/** Long-lived access token from HA */
|
|
19
|
+
token: string;
|
|
20
|
+
/** Use secure WebSocket (wss://) */
|
|
21
|
+
secure?: boolean;
|
|
22
|
+
/** Friendly name for this instance */
|
|
23
|
+
friendlyName?: string;
|
|
24
|
+
/** Auto-reconnect on disconnect (default: true) */
|
|
25
|
+
autoReconnect?: boolean;
|
|
26
|
+
/** Reconnect delay in ms (default: 5000) */
|
|
27
|
+
reconnectDelay?: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Home Assistant configuration in DeviceManager options
|
|
32
|
+
*/
|
|
33
|
+
export interface IHomeAssistantOptions {
|
|
34
|
+
/** Enable mDNS auto-discovery of HA instances */
|
|
35
|
+
autoDiscovery?: boolean;
|
|
36
|
+
/** Manually configured HA instances */
|
|
37
|
+
instances?: IHomeAssistantInstanceConfig[];
|
|
38
|
+
/** Filter: only discover these domains (default: all) */
|
|
39
|
+
enabledDomains?: THomeAssistantDomain[];
|
|
40
|
+
/** Auto-reconnect on disconnect (default: true) */
|
|
41
|
+
autoReconnect?: boolean;
|
|
42
|
+
/** Reconnect delay in ms (default: 5000) */
|
|
43
|
+
reconnectDelay?: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// ============================================================================
|
|
47
|
+
// Entity Types
|
|
48
|
+
// ============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Supported Home Assistant domains that map to features
|
|
52
|
+
*/
|
|
53
|
+
export type THomeAssistantDomain =
|
|
54
|
+
| 'light'
|
|
55
|
+
| 'switch'
|
|
56
|
+
| 'sensor'
|
|
57
|
+
| 'binary_sensor'
|
|
58
|
+
| 'climate'
|
|
59
|
+
| 'fan'
|
|
60
|
+
| 'cover'
|
|
61
|
+
| 'lock'
|
|
62
|
+
| 'camera'
|
|
63
|
+
| 'media_player';
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Home Assistant entity state
|
|
67
|
+
*/
|
|
68
|
+
export interface IHomeAssistantEntity {
|
|
69
|
+
/** Entity ID (e.g., "light.living_room") */
|
|
70
|
+
entity_id: string;
|
|
71
|
+
/** Current state value (e.g., "on", "off", "25.5") */
|
|
72
|
+
state: string;
|
|
73
|
+
/** Additional attributes */
|
|
74
|
+
attributes: IHomeAssistantEntityAttributes;
|
|
75
|
+
/** Last changed timestamp */
|
|
76
|
+
last_changed: string;
|
|
77
|
+
/** Last updated timestamp */
|
|
78
|
+
last_updated: string;
|
|
79
|
+
/** Context information */
|
|
80
|
+
context: IHomeAssistantContext;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Common entity attributes
|
|
85
|
+
*/
|
|
86
|
+
export interface IHomeAssistantEntityAttributes {
|
|
87
|
+
/** Friendly name */
|
|
88
|
+
friendly_name?: string;
|
|
89
|
+
/** Device class */
|
|
90
|
+
device_class?: string;
|
|
91
|
+
/** Unit of measurement */
|
|
92
|
+
unit_of_measurement?: string;
|
|
93
|
+
/** Icon */
|
|
94
|
+
icon?: string;
|
|
95
|
+
/** Entity category */
|
|
96
|
+
entity_category?: string;
|
|
97
|
+
/** Assumed state (for optimistic updates) */
|
|
98
|
+
assumed_state?: boolean;
|
|
99
|
+
/** Supported features bitmask */
|
|
100
|
+
supported_features?: number;
|
|
101
|
+
/** Additional dynamic attributes */
|
|
102
|
+
[key: string]: unknown;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Light-specific attributes
|
|
107
|
+
*/
|
|
108
|
+
export interface IHomeAssistantLightAttributes extends IHomeAssistantEntityAttributes {
|
|
109
|
+
brightness?: number; // 0-255
|
|
110
|
+
color_temp?: number; // Mireds
|
|
111
|
+
color_temp_kelvin?: number; // Kelvin
|
|
112
|
+
hs_color?: [number, number]; // [hue 0-360, saturation 0-100]
|
|
113
|
+
rgb_color?: [number, number, number];
|
|
114
|
+
xy_color?: [number, number];
|
|
115
|
+
rgbw_color?: [number, number, number, number];
|
|
116
|
+
rgbww_color?: [number, number, number, number, number];
|
|
117
|
+
effect?: string;
|
|
118
|
+
effect_list?: string[];
|
|
119
|
+
color_mode?: string;
|
|
120
|
+
supported_color_modes?: string[];
|
|
121
|
+
min_mireds?: number;
|
|
122
|
+
max_mireds?: number;
|
|
123
|
+
min_color_temp_kelvin?: number;
|
|
124
|
+
max_color_temp_kelvin?: number;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Climate-specific attributes
|
|
129
|
+
*/
|
|
130
|
+
export interface IHomeAssistantClimateAttributes extends IHomeAssistantEntityAttributes {
|
|
131
|
+
hvac_modes?: string[];
|
|
132
|
+
hvac_action?: string;
|
|
133
|
+
current_temperature?: number;
|
|
134
|
+
target_temp_high?: number;
|
|
135
|
+
target_temp_low?: number;
|
|
136
|
+
temperature?: number;
|
|
137
|
+
preset_mode?: string;
|
|
138
|
+
preset_modes?: string[];
|
|
139
|
+
fan_mode?: string;
|
|
140
|
+
fan_modes?: string[];
|
|
141
|
+
swing_mode?: string;
|
|
142
|
+
swing_modes?: string[];
|
|
143
|
+
aux_heat?: boolean;
|
|
144
|
+
current_humidity?: number;
|
|
145
|
+
humidity?: number;
|
|
146
|
+
min_temp?: number;
|
|
147
|
+
max_temp?: number;
|
|
148
|
+
target_temp_step?: number;
|
|
149
|
+
min_humidity?: number;
|
|
150
|
+
max_humidity?: number;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Sensor-specific attributes
|
|
155
|
+
*/
|
|
156
|
+
export interface IHomeAssistantSensorAttributes extends IHomeAssistantEntityAttributes {
|
|
157
|
+
state_class?: 'measurement' | 'total' | 'total_increasing';
|
|
158
|
+
native_unit_of_measurement?: string;
|
|
159
|
+
native_value?: string | number;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Cover-specific attributes
|
|
164
|
+
*/
|
|
165
|
+
export interface IHomeAssistantCoverAttributes extends IHomeAssistantEntityAttributes {
|
|
166
|
+
current_position?: number; // 0-100
|
|
167
|
+
current_tilt_position?: number; // 0-100
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Fan-specific attributes
|
|
172
|
+
*/
|
|
173
|
+
export interface IHomeAssistantFanAttributes extends IHomeAssistantEntityAttributes {
|
|
174
|
+
percentage?: number; // 0-100
|
|
175
|
+
percentage_step?: number;
|
|
176
|
+
preset_mode?: string;
|
|
177
|
+
preset_modes?: string[];
|
|
178
|
+
oscillating?: boolean;
|
|
179
|
+
direction?: 'forward' | 'reverse';
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Lock-specific attributes
|
|
184
|
+
*/
|
|
185
|
+
export interface IHomeAssistantLockAttributes extends IHomeAssistantEntityAttributes {
|
|
186
|
+
is_locked?: boolean;
|
|
187
|
+
is_locking?: boolean;
|
|
188
|
+
is_unlocking?: boolean;
|
|
189
|
+
is_jammed?: boolean;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Camera-specific attributes
|
|
194
|
+
*/
|
|
195
|
+
export interface IHomeAssistantCameraAttributes extends IHomeAssistantEntityAttributes {
|
|
196
|
+
access_token?: string;
|
|
197
|
+
entity_picture?: string;
|
|
198
|
+
frontend_stream_type?: 'hls' | 'web_rtc';
|
|
199
|
+
is_streaming?: boolean;
|
|
200
|
+
motion_detection?: boolean;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Media player-specific attributes
|
|
205
|
+
*/
|
|
206
|
+
export interface IHomeAssistantMediaPlayerAttributes extends IHomeAssistantEntityAttributes {
|
|
207
|
+
volume_level?: number; // 0-1
|
|
208
|
+
is_volume_muted?: boolean;
|
|
209
|
+
media_content_id?: string;
|
|
210
|
+
media_content_type?: string;
|
|
211
|
+
media_duration?: number;
|
|
212
|
+
media_position?: number;
|
|
213
|
+
media_position_updated_at?: string;
|
|
214
|
+
media_title?: string;
|
|
215
|
+
media_artist?: string;
|
|
216
|
+
media_album_name?: string;
|
|
217
|
+
media_album_artist?: string;
|
|
218
|
+
media_track?: number;
|
|
219
|
+
media_series_title?: string;
|
|
220
|
+
media_season?: number;
|
|
221
|
+
media_episode?: number;
|
|
222
|
+
app_id?: string;
|
|
223
|
+
app_name?: string;
|
|
224
|
+
source?: string;
|
|
225
|
+
source_list?: string[];
|
|
226
|
+
sound_mode?: string;
|
|
227
|
+
sound_mode_list?: string[];
|
|
228
|
+
shuffle?: boolean;
|
|
229
|
+
repeat?: 'off' | 'all' | 'one';
|
|
230
|
+
entity_picture_local?: string;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Context for entity state changes
|
|
235
|
+
*/
|
|
236
|
+
export interface IHomeAssistantContext {
|
|
237
|
+
id: string;
|
|
238
|
+
parent_id?: string;
|
|
239
|
+
user_id?: string;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ============================================================================
|
|
243
|
+
// WebSocket Message Types
|
|
244
|
+
// ============================================================================
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Base message structure
|
|
248
|
+
*/
|
|
249
|
+
export interface IHomeAssistantMessage {
|
|
250
|
+
id?: number;
|
|
251
|
+
type: string;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Authentication required message
|
|
256
|
+
*/
|
|
257
|
+
export interface IHomeAssistantAuthRequired extends IHomeAssistantMessage {
|
|
258
|
+
type: 'auth_required';
|
|
259
|
+
ha_version: string;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Authentication message to send
|
|
264
|
+
*/
|
|
265
|
+
export interface IHomeAssistantAuth extends IHomeAssistantMessage {
|
|
266
|
+
type: 'auth';
|
|
267
|
+
access_token: string;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Authentication success
|
|
272
|
+
*/
|
|
273
|
+
export interface IHomeAssistantAuthOk extends IHomeAssistantMessage {
|
|
274
|
+
type: 'auth_ok';
|
|
275
|
+
ha_version: string;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Authentication invalid
|
|
280
|
+
*/
|
|
281
|
+
export interface IHomeAssistantAuthInvalid extends IHomeAssistantMessage {
|
|
282
|
+
type: 'auth_invalid';
|
|
283
|
+
message: string;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Result message
|
|
288
|
+
*/
|
|
289
|
+
export interface IHomeAssistantResult extends IHomeAssistantMessage {
|
|
290
|
+
id: number;
|
|
291
|
+
type: 'result';
|
|
292
|
+
success: boolean;
|
|
293
|
+
result?: unknown;
|
|
294
|
+
error?: {
|
|
295
|
+
code: string;
|
|
296
|
+
message: string;
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Event message
|
|
302
|
+
*/
|
|
303
|
+
export interface IHomeAssistantEvent extends IHomeAssistantMessage {
|
|
304
|
+
id: number;
|
|
305
|
+
type: 'event';
|
|
306
|
+
event: {
|
|
307
|
+
event_type: string;
|
|
308
|
+
data: unknown;
|
|
309
|
+
origin: string;
|
|
310
|
+
time_fired: string;
|
|
311
|
+
context: IHomeAssistantContext;
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* State changed event data
|
|
317
|
+
*/
|
|
318
|
+
export interface IHomeAssistantStateChangedEvent {
|
|
319
|
+
entity_id: string;
|
|
320
|
+
old_state: IHomeAssistantEntity | null;
|
|
321
|
+
new_state: IHomeAssistantEntity | null;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Subscribe events request
|
|
326
|
+
*/
|
|
327
|
+
export interface IHomeAssistantSubscribeEvents extends IHomeAssistantMessage {
|
|
328
|
+
id: number;
|
|
329
|
+
type: 'subscribe_events';
|
|
330
|
+
event_type?: string;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Get states request
|
|
335
|
+
*/
|
|
336
|
+
export interface IHomeAssistantGetStates extends IHomeAssistantMessage {
|
|
337
|
+
id: number;
|
|
338
|
+
type: 'get_states';
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Call service request
|
|
343
|
+
*/
|
|
344
|
+
export interface IHomeAssistantCallService extends IHomeAssistantMessage {
|
|
345
|
+
id: number;
|
|
346
|
+
type: 'call_service';
|
|
347
|
+
domain: string;
|
|
348
|
+
service: string;
|
|
349
|
+
target?: {
|
|
350
|
+
entity_id?: string | string[];
|
|
351
|
+
device_id?: string | string[];
|
|
352
|
+
area_id?: string | string[];
|
|
353
|
+
};
|
|
354
|
+
service_data?: Record<string, unknown>;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Get services request
|
|
359
|
+
*/
|
|
360
|
+
export interface IHomeAssistantGetServices extends IHomeAssistantMessage {
|
|
361
|
+
id: number;
|
|
362
|
+
type: 'get_services';
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Get config request
|
|
367
|
+
*/
|
|
368
|
+
export interface IHomeAssistantGetConfig extends IHomeAssistantMessage {
|
|
369
|
+
id: number;
|
|
370
|
+
type: 'get_config';
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Home Assistant config response
|
|
375
|
+
*/
|
|
376
|
+
export interface IHomeAssistantConfig {
|
|
377
|
+
latitude: number;
|
|
378
|
+
longitude: number;
|
|
379
|
+
elevation: number;
|
|
380
|
+
unit_system: {
|
|
381
|
+
length: string;
|
|
382
|
+
mass: string;
|
|
383
|
+
pressure: string;
|
|
384
|
+
temperature: string;
|
|
385
|
+
volume: string;
|
|
386
|
+
};
|
|
387
|
+
location_name: string;
|
|
388
|
+
time_zone: string;
|
|
389
|
+
components: string[];
|
|
390
|
+
config_dir: string;
|
|
391
|
+
allowlist_external_dirs: string[];
|
|
392
|
+
allowlist_external_urls: string[];
|
|
393
|
+
version: string;
|
|
394
|
+
config_source: string;
|
|
395
|
+
safe_mode: boolean;
|
|
396
|
+
state: 'NOT_RUNNING' | 'STARTING' | 'RUNNING' | 'STOPPING' | 'FINAL_WRITE';
|
|
397
|
+
external_url: string | null;
|
|
398
|
+
internal_url: string | null;
|
|
399
|
+
currency: string;
|
|
400
|
+
country: string;
|
|
401
|
+
language: string;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// ============================================================================
|
|
405
|
+
// Service Definitions
|
|
406
|
+
// ============================================================================
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* Light service data
|
|
410
|
+
*/
|
|
411
|
+
export interface IHomeAssistantLightServiceData {
|
|
412
|
+
brightness?: number; // 0-255
|
|
413
|
+
brightness_pct?: number; // 0-100
|
|
414
|
+
brightness_step?: number; // Step to increase/decrease
|
|
415
|
+
brightness_step_pct?: number; // Step percentage
|
|
416
|
+
color_temp?: number; // Mireds
|
|
417
|
+
color_temp_kelvin?: number; // Kelvin
|
|
418
|
+
hs_color?: [number, number]; // [hue, saturation]
|
|
419
|
+
rgb_color?: [number, number, number];
|
|
420
|
+
xy_color?: [number, number];
|
|
421
|
+
rgbw_color?: [number, number, number, number];
|
|
422
|
+
rgbww_color?: [number, number, number, number, number];
|
|
423
|
+
color_name?: string;
|
|
424
|
+
kelvin?: number;
|
|
425
|
+
effect?: string;
|
|
426
|
+
transition?: number; // Seconds
|
|
427
|
+
flash?: 'short' | 'long';
|
|
428
|
+
profile?: string;
|
|
429
|
+
[key: string]: unknown; // Index signature for Record<string, unknown>
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Climate service data
|
|
434
|
+
*/
|
|
435
|
+
export interface IHomeAssistantClimateServiceData {
|
|
436
|
+
hvac_mode?: string;
|
|
437
|
+
temperature?: number;
|
|
438
|
+
target_temp_high?: number;
|
|
439
|
+
target_temp_low?: number;
|
|
440
|
+
humidity?: number;
|
|
441
|
+
fan_mode?: string;
|
|
442
|
+
swing_mode?: string;
|
|
443
|
+
preset_mode?: string;
|
|
444
|
+
aux_heat?: boolean;
|
|
445
|
+
[key: string]: unknown; // Index signature for Record<string, unknown>
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Cover service data
|
|
450
|
+
*/
|
|
451
|
+
export interface IHomeAssistantCoverServiceData {
|
|
452
|
+
position?: number; // 0-100
|
|
453
|
+
tilt_position?: number; // 0-100
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
* Fan service data
|
|
458
|
+
*/
|
|
459
|
+
export interface IHomeAssistantFanServiceData {
|
|
460
|
+
percentage?: number; // 0-100
|
|
461
|
+
percentage_step?: number;
|
|
462
|
+
preset_mode?: string;
|
|
463
|
+
direction?: 'forward' | 'reverse';
|
|
464
|
+
oscillating?: boolean;
|
|
465
|
+
[key: string]: unknown; // Index signature for Record<string, unknown>
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Media player service data
|
|
470
|
+
*/
|
|
471
|
+
export interface IHomeAssistantMediaPlayerServiceData {
|
|
472
|
+
volume_level?: number; // 0-1
|
|
473
|
+
is_volume_muted?: boolean;
|
|
474
|
+
media_content_id?: string;
|
|
475
|
+
media_content_type?: string;
|
|
476
|
+
enqueue?: 'play' | 'next' | 'add' | 'replace';
|
|
477
|
+
seek_position?: number;
|
|
478
|
+
source?: string;
|
|
479
|
+
sound_mode?: string;
|
|
480
|
+
shuffle?: boolean;
|
|
481
|
+
repeat?: 'off' | 'all' | 'one';
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// ============================================================================
|
|
485
|
+
// Discovery Types
|
|
486
|
+
// ============================================================================
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* Discovered Home Assistant instance via mDNS
|
|
490
|
+
*/
|
|
491
|
+
export interface IHomeAssistantDiscoveredInstance {
|
|
492
|
+
/** Instance ID (derived from host) */
|
|
493
|
+
id: string;
|
|
494
|
+
/** Host address */
|
|
495
|
+
host: string;
|
|
496
|
+
/** Port number */
|
|
497
|
+
port: number;
|
|
498
|
+
/** Base URL */
|
|
499
|
+
base_url: string;
|
|
500
|
+
/** mDNS TXT records */
|
|
501
|
+
txtRecords: Record<string, string>;
|
|
502
|
+
/** Whether connection requires token */
|
|
503
|
+
requires_api_password: boolean;
|
|
504
|
+
/** Friendly name from mDNS */
|
|
505
|
+
friendlyName?: string;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// ============================================================================
|
|
509
|
+
// Protocol Events
|
|
510
|
+
// ============================================================================
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Events emitted by HomeAssistantProtocol
|
|
514
|
+
*/
|
|
515
|
+
export type THomeAssistantProtocolEvents = {
|
|
516
|
+
'connected': () => void;
|
|
517
|
+
'disconnected': () => void;
|
|
518
|
+
'reconnecting': (attempt: number) => void;
|
|
519
|
+
'authenticated': (config: IHomeAssistantConfig) => void;
|
|
520
|
+
'auth:failed': (message: string) => void;
|
|
521
|
+
'state:changed': (event: IHomeAssistantStateChangedEvent) => void;
|
|
522
|
+
'states:loaded': (entities: IHomeAssistantEntity[]) => void;
|
|
523
|
+
'error': (error: Error) => void;
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Events emitted by HomeAssistantDiscovery
|
|
528
|
+
*/
|
|
529
|
+
export type THomeAssistantDiscoveryEvents = {
|
|
530
|
+
'instance:found': (instance: IHomeAssistantDiscoveredInstance) => void;
|
|
531
|
+
'instance:lost': (instanceId: string) => void;
|
|
532
|
+
'entity:found': (entity: IHomeAssistantEntity) => void;
|
|
533
|
+
'entity:updated': (entity: IHomeAssistantEntity) => void;
|
|
534
|
+
'entity:removed': (entityId: string) => void;
|
|
535
|
+
'error': (error: Error) => void;
|
|
536
|
+
};
|
|
537
|
+
|
|
538
|
+
// ============================================================================
|
|
539
|
+
// Helper Types
|
|
540
|
+
// ============================================================================
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Extract domain from entity_id
|
|
544
|
+
*/
|
|
545
|
+
export function getEntityDomain(entityId: string): THomeAssistantDomain | null {
|
|
546
|
+
const domain = entityId.split('.')[0];
|
|
547
|
+
const validDomains: THomeAssistantDomain[] = [
|
|
548
|
+
'light', 'switch', 'sensor', 'binary_sensor', 'climate',
|
|
549
|
+
'fan', 'cover', 'lock', 'camera', 'media_player'
|
|
550
|
+
];
|
|
551
|
+
return validDomains.includes(domain as THomeAssistantDomain)
|
|
552
|
+
? domain as THomeAssistantDomain
|
|
553
|
+
: null;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/**
|
|
557
|
+
* Map HA domain to feature type
|
|
558
|
+
*/
|
|
559
|
+
export function domainToFeatureType(domain: THomeAssistantDomain): string {
|
|
560
|
+
const mapping: Record<THomeAssistantDomain, string> = {
|
|
561
|
+
'light': 'light',
|
|
562
|
+
'switch': 'switch',
|
|
563
|
+
'sensor': 'sensor',
|
|
564
|
+
'binary_sensor': 'sensor',
|
|
565
|
+
'climate': 'climate',
|
|
566
|
+
'fan': 'fan',
|
|
567
|
+
'cover': 'cover',
|
|
568
|
+
'lock': 'lock',
|
|
569
|
+
'camera': 'camera',
|
|
570
|
+
'media_player': 'playback',
|
|
571
|
+
};
|
|
572
|
+
return mapping[domain];
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Supported light color modes in HA
|
|
577
|
+
*/
|
|
578
|
+
export type THomeAssistantColorMode =
|
|
579
|
+
| 'unknown'
|
|
580
|
+
| 'onoff'
|
|
581
|
+
| 'brightness'
|
|
582
|
+
| 'color_temp'
|
|
583
|
+
| 'hs'
|
|
584
|
+
| 'xy'
|
|
585
|
+
| 'rgb'
|
|
586
|
+
| 'rgbw'
|
|
587
|
+
| 'rgbww'
|
|
588
|
+
| 'white';
|
|
589
|
+
|
|
590
|
+
/**
|
|
591
|
+
* Light supported features bitmask
|
|
592
|
+
*/
|
|
593
|
+
export const LIGHT_SUPPORT = {
|
|
594
|
+
EFFECT: 4,
|
|
595
|
+
FLASH: 8,
|
|
596
|
+
TRANSITION: 32,
|
|
597
|
+
} as const;
|
|
598
|
+
|
|
599
|
+
/**
|
|
600
|
+
* Climate supported features bitmask
|
|
601
|
+
*/
|
|
602
|
+
export const CLIMATE_SUPPORT = {
|
|
603
|
+
TARGET_TEMPERATURE: 1,
|
|
604
|
+
TARGET_TEMPERATURE_RANGE: 2,
|
|
605
|
+
TARGET_HUMIDITY: 4,
|
|
606
|
+
FAN_MODE: 8,
|
|
607
|
+
PRESET_MODE: 16,
|
|
608
|
+
SWING_MODE: 32,
|
|
609
|
+
AUX_HEAT: 64,
|
|
610
|
+
} as const;
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* Cover supported features bitmask
|
|
614
|
+
*/
|
|
615
|
+
export const COVER_SUPPORT = {
|
|
616
|
+
OPEN: 1,
|
|
617
|
+
CLOSE: 2,
|
|
618
|
+
SET_POSITION: 4,
|
|
619
|
+
STOP: 8,
|
|
620
|
+
OPEN_TILT: 16,
|
|
621
|
+
CLOSE_TILT: 32,
|
|
622
|
+
STOP_TILT: 64,
|
|
623
|
+
SET_TILT_POSITION: 128,
|
|
624
|
+
} as const;
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Fan supported features bitmask
|
|
628
|
+
*/
|
|
629
|
+
export const FAN_SUPPORT = {
|
|
630
|
+
SET_SPEED: 1,
|
|
631
|
+
OSCILLATE: 2,
|
|
632
|
+
DIRECTION: 4,
|
|
633
|
+
PRESET_MODE: 8,
|
|
634
|
+
} as const;
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* Lock supported features bitmask
|
|
638
|
+
*/
|
|
639
|
+
export const LOCK_SUPPORT = {
|
|
640
|
+
OPEN: 1,
|
|
641
|
+
} as const;
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Media player supported features bitmask
|
|
645
|
+
*/
|
|
646
|
+
export const MEDIA_PLAYER_SUPPORT = {
|
|
647
|
+
PAUSE: 1,
|
|
648
|
+
SEEK: 2,
|
|
649
|
+
VOLUME_SET: 4,
|
|
650
|
+
VOLUME_MUTE: 8,
|
|
651
|
+
PREVIOUS_TRACK: 16,
|
|
652
|
+
NEXT_TRACK: 32,
|
|
653
|
+
TURN_ON: 128,
|
|
654
|
+
TURN_OFF: 256,
|
|
655
|
+
PLAY_MEDIA: 512,
|
|
656
|
+
VOLUME_STEP: 1024,
|
|
657
|
+
SELECT_SOURCE: 2048,
|
|
658
|
+
STOP: 4096,
|
|
659
|
+
CLEAR_PLAYLIST: 8192,
|
|
660
|
+
PLAY: 16384,
|
|
661
|
+
SHUFFLE_SET: 32768,
|
|
662
|
+
SELECT_SOUND_MODE: 65536,
|
|
663
|
+
BROWSE_MEDIA: 131072,
|
|
664
|
+
REPEAT_SET: 262144,
|
|
665
|
+
GROUPING: 524288,
|
|
666
|
+
} as const;
|