@coffeerunhobby/mcp-ha-connect 0.5.0

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 (294) hide show
  1. package/.dockerignore +8 -0
  2. package/.env.example +149 -0
  3. package/.gitattributes +30 -0
  4. package/Dockerfile +33 -0
  5. package/LICENSE +21 -0
  6. package/README.md +394 -0
  7. package/dist/config.d.ts +33 -0
  8. package/dist/config.d.ts.map +1 -0
  9. package/dist/config.js +183 -0
  10. package/dist/config.js.map +1 -0
  11. package/dist/haClient/automations.d.ts +67 -0
  12. package/dist/haClient/automations.d.ts.map +1 -0
  13. package/dist/haClient/automations.js +181 -0
  14. package/dist/haClient/automations.js.map +1 -0
  15. package/dist/haClient/config.d.ts +28 -0
  16. package/dist/haClient/config.d.ts.map +1 -0
  17. package/dist/haClient/config.js +38 -0
  18. package/dist/haClient/config.js.map +1 -0
  19. package/dist/haClient/devices.d.ts +219 -0
  20. package/dist/haClient/devices.d.ts.map +1 -0
  21. package/dist/haClient/devices.js +506 -0
  22. package/dist/haClient/devices.js.map +1 -0
  23. package/dist/haClient/entities.d.ts +35 -0
  24. package/dist/haClient/entities.d.ts.map +1 -0
  25. package/dist/haClient/entities.js +97 -0
  26. package/dist/haClient/entities.js.map +1 -0
  27. package/dist/haClient/events.d.ts +138 -0
  28. package/dist/haClient/events.d.ts.map +1 -0
  29. package/dist/haClient/events.js +344 -0
  30. package/dist/haClient/events.js.map +1 -0
  31. package/dist/haClient/history.d.ts +26 -0
  32. package/dist/haClient/history.d.ts.map +1 -0
  33. package/dist/haClient/history.js +54 -0
  34. package/dist/haClient/history.js.map +1 -0
  35. package/dist/haClient/index.d.ts +153 -0
  36. package/dist/haClient/index.d.ts.map +1 -0
  37. package/dist/haClient/index.js +223 -0
  38. package/dist/haClient/index.js.map +1 -0
  39. package/dist/haClient/request.d.ts +34 -0
  40. package/dist/haClient/request.d.ts.map +1 -0
  41. package/dist/haClient/request.js +93 -0
  42. package/dist/haClient/request.js.map +1 -0
  43. package/dist/haClient/services.d.ts +22 -0
  44. package/dist/haClient/services.d.ts.map +1 -0
  45. package/dist/haClient/services.js +39 -0
  46. package/dist/haClient/services.js.map +1 -0
  47. package/dist/haClient/states.d.ts +26 -0
  48. package/dist/haClient/states.d.ts.map +1 -0
  49. package/dist/haClient/states.js +53 -0
  50. package/dist/haClient/states.js.map +1 -0
  51. package/dist/haClient/updates.d.ts +22 -0
  52. package/dist/haClient/updates.d.ts.map +1 -0
  53. package/dist/haClient/updates.js +48 -0
  54. package/dist/haClient/updates.js.map +1 -0
  55. package/dist/haClient.d.ts +97 -0
  56. package/dist/haClient.d.ts.map +1 -0
  57. package/dist/haClient.js +344 -0
  58. package/dist/haClient.js.map +1 -0
  59. package/dist/index.d.ts +8 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +92 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/localAI/index.d.ts +37 -0
  64. package/dist/localAI/index.d.ts.map +1 -0
  65. package/dist/localAI/index.js +73 -0
  66. package/dist/localAI/index.js.map +1 -0
  67. package/dist/localAI/prompts.d.ts +20 -0
  68. package/dist/localAI/prompts.d.ts.map +1 -0
  69. package/dist/localAI/prompts.js +48 -0
  70. package/dist/localAI/prompts.js.map +1 -0
  71. package/dist/localAI/providers/base.d.ts +51 -0
  72. package/dist/localAI/providers/base.d.ts.map +1 -0
  73. package/dist/localAI/providers/base.js +80 -0
  74. package/dist/localAI/providers/base.js.map +1 -0
  75. package/dist/localAI/providers/ollama.d.ts +22 -0
  76. package/dist/localAI/providers/ollama.d.ts.map +1 -0
  77. package/dist/localAI/providers/ollama.js +63 -0
  78. package/dist/localAI/providers/ollama.js.map +1 -0
  79. package/dist/localAI/providers/openai.d.ts +23 -0
  80. package/dist/localAI/providers/openai.d.ts.map +1 -0
  81. package/dist/localAI/providers/openai.js +63 -0
  82. package/dist/localAI/providers/openai.js.map +1 -0
  83. package/dist/localAI/types.d.ts +61 -0
  84. package/dist/localAI/types.d.ts.map +1 -0
  85. package/dist/localAI/types.js +6 -0
  86. package/dist/localAI/types.js.map +1 -0
  87. package/dist/ollamaClient.d.ts +37 -0
  88. package/dist/ollamaClient.d.ts.map +1 -0
  89. package/dist/ollamaClient.js +110 -0
  90. package/dist/ollamaClient.js.map +1 -0
  91. package/dist/resources/index.d.ts +11 -0
  92. package/dist/resources/index.d.ts.map +1 -0
  93. package/dist/resources/index.js +238 -0
  94. package/dist/resources/index.js.map +1 -0
  95. package/dist/server/common.d.ts +9 -0
  96. package/dist/server/common.d.ts.map +1 -0
  97. package/dist/server/common.js +27 -0
  98. package/dist/server/common.js.map +1 -0
  99. package/dist/server/eventSubscription.d.ts +53 -0
  100. package/dist/server/eventSubscription.d.ts.map +1 -0
  101. package/dist/server/eventSubscription.js +257 -0
  102. package/dist/server/eventSubscription.js.map +1 -0
  103. package/dist/server/http.d.ts +12 -0
  104. package/dist/server/http.d.ts.map +1 -0
  105. package/dist/server/http.js +491 -0
  106. package/dist/server/http.js.map +1 -0
  107. package/dist/server/rateLimiter.d.ts +70 -0
  108. package/dist/server/rateLimiter.d.ts.map +1 -0
  109. package/dist/server/rateLimiter.js +156 -0
  110. package/dist/server/rateLimiter.js.map +1 -0
  111. package/dist/server/sse.d.ts +32 -0
  112. package/dist/server/sse.d.ts.map +1 -0
  113. package/dist/server/sse.js +76 -0
  114. package/dist/server/sse.js.map +1 -0
  115. package/dist/server/stdio.d.ts +8 -0
  116. package/dist/server/stdio.d.ts.map +1 -0
  117. package/dist/server/stdio.js +16 -0
  118. package/dist/server/stdio.js.map +1 -0
  119. package/dist/server/stream.d.ts +26 -0
  120. package/dist/server/stream.d.ts.map +1 -0
  121. package/dist/server/stream.js +81 -0
  122. package/dist/server/stream.js.map +1 -0
  123. package/dist/server.d.ts +8 -0
  124. package/dist/server.d.ts.map +1 -0
  125. package/dist/server.js +30 -0
  126. package/dist/server.js.map +1 -0
  127. package/dist/tools/callService.d.ts +8 -0
  128. package/dist/tools/callService.d.ts.map +1 -0
  129. package/dist/tools/callService.js +100 -0
  130. package/dist/tools/callService.js.map +1 -0
  131. package/dist/tools/getClient.d.ts +8 -0
  132. package/dist/tools/getClient.d.ts.map +1 -0
  133. package/dist/tools/getClient.js +94 -0
  134. package/dist/tools/getClient.js.map +1 -0
  135. package/dist/tools/getDevice.d.ts +8 -0
  136. package/dist/tools/getDevice.d.ts.map +1 -0
  137. package/dist/tools/getDevice.js +94 -0
  138. package/dist/tools/getDevice.js.map +1 -0
  139. package/dist/tools/getEntitiesByDomain.d.ts +8 -0
  140. package/dist/tools/getEntitiesByDomain.d.ts.map +1 -0
  141. package/dist/tools/getEntitiesByDomain.js +80 -0
  142. package/dist/tools/getEntitiesByDomain.js.map +1 -0
  143. package/dist/tools/getState.d.ts +8 -0
  144. package/dist/tools/getState.d.ts.map +1 -0
  145. package/dist/tools/getState.js +90 -0
  146. package/dist/tools/getState.js.map +1 -0
  147. package/dist/tools/getStates.d.ts +8 -0
  148. package/dist/tools/getStates.d.ts.map +1 -0
  149. package/dist/tools/getStates.js +70 -0
  150. package/dist/tools/getStates.js.map +1 -0
  151. package/dist/tools/index.d.ts +9 -0
  152. package/dist/tools/index.d.ts.map +1 -0
  153. package/dist/tools/index.js +9 -0
  154. package/dist/tools/index.js.map +1 -0
  155. package/dist/tools/listClients.d.ts +8 -0
  156. package/dist/tools/listClients.d.ts.map +1 -0
  157. package/dist/tools/listClients.js +73 -0
  158. package/dist/tools/listClients.js.map +1 -0
  159. package/dist/tools/listDevices.d.ts +8 -0
  160. package/dist/tools/listDevices.d.ts.map +1 -0
  161. package/dist/tools/listDevices.js +73 -0
  162. package/dist/tools/listDevices.js.map +1 -0
  163. package/dist/tools/listSites.d.ts +8 -0
  164. package/dist/tools/listSites.d.ts.map +1 -0
  165. package/dist/tools/listSites.js +67 -0
  166. package/dist/tools/listSites.js.map +1 -0
  167. package/dist/tools/registry.d.ts +9 -0
  168. package/dist/tools/registry.d.ts.map +1 -0
  169. package/dist/tools/registry.js +1382 -0
  170. package/dist/tools/registry.js.map +1 -0
  171. package/dist/tools/searchDevices.d.ts +8 -0
  172. package/dist/tools/searchDevices.d.ts.map +1 -0
  173. package/dist/tools/searchDevices.js +84 -0
  174. package/dist/tools/searchDevices.js.map +1 -0
  175. package/dist/tools/searchEntities.d.ts +8 -0
  176. package/dist/tools/searchEntities.d.ts.map +1 -0
  177. package/dist/tools/searchEntities.js +80 -0
  178. package/dist/tools/searchEntities.js.map +1 -0
  179. package/dist/types/entity.d.ts +98 -0
  180. package/dist/types/entity.d.ts.map +1 -0
  181. package/dist/types/entity.js +2 -0
  182. package/dist/types/entity.js.map +1 -0
  183. package/dist/types/errors.d.ts +16 -0
  184. package/dist/types/errors.d.ts.map +1 -0
  185. package/dist/types/errors.js +32 -0
  186. package/dist/types/errors.js.map +1 -0
  187. package/dist/types/haConfig.d.ts +8 -0
  188. package/dist/types/haConfig.d.ts.map +1 -0
  189. package/dist/types/haConfig.js +2 -0
  190. package/dist/types/haConfig.js.map +1 -0
  191. package/dist/types/index.d.ts +6 -0
  192. package/dist/types/index.d.ts.map +1 -0
  193. package/dist/types/index.js +2 -0
  194. package/dist/types/index.js.map +1 -0
  195. package/dist/types/request.d.ts +7 -0
  196. package/dist/types/request.d.ts.map +1 -0
  197. package/dist/types/request.js +2 -0
  198. package/dist/types/request.js.map +1 -0
  199. package/dist/types/serviceCall.d.ts +18 -0
  200. package/dist/types/serviceCall.d.ts.map +1 -0
  201. package/dist/types/serviceCall.js +2 -0
  202. package/dist/types/serviceCall.js.map +1 -0
  203. package/dist/types.d.ts +2 -0
  204. package/dist/types.d.ts.map +1 -0
  205. package/dist/types.js +3 -0
  206. package/dist/types.js.map +1 -0
  207. package/dist/utils/config-validations.d.ts +12 -0
  208. package/dist/utils/config-validations.d.ts.map +1 -0
  209. package/dist/utils/config-validations.js +43 -0
  210. package/dist/utils/config-validations.js.map +1 -0
  211. package/dist/utils/logger.d.ts +24 -0
  212. package/dist/utils/logger.d.ts.map +1 -0
  213. package/dist/utils/logger.js +94 -0
  214. package/dist/utils/logger.js.map +1 -0
  215. package/dist/wrapper.d.ts +8 -0
  216. package/dist/wrapper.d.ts.map +1 -0
  217. package/dist/wrapper.js +301 -0
  218. package/dist/wrapper.js.map +1 -0
  219. package/docker-compose.yml +17 -0
  220. package/docs/CHANGELOG.md +86 -0
  221. package/docs/LOCAL_CLIENT.md +268 -0
  222. package/docs/SSE_API.md +341 -0
  223. package/eslint.config.js +33 -0
  224. package/n8n/ai-agent-safety-monitor.json +355 -0
  225. package/openapi.json +166 -0
  226. package/package.json +51 -0
  227. package/src/config.ts +260 -0
  228. package/src/haClient/automations.ts +217 -0
  229. package/src/haClient/config.ts +41 -0
  230. package/src/haClient/devices.ts +653 -0
  231. package/src/haClient/entities.ts +128 -0
  232. package/src/haClient/events.ts +456 -0
  233. package/src/haClient/history.ts +68 -0
  234. package/src/haClient/index.ts +287 -0
  235. package/src/haClient/request.ts +127 -0
  236. package/src/haClient/services.ts +45 -0
  237. package/src/haClient/states.ts +60 -0
  238. package/src/haClient/updates.ts +58 -0
  239. package/src/index.ts +99 -0
  240. package/src/localAI/index.ts +88 -0
  241. package/src/localAI/prompts.ts +50 -0
  242. package/src/localAI/providers/base.ts +120 -0
  243. package/src/localAI/providers/ollama.ts +78 -0
  244. package/src/localAI/providers/openai.ts +86 -0
  245. package/src/localAI/types.ts +67 -0
  246. package/src/resources/index.ts +266 -0
  247. package/src/server/common.ts +38 -0
  248. package/src/server/eventSubscription.ts +318 -0
  249. package/src/server/http.ts +546 -0
  250. package/src/server/rateLimiter.ts +195 -0
  251. package/src/server/sse.ts +120 -0
  252. package/src/server/stdio.ts +22 -0
  253. package/src/server/stream.ts +113 -0
  254. package/src/tools/callService.ts +114 -0
  255. package/src/tools/getEntitiesByDomain.ts +92 -0
  256. package/src/tools/getState.ts +103 -0
  257. package/src/tools/getStates.ts +80 -0
  258. package/src/tools/index.ts +9 -0
  259. package/src/tools/registry.ts +1521 -0
  260. package/src/tools/searchEntities.ts +92 -0
  261. package/src/types/entity.ts +110 -0
  262. package/src/types/errors.ts +33 -0
  263. package/src/types/haConfig.ts +7 -0
  264. package/src/types/index.ts +5 -0
  265. package/src/types/request.ts +6 -0
  266. package/src/types/serviceCall.ts +18 -0
  267. package/src/types.ts +2 -0
  268. package/src/utils/config-validations.ts +46 -0
  269. package/src/utils/logger.ts +114 -0
  270. package/src/wrapper.ts +340 -0
  271. package/tests/config.test.ts +332 -0
  272. package/tests/haClient/automations.test.ts +133 -0
  273. package/tests/haClient/config.test.ts +96 -0
  274. package/tests/haClient/entities.test.ts +188 -0
  275. package/tests/haClient/history.test.ts +170 -0
  276. package/tests/haClient/index.test.ts +221 -0
  277. package/tests/haClient/request.test.ts +217 -0
  278. package/tests/haClient/services.test.ts +120 -0
  279. package/tests/haClient/states.test.ts +119 -0
  280. package/tests/haClient/updates.test.ts +193 -0
  281. package/tests/index.test.ts +164 -0
  282. package/tests/localAI/index.test.ts +168 -0
  283. package/tests/localAI/ollama.test.ts +187 -0
  284. package/tests/localAI/openai.test.ts +257 -0
  285. package/tests/server/common.test.ts +64 -0
  286. package/tests/server/http.test.ts +326 -0
  287. package/tests/server/sse.test.ts +240 -0
  288. package/tests/server/stdio.test.ts +102 -0
  289. package/tests/server/stream.test.ts +287 -0
  290. package/tests/tools/registry.test.ts +355 -0
  291. package/tests/utils/config-validations.test.ts +289 -0
  292. package/tests/utils/logger.test.ts +327 -0
  293. package/tsconfig.json +25 -0
  294. package/vitest.config.ts +26 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Home Assistant WebSocket Event Subscription
3
+ * Connects to Home Assistant WebSocket API to receive real-time events
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ export interface HaEvent {
7
+ event_type: string;
8
+ data: {
9
+ entity_id?: string;
10
+ old_state?: {
11
+ entity_id: string;
12
+ state: string;
13
+ attributes: Record<string, unknown>;
14
+ last_changed: string;
15
+ last_updated: string;
16
+ } | null;
17
+ new_state?: {
18
+ entity_id: string;
19
+ state: string;
20
+ attributes: Record<string, unknown>;
21
+ last_changed: string;
22
+ last_updated: string;
23
+ } | null;
24
+ domain?: string;
25
+ service?: string;
26
+ service_data?: Record<string, unknown>;
27
+ [key: string]: unknown;
28
+ };
29
+ origin: string;
30
+ time_fired: string;
31
+ context: {
32
+ id: string;
33
+ parent_id: string | null;
34
+ user_id: string | null;
35
+ };
36
+ }
37
+ export interface EventSubscription {
38
+ id: string;
39
+ subscriptionId: number;
40
+ eventType?: string;
41
+ domain?: string;
42
+ entityId?: string;
43
+ callback: (event: HaEvent) => void;
44
+ }
45
+ export interface EventSubscriberConfig {
46
+ baseUrl: string;
47
+ token: string;
48
+ reconnectInterval?: number;
49
+ maxReconnectAttempts?: number;
50
+ }
51
+ /**
52
+ * Home Assistant Event Subscriber
53
+ * Subscribes to real-time events via WebSocket
54
+ */
55
+ export declare class EventSubscriber extends EventEmitter {
56
+ private ws;
57
+ private messageId;
58
+ private authenticated;
59
+ private subscriptions;
60
+ private pendingSubscriptions;
61
+ private reconnectAttempts;
62
+ private reconnectTimer;
63
+ private isConnecting;
64
+ private shouldReconnect;
65
+ private readonly config;
66
+ private readonly reconnectInterval;
67
+ private readonly maxReconnectAttempts;
68
+ constructor(config: EventSubscriberConfig);
69
+ /**
70
+ * Connect to Home Assistant WebSocket API
71
+ */
72
+ connect(): Promise<void>;
73
+ /**
74
+ * Handle incoming WebSocket messages
75
+ */
76
+ private handleMessage;
77
+ /**
78
+ * Handle result messages (responses to commands)
79
+ */
80
+ private handleResult;
81
+ /**
82
+ * Handle event messages
83
+ */
84
+ private handleEvent;
85
+ /**
86
+ * Check if an event matches a subscription's filters
87
+ */
88
+ private eventMatchesSubscription;
89
+ /**
90
+ * Handle disconnection and attempt reconnect
91
+ */
92
+ private handleDisconnect;
93
+ /**
94
+ * Subscribe to all events
95
+ */
96
+ subscribeEvents(callback: (event: HaEvent) => void): Promise<string>;
97
+ /**
98
+ * Subscribe to specific event type
99
+ */
100
+ subscribeEventType(eventType: string, callback: (event: HaEvent) => void): Promise<string>;
101
+ /**
102
+ * Subscribe to state changes for a specific domain
103
+ */
104
+ subscribeDomain(domain: string, callback: (event: HaEvent) => void): Promise<string>;
105
+ /**
106
+ * Subscribe to state changes for a specific entity
107
+ */
108
+ subscribeEntity(entityId: string, callback: (event: HaEvent) => void): Promise<string>;
109
+ /**
110
+ * Internal subscribe method
111
+ */
112
+ private subscribe;
113
+ /**
114
+ * Send subscribe_events command
115
+ */
116
+ private sendSubscribeEvents;
117
+ /**
118
+ * Unsubscribe from events
119
+ */
120
+ unsubscribe(subscriptionId: string): Promise<void>;
121
+ /**
122
+ * Send a message over WebSocket
123
+ */
124
+ private sendMessage;
125
+ /**
126
+ * Disconnect from Home Assistant
127
+ */
128
+ disconnect(): void;
129
+ /**
130
+ * Check if connected
131
+ */
132
+ isConnected(): boolean;
133
+ /**
134
+ * Get active subscription count
135
+ */
136
+ getSubscriptionCount(): number;
137
+ }
138
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/haClient/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,344 @@
1
+ /**
2
+ * Home Assistant WebSocket Event Subscription
3
+ * Connects to Home Assistant WebSocket API to receive real-time events
4
+ */
5
+ import { EventEmitter } from 'events';
6
+ import WebSocket from 'ws';
7
+ import { logger } from '../utils/logger.js';
8
+ /**
9
+ * Home Assistant Event Subscriber
10
+ * Subscribes to real-time events via WebSocket
11
+ */
12
+ export class EventSubscriber extends EventEmitter {
13
+ ws = null;
14
+ messageId = 1;
15
+ authenticated = false;
16
+ subscriptions = new Map();
17
+ pendingSubscriptions = [];
18
+ reconnectAttempts = 0;
19
+ reconnectTimer = null;
20
+ isConnecting = false;
21
+ shouldReconnect = true;
22
+ config;
23
+ reconnectInterval;
24
+ maxReconnectAttempts;
25
+ constructor(config) {
26
+ super();
27
+ this.config = config;
28
+ this.reconnectInterval = config.reconnectInterval ?? 5000;
29
+ this.maxReconnectAttempts = config.maxReconnectAttempts ?? 10;
30
+ }
31
+ /**
32
+ * Connect to Home Assistant WebSocket API
33
+ */
34
+ async connect() {
35
+ if (this.ws?.readyState === WebSocket.OPEN) {
36
+ logger.debug('WebSocket already connected');
37
+ return;
38
+ }
39
+ if (this.isConnecting) {
40
+ logger.debug('WebSocket connection already in progress');
41
+ return;
42
+ }
43
+ this.isConnecting = true;
44
+ this.shouldReconnect = true;
45
+ return new Promise((resolve, reject) => {
46
+ try {
47
+ // Convert HTTP URL to WebSocket URL
48
+ const wsUrl = this.config.baseUrl
49
+ .replace(/^http/, 'ws')
50
+ .replace(/\/$/, '') + '/api/websocket';
51
+ logger.info('Connecting to Home Assistant WebSocket', { url: wsUrl });
52
+ this.ws = new WebSocket(wsUrl);
53
+ this.ws.on('open', () => {
54
+ logger.info('WebSocket connection established');
55
+ this.reconnectAttempts = 0;
56
+ });
57
+ this.ws.on('message', (data) => {
58
+ try {
59
+ const message = JSON.parse(data.toString());
60
+ this.handleMessage(message, resolve, reject);
61
+ }
62
+ catch (error) {
63
+ logger.error('Failed to parse WebSocket message', { error });
64
+ }
65
+ });
66
+ this.ws.on('close', (code, reason) => {
67
+ logger.info('WebSocket connection closed', { code, reason: reason.toString() });
68
+ this.authenticated = false;
69
+ this.isConnecting = false;
70
+ this.handleDisconnect();
71
+ });
72
+ this.ws.on('error', (error) => {
73
+ logger.error('WebSocket error', { error: error.message });
74
+ this.isConnecting = false;
75
+ reject(error);
76
+ });
77
+ }
78
+ catch (error) {
79
+ this.isConnecting = false;
80
+ reject(error);
81
+ }
82
+ });
83
+ }
84
+ /**
85
+ * Handle incoming WebSocket messages
86
+ */
87
+ handleMessage(message, resolveConnect, rejectConnect) {
88
+ const type = message.type;
89
+ switch (type) {
90
+ case 'auth_required':
91
+ // Send authentication
92
+ this.sendMessage({
93
+ type: 'auth',
94
+ access_token: this.config.token,
95
+ });
96
+ break;
97
+ case 'auth_ok':
98
+ logger.info('WebSocket authentication successful');
99
+ this.authenticated = true;
100
+ this.isConnecting = false;
101
+ this.emit('connected');
102
+ resolveConnect();
103
+ break;
104
+ case 'auth_invalid':
105
+ logger.error('WebSocket authentication failed', { message: message.message });
106
+ this.isConnecting = false;
107
+ rejectConnect(new Error(`Authentication failed: ${message.message}`));
108
+ break;
109
+ case 'result':
110
+ this.handleResult(message);
111
+ break;
112
+ case 'event':
113
+ this.handleEvent(message);
114
+ break;
115
+ default:
116
+ logger.debug('Unhandled WebSocket message type', { type, message });
117
+ }
118
+ }
119
+ /**
120
+ * Handle result messages (responses to commands)
121
+ */
122
+ handleResult(message) {
123
+ const id = message.id;
124
+ const success = message.success;
125
+ if (this.pendingSubscriptions.length > 0) {
126
+ const pending = this.pendingSubscriptions.shift();
127
+ if (success) {
128
+ pending.resolve(id);
129
+ }
130
+ else {
131
+ const error = message.error;
132
+ pending.reject(new Error(error?.message ?? 'Subscription failed'));
133
+ }
134
+ }
135
+ }
136
+ /**
137
+ * Handle event messages
138
+ */
139
+ handleEvent(message) {
140
+ const event = message.event;
141
+ if (!event)
142
+ return;
143
+ // Emit to all matching subscriptions
144
+ for (const sub of this.subscriptions.values()) {
145
+ if (this.eventMatchesSubscription(event, sub)) {
146
+ try {
147
+ sub.callback(event);
148
+ }
149
+ catch (error) {
150
+ logger.error('Error in event callback', { error, subscriptionId: sub.id });
151
+ }
152
+ }
153
+ }
154
+ // Also emit on the EventEmitter for generic listeners
155
+ this.emit('event', event);
156
+ this.emit(`event:${event.event_type}`, event);
157
+ if (event.data.entity_id) {
158
+ this.emit(`entity:${event.data.entity_id}`, event);
159
+ }
160
+ if (event.data.domain) {
161
+ this.emit(`domain:${event.data.domain}`, event);
162
+ }
163
+ }
164
+ /**
165
+ * Check if an event matches a subscription's filters
166
+ */
167
+ eventMatchesSubscription(event, sub) {
168
+ // Check event type filter
169
+ if (sub.eventType && event.event_type !== sub.eventType) {
170
+ return false;
171
+ }
172
+ // Check domain filter (for state_changed events)
173
+ if (sub.domain && event.event_type === 'state_changed') {
174
+ const entityDomain = event.data.entity_id?.split('.')[0];
175
+ if (entityDomain !== sub.domain) {
176
+ return false;
177
+ }
178
+ }
179
+ // Check entity filter
180
+ if (sub.entityId && event.data.entity_id !== sub.entityId) {
181
+ return false;
182
+ }
183
+ return true;
184
+ }
185
+ /**
186
+ * Handle disconnection and attempt reconnect
187
+ */
188
+ handleDisconnect() {
189
+ if (!this.shouldReconnect) {
190
+ return;
191
+ }
192
+ if (this.reconnectAttempts >= this.maxReconnectAttempts) {
193
+ logger.error('Max reconnect attempts reached, giving up');
194
+ this.emit('disconnected', new Error('Max reconnect attempts reached'));
195
+ return;
196
+ }
197
+ this.reconnectAttempts++;
198
+ const delay = this.reconnectInterval * Math.pow(2, this.reconnectAttempts - 1);
199
+ logger.info('Scheduling reconnect', {
200
+ attempt: this.reconnectAttempts,
201
+ maxAttempts: this.maxReconnectAttempts,
202
+ delayMs: delay,
203
+ });
204
+ this.reconnectTimer = setTimeout(() => {
205
+ this.connect().catch((error) => {
206
+ logger.error('Reconnect failed', { error: error.message });
207
+ });
208
+ }, delay);
209
+ }
210
+ /**
211
+ * Subscribe to all events
212
+ */
213
+ async subscribeEvents(callback) {
214
+ return this.subscribe({
215
+ callback,
216
+ });
217
+ }
218
+ /**
219
+ * Subscribe to specific event type
220
+ */
221
+ async subscribeEventType(eventType, callback) {
222
+ return this.subscribe({
223
+ eventType,
224
+ callback,
225
+ });
226
+ }
227
+ /**
228
+ * Subscribe to state changes for a specific domain
229
+ */
230
+ async subscribeDomain(domain, callback) {
231
+ return this.subscribe({
232
+ eventType: 'state_changed',
233
+ domain,
234
+ callback,
235
+ });
236
+ }
237
+ /**
238
+ * Subscribe to state changes for a specific entity
239
+ */
240
+ async subscribeEntity(entityId, callback) {
241
+ return this.subscribe({
242
+ eventType: 'state_changed',
243
+ entityId,
244
+ callback,
245
+ });
246
+ }
247
+ /**
248
+ * Internal subscribe method
249
+ */
250
+ async subscribe(options) {
251
+ if (!this.authenticated) {
252
+ await this.connect();
253
+ }
254
+ const subscriptionId = await this.sendSubscribeEvents(options.eventType);
255
+ const id = `sub_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
256
+ this.subscriptions.set(id, {
257
+ id,
258
+ subscriptionId,
259
+ eventType: options.eventType,
260
+ domain: options.domain,
261
+ entityId: options.entityId,
262
+ callback: options.callback,
263
+ });
264
+ logger.info('Created event subscription', {
265
+ id,
266
+ eventType: options.eventType,
267
+ domain: options.domain,
268
+ entityId: options.entityId,
269
+ });
270
+ return id;
271
+ }
272
+ /**
273
+ * Send subscribe_events command
274
+ */
275
+ sendSubscribeEvents(eventType) {
276
+ return new Promise((resolve, reject) => {
277
+ this.pendingSubscriptions.push({ resolve, reject });
278
+ const message = {
279
+ id: this.messageId++,
280
+ type: 'subscribe_events',
281
+ };
282
+ if (eventType) {
283
+ message.event_type = eventType;
284
+ }
285
+ this.sendMessage(message);
286
+ });
287
+ }
288
+ /**
289
+ * Unsubscribe from events
290
+ */
291
+ async unsubscribe(subscriptionId) {
292
+ const sub = this.subscriptions.get(subscriptionId);
293
+ if (!sub) {
294
+ return;
295
+ }
296
+ // Send unsubscribe command
297
+ this.sendMessage({
298
+ id: this.messageId++,
299
+ type: 'unsubscribe_events',
300
+ subscription: sub.subscriptionId,
301
+ });
302
+ this.subscriptions.delete(subscriptionId);
303
+ logger.info('Removed event subscription', { id: subscriptionId });
304
+ }
305
+ /**
306
+ * Send a message over WebSocket
307
+ */
308
+ sendMessage(message) {
309
+ if (this.ws?.readyState !== WebSocket.OPEN) {
310
+ throw new Error('WebSocket is not connected');
311
+ }
312
+ this.ws.send(JSON.stringify(message));
313
+ }
314
+ /**
315
+ * Disconnect from Home Assistant
316
+ */
317
+ disconnect() {
318
+ this.shouldReconnect = false;
319
+ if (this.reconnectTimer) {
320
+ clearTimeout(this.reconnectTimer);
321
+ this.reconnectTimer = null;
322
+ }
323
+ if (this.ws) {
324
+ this.ws.close();
325
+ this.ws = null;
326
+ }
327
+ this.authenticated = false;
328
+ this.subscriptions.clear();
329
+ logger.info('Disconnected from Home Assistant WebSocket');
330
+ }
331
+ /**
332
+ * Check if connected
333
+ */
334
+ isConnected() {
335
+ return this.ws?.readyState === WebSocket.OPEN && this.authenticated;
336
+ }
337
+ /**
338
+ * Get active subscription count
339
+ */
340
+ getSubscriptionCount() {
341
+ return this.subscriptions.size;
342
+ }
343
+ }
344
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/haClient/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * History Operations for Home Assistant API
3
+ * Handles historical data and system logs
4
+ */
5
+ import type { Entity, LogbookEntry } from '../types/index.js';
6
+ import type { RequestHandler } from './request.js';
7
+ /**
8
+ * History-related operations for the Home Assistant API.
9
+ */
10
+ export declare class HistoryOperations {
11
+ private readonly request;
12
+ constructor(request: RequestHandler);
13
+ /**
14
+ * Get historical data for an entity
15
+ */
16
+ getHistory(entityId: string, hours?: number): Promise<Entity[][]>;
17
+ /**
18
+ * Get system log entries from the logbook
19
+ * Returns recent events/state changes, optionally filtered by entity
20
+ */
21
+ getSystemLog(options?: {
22
+ hours?: number;
23
+ entity_id?: string;
24
+ }): Promise<LogbookEntry[]>;
25
+ }
26
+ //# sourceMappingURL=history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/haClient/history.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD;;GAEG;AACH,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,cAAc;IAEpD;;OAEG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,GAAE,MAAW,GAAG,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;IAqB3E;;;OAGG;IACG,YAAY,CAAC,OAAO,GAAE;QAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,MAAM,CAAC;KACf,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;CAqBjC"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * History Operations for Home Assistant API
3
+ * Handles historical data and system logs
4
+ */
5
+ import { logger } from '../utils/logger.js';
6
+ /**
7
+ * History-related operations for the Home Assistant API.
8
+ */
9
+ export class HistoryOperations {
10
+ request;
11
+ constructor(request) {
12
+ this.request = request;
13
+ }
14
+ /**
15
+ * Get historical data for an entity
16
+ */
17
+ async getHistory(entityId, hours = 24) {
18
+ logger.debug('Fetching history', { entityId, hours });
19
+ const endTime = new Date();
20
+ const startTime = new Date(endTime.getTime() - hours * 60 * 60 * 1000);
21
+ const path = `/history/period/${startTime.toISOString()}`;
22
+ const history = await this.request.get(path, {
23
+ filter_entity_id: entityId,
24
+ end_time: endTime.toISOString(),
25
+ });
26
+ logger.info('Fetched history', {
27
+ entityId,
28
+ hours,
29
+ records: history[0]?.length ?? 0
30
+ });
31
+ return history;
32
+ }
33
+ /**
34
+ * Get system log entries from the logbook
35
+ * Returns recent events/state changes, optionally filtered by entity
36
+ */
37
+ async getSystemLog(options = {}) {
38
+ const hours = options.hours || 24;
39
+ logger.debug('Fetching system log', { hours, entity_id: options.entity_id });
40
+ const endTime = new Date();
41
+ const startTime = new Date(endTime.getTime() - hours * 60 * 60 * 1000);
42
+ const path = `/logbook/${startTime.toISOString()}`;
43
+ const params = {
44
+ end_time: endTime.toISOString(),
45
+ };
46
+ if (options.entity_id) {
47
+ params.entity = options.entity_id;
48
+ }
49
+ const entries = await this.request.get(path, params);
50
+ logger.info('Fetched system log', { count: entries.length, hours });
51
+ return entries;
52
+ }
53
+ }
54
+ //# sourceMappingURL=history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/haClient/history.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAG5C;;GAEG;AACH,MAAM,OAAO,iBAAiB;IACC;IAA7B,YAA6B,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;IAAG,CAAC;IAExD;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,QAAgB,EAAE;QACnD,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QAEtD,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAEvE,MAAM,IAAI,GAAG,mBAAmB,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QAC1D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAa,IAAI,EAAE;YACvD,gBAAgB,EAAE,QAAQ;YAC1B,QAAQ,EAAE,OAAO,CAAC,WAAW,EAAE;SAChC,CAAC,CAAC;QAEH,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE;YAC7B,QAAQ;YACR,KAAK;YACL,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,IAAI,CAAC;SACjC,CAAC,CAAC;QAEH,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,YAAY,CAAC,UAGf,EAAE;QACJ,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAE7E,MAAM,OAAO,GAAG,IAAI,IAAI,EAAE,CAAC;QAC3B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAEvE,MAAM,IAAI,GAAG,YAAY,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC;QACnD,MAAM,MAAM,GAA2B;YACrC,QAAQ,EAAE,OAAO,CAAC,WAAW,EAAE;SAChC,CAAC;QAEF,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YACtB,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;QACpC,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAiB,IAAI,EAAE,MAAM,CAAC,CAAC;QAErE,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QACpE,OAAO,OAAO,CAAC;IACjB,CAAC;CACF"}