@matter-server/dashboard 0.2.0-alpha.0-00000000-000000000

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 (172) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +11 -0
  3. package/dist/esm/client/client-context.d.ts +10 -0
  4. package/dist/esm/client/client-context.d.ts.map +1 -0
  5. package/dist/esm/client/client-context.js +11 -0
  6. package/dist/esm/client/client-context.js.map +6 -0
  7. package/dist/esm/client/models/descriptions.d.ts +20 -0
  8. package/dist/esm/client/models/descriptions.d.ts.map +1 -0
  9. package/dist/esm/client/models/descriptions.js +10929 -0
  10. package/dist/esm/client/models/descriptions.js.map +6 -0
  11. package/dist/esm/components/dialog-box/dialog-box.d.ts +25 -0
  12. package/dist/esm/components/dialog-box/dialog-box.d.ts.map +1 -0
  13. package/dist/esm/components/dialog-box/dialog-box.js +66 -0
  14. package/dist/esm/components/dialog-box/dialog-box.js.map +6 -0
  15. package/dist/esm/components/dialog-box/show-dialog-box.d.ts +18 -0
  16. package/dist/esm/components/dialog-box/show-dialog-box.d.ts.map +1 -0
  17. package/dist/esm/components/dialog-box/show-dialog-box.js +22 -0
  18. package/dist/esm/components/dialog-box/show-dialog-box.js.map +6 -0
  19. package/dist/esm/components/dialogs/acl/model.d.ts +33 -0
  20. package/dist/esm/components/dialogs/acl/model.d.ts.map +1 -0
  21. package/dist/esm/components/dialogs/acl/model.js +79 -0
  22. package/dist/esm/components/dialogs/acl/model.js.map +6 -0
  23. package/dist/esm/components/dialogs/binding/model.d.ts +20 -0
  24. package/dist/esm/components/dialogs/binding/model.d.ts.map +1 -0
  25. package/dist/esm/components/dialogs/binding/model.js +45 -0
  26. package/dist/esm/components/dialogs/binding/model.js.map +6 -0
  27. package/dist/esm/components/dialogs/binding/node-binding-dialog.d.ts +49 -0
  28. package/dist/esm/components/dialogs/binding/node-binding-dialog.d.ts.map +1 -0
  29. package/dist/esm/components/dialogs/binding/node-binding-dialog.js +357 -0
  30. package/dist/esm/components/dialogs/binding/node-binding-dialog.js.map +6 -0
  31. package/dist/esm/components/dialogs/binding/show-node-binding-dialog.d.ts +8 -0
  32. package/dist/esm/components/dialogs/binding/show-node-binding-dialog.d.ts.map +1 -0
  33. package/dist/esm/components/dialogs/binding/show-node-binding-dialog.js +17 -0
  34. package/dist/esm/components/dialogs/binding/show-node-binding-dialog.js.map +6 -0
  35. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-dialog.d.ts +31 -0
  36. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-dialog.d.ts.map +1 -0
  37. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-dialog.js +94 -0
  38. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-dialog.js.map +6 -0
  39. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-existing.d.ts +17 -0
  40. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-existing.d.ts.map +1 -0
  41. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-existing.js +64 -0
  42. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-existing.js.map +6 -0
  43. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-thread.d.ts +19 -0
  44. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-thread.d.ts.map +1 -0
  45. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-thread.js +91 -0
  46. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-thread.js.map +6 -0
  47. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-wifi.d.ts +20 -0
  48. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-wifi.d.ts.map +1 -0
  49. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-wifi.js +106 -0
  50. package/dist/esm/components/dialogs/commission-node-dialog/commission-node-wifi.js.map +6 -0
  51. package/dist/esm/components/dialogs/commission-node-dialog/show-commission-node-dialog.d.ts +8 -0
  52. package/dist/esm/components/dialogs/commission-node-dialog/show-commission-node-dialog.d.ts.map +1 -0
  53. package/dist/esm/components/dialogs/commission-node-dialog/show-commission-node-dialog.js +15 -0
  54. package/dist/esm/components/dialogs/commission-node-dialog/show-commission-node-dialog.js.map +6 -0
  55. package/dist/esm/components/ha-svg-icon.d.ts +19 -0
  56. package/dist/esm/components/ha-svg-icon.d.ts.map +1 -0
  57. package/dist/esm/components/ha-svg-icon.js +77 -0
  58. package/dist/esm/components/ha-svg-icon.js.map +6 -0
  59. package/dist/esm/entrypoint/main.d.ts +7 -0
  60. package/dist/esm/entrypoint/main.d.ts.map +1 -0
  61. package/dist/esm/entrypoint/main.js +45 -0
  62. package/dist/esm/entrypoint/main.js.map +6 -0
  63. package/dist/esm/package.json +3 -0
  64. package/dist/esm/pages/components/context.d.ts +9 -0
  65. package/dist/esm/pages/components/context.d.ts.map +1 -0
  66. package/dist/esm/pages/components/context.js +11 -0
  67. package/dist/esm/pages/components/context.js.map +6 -0
  68. package/dist/esm/pages/components/footer.d.ts +11 -0
  69. package/dist/esm/pages/components/footer.d.ts.map +1 -0
  70. package/dist/esm/pages/components/footer.js +52 -0
  71. package/dist/esm/pages/components/footer.js.map +6 -0
  72. package/dist/esm/pages/components/header.d.ts +27 -0
  73. package/dist/esm/pages/components/header.d.ts.map +1 -0
  74. package/dist/esm/pages/components/header.js +90 -0
  75. package/dist/esm/pages/components/header.js.map +6 -0
  76. package/dist/esm/pages/components/node-details.d.ts +29 -0
  77. package/dist/esm/pages/components/node-details.d.ts.map +1 -0
  78. package/dist/esm/pages/components/node-details.js +241 -0
  79. package/dist/esm/pages/components/node-details.js.map +6 -0
  80. package/dist/esm/pages/components/server-details.d.ts +24 -0
  81. package/dist/esm/pages/components/server-details.d.ts.map +1 -0
  82. package/dist/esm/pages/components/server-details.js +130 -0
  83. package/dist/esm/pages/components/server-details.js.map +6 -0
  84. package/dist/esm/pages/matter-cluster-view.d.ts +30 -0
  85. package/dist/esm/pages/matter-cluster-view.d.ts.map +1 -0
  86. package/dist/esm/pages/matter-cluster-view.js +154 -0
  87. package/dist/esm/pages/matter-cluster-view.js.map +6 -0
  88. package/dist/esm/pages/matter-dashboard-app.d.ts +27 -0
  89. package/dist/esm/pages/matter-dashboard-app.d.ts.map +1 -0
  90. package/dist/esm/pages/matter-dashboard-app.js +122 -0
  91. package/dist/esm/pages/matter-dashboard-app.js.map +6 -0
  92. package/dist/esm/pages/matter-endpoint-view.d.ts +29 -0
  93. package/dist/esm/pages/matter-endpoint-view.d.ts.map +1 -0
  94. package/dist/esm/pages/matter-endpoint-view.js +149 -0
  95. package/dist/esm/pages/matter-endpoint-view.js.map +6 -0
  96. package/dist/esm/pages/matter-node-view.d.ts +28 -0
  97. package/dist/esm/pages/matter-node-view.d.ts.map +1 -0
  98. package/dist/esm/pages/matter-node-view.js +122 -0
  99. package/dist/esm/pages/matter-node-view.js.map +6 -0
  100. package/dist/esm/pages/matter-server-view.d.ts +31 -0
  101. package/dist/esm/pages/matter-server-view.d.ts.map +1 -0
  102. package/dist/esm/pages/matter-server-view.js +113 -0
  103. package/dist/esm/pages/matter-server-view.js.map +6 -0
  104. package/dist/esm/util/clone_class.d.ts +7 -0
  105. package/dist/esm/util/clone_class.d.ts.map +1 -0
  106. package/dist/esm/util/clone_class.js +10 -0
  107. package/dist/esm/util/clone_class.js.map +6 -0
  108. package/dist/esm/util/fire_event.d.ts +34 -0
  109. package/dist/esm/util/fire_event.d.ts.map +1 -0
  110. package/dist/esm/util/fire_event.js +21 -0
  111. package/dist/esm/util/fire_event.js.map +6 -0
  112. package/dist/esm/util/prevent_default.d.ts +7 -0
  113. package/dist/esm/util/prevent_default.d.ts.map +1 -0
  114. package/dist/esm/util/prevent_default.js +10 -0
  115. package/dist/esm/util/prevent_default.js.map +6 -0
  116. package/dist/esm/util/routing.d.ts +10 -0
  117. package/dist/esm/util/routing.d.ts.map +1 -0
  118. package/dist/esm/util/routing.js +6 -0
  119. package/dist/esm/util/routing.js.map +6 -0
  120. package/dist/web/index.html +40 -0
  121. package/dist/web/js/commission-node-dialog-BJsfA4IV.js +78 -0
  122. package/dist/web/js/commission-node-dialog-DEZ3EqYO.js +78 -0
  123. package/dist/web/js/commission-node-existing-CzRtUgBm.js +50 -0
  124. package/dist/web/js/commission-node-existing-OK1ybPFI.js +50 -0
  125. package/dist/web/js/commission-node-thread-DLmclivF.js +75 -0
  126. package/dist/web/js/commission-node-thread-FcLFz84I.js +75 -0
  127. package/dist/web/js/commission-node-wifi-C8ho-UYb.js +88 -0
  128. package/dist/web/js/commission-node-wifi-C8iGfy7c.js +88 -0
  129. package/dist/web/js/dialog-box-BPz-oO3d.js +52 -0
  130. package/dist/web/js/dialog-box-DN32sjfR.js +52 -0
  131. package/dist/web/js/fire_event-BERTqZpV.js +169 -0
  132. package/dist/web/js/fire_event-BlsbXpOL.js +169 -0
  133. package/dist/web/js/main.js +547 -0
  134. package/dist/web/js/matter-dashboard-app-5UjO1Ik8.js +16068 -0
  135. package/dist/web/js/matter-dashboard-app-BazvuIIi.js +16068 -0
  136. package/dist/web/js/node-binding-dialog-2yitVn0R.js +443 -0
  137. package/dist/web/js/node-binding-dialog-Cw6QEmL3.js +443 -0
  138. package/dist/web/js/outlined-text-field-BMLYwwlc.js +2086 -0
  139. package/dist/web/js/outlined-text-field-Sqd4JHxo.js +2086 -0
  140. package/dist/web/js/prevent_default-BsT53c0u.js +814 -0
  141. package/dist/web/js/prevent_default-D4GG_QeD.js +814 -0
  142. package/package.json +54 -0
  143. package/src/client/client-context.ts +10 -0
  144. package/src/client/models/descriptions.ts +10948 -0
  145. package/src/components/dialog-box/dialog-box.ts +62 -0
  146. package/src/components/dialog-box/show-dialog-box.ts +32 -0
  147. package/src/components/dialogs/acl/model.ts +105 -0
  148. package/src/components/dialogs/binding/model.ts +58 -0
  149. package/src/components/dialogs/binding/node-binding-dialog.ts +419 -0
  150. package/src/components/dialogs/binding/show-node-binding-dialog.ts +16 -0
  151. package/src/components/dialogs/commission-node-dialog/commission-node-dialog.ts +102 -0
  152. package/src/components/dialogs/commission-node-dialog/commission-node-existing.ts +49 -0
  153. package/src/components/dialogs/commission-node-dialog/commission-node-thread.ts +76 -0
  154. package/src/components/dialogs/commission-node-dialog/commission-node-wifi.ts +90 -0
  155. package/src/components/dialogs/commission-node-dialog/show-commission-node-dialog.ts +14 -0
  156. package/src/components/ha-svg-icon.ts +66 -0
  157. package/src/entrypoint/main.ts +60 -0
  158. package/src/pages/components/context.ts +10 -0
  159. package/src/pages/components/footer.ts +39 -0
  160. package/src/pages/components/header.ts +87 -0
  161. package/src/pages/components/node-details.ts +252 -0
  162. package/src/pages/components/server-details.ts +124 -0
  163. package/src/pages/matter-cluster-view.ts +162 -0
  164. package/src/pages/matter-dashboard-app.ts +125 -0
  165. package/src/pages/matter-endpoint-view.ts +152 -0
  166. package/src/pages/matter-node-view.ts +126 -0
  167. package/src/pages/matter-server-view.ts +117 -0
  168. package/src/tsconfig.json +16 -0
  169. package/src/util/clone_class.ts +7 -0
  170. package/src/util/fire_event.ts +83 -0
  171. package/src/util/prevent_default.ts +7 -0
  172. package/src/util/routing.ts +10 -0
@@ -0,0 +1,547 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025-2026 Open Home Foundation
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ const BIGINT_MARKER = "__BIGINT__";
7
+ function toBigIntAwareJson(value, spaces) {
8
+ const replacements = new Array();
9
+ let result = JSON.stringify(value, (_key, val) => {
10
+ if (typeof val === "bigint") {
11
+ if (val > Number.MAX_SAFE_INTEGER) {
12
+ replacements.push({
13
+ from: `"0x${val.toString(16)}"`,
14
+ to: val.toString()
15
+ });
16
+ return `0x${val.toString(16)}`;
17
+ } else {
18
+ return Number(val);
19
+ }
20
+ }
21
+ return val;
22
+ }, spaces);
23
+ if (replacements.length > 0) {
24
+ replacements.forEach(({
25
+ from,
26
+ to
27
+ }) => {
28
+ result = result.replaceAll(from, to);
29
+ });
30
+ }
31
+ return result;
32
+ }
33
+ function parseBigIntAwareJson(json) {
34
+ const processed = json.replace(/([:,[])\s*(\d{15,})(?=[,}\]\s])/g, (match, prefix, number) => {
35
+ const num = BigInt(number);
36
+ if (num > Number.MAX_SAFE_INTEGER) {
37
+ return `${prefix}"${BIGINT_MARKER}${number}"`;
38
+ }
39
+ return match;
40
+ });
41
+ return JSON.parse(processed, (_key, value) => {
42
+ if (typeof value === "string" && value.startsWith(BIGINT_MARKER)) {
43
+ return BigInt(value.slice(BIGINT_MARKER.length));
44
+ }
45
+ return value;
46
+ });
47
+ }
48
+
49
+ /**
50
+ * @license
51
+ * Copyright 2025-2026 Open Home Foundation
52
+ * SPDX-License-Identifier: Apache-2.0
53
+ */
54
+ class Connection {
55
+ /**
56
+ * Create a new connection.
57
+ * @param ws_server_url WebSocket server URL
58
+ * @param wsFactory Optional factory function to create WebSocket instances.
59
+ * If not provided, uses the global WebSocket constructor.
60
+ */
61
+ constructor(ws_server_url, wsFactory) {
62
+ this.ws_server_url = ws_server_url;
63
+ this.ws_server_url = ws_server_url;
64
+ this.wsFactory = wsFactory ?? (url => new WebSocket(url));
65
+ }
66
+ serverInfo = void 0;
67
+ socket;
68
+ wsFactory;
69
+ get connected() {
70
+ var _this$socket;
71
+ return ((_this$socket = this.socket) === null || _this$socket === void 0 ? void 0 : _this$socket.readyState) === 1;
72
+ }
73
+ async connect(onMessage, onConnectionLost) {
74
+ if (this.socket) {
75
+ throw new Error("Already connected");
76
+ }
77
+ console.debug("Trying to connect");
78
+ return new Promise((resolve, reject) => {
79
+ this.socket = this.wsFactory(this.ws_server_url);
80
+ this.socket.onopen = () => {
81
+ console.log("WebSocket Connected");
82
+ };
83
+ this.socket.onclose = () => {
84
+ console.log("WebSocket Closed");
85
+ onConnectionLost();
86
+ };
87
+ this.socket.onerror = error => {
88
+ console.error("WebSocket Error: ", error);
89
+ reject(new Error("WebSocket Error"));
90
+ };
91
+ this.socket.onmessage = event => {
92
+ const dataStr = typeof event.data === "string" ? event.data : String(event.data);
93
+ const data = parseBigIntAwareJson(dataStr);
94
+ console.log("WebSocket OnMessage", data);
95
+ if (!this.serverInfo) {
96
+ this.serverInfo = data;
97
+ resolve();
98
+ return;
99
+ }
100
+ onMessage(data);
101
+ };
102
+ });
103
+ }
104
+ disconnect() {
105
+ if (this.socket) {
106
+ this.socket.close();
107
+ this.socket = void 0;
108
+ }
109
+ }
110
+ sendMessage(message) {
111
+ if (!this.socket) {
112
+ throw new Error("Not connected");
113
+ }
114
+ console.log("WebSocket send message", message);
115
+ this.socket.send(toBigIntAwareJson(message));
116
+ }
117
+ }
118
+
119
+ /**
120
+ * @license
121
+ * Copyright 2025-2026 Open Home Foundation
122
+ * SPDX-License-Identifier: Apache-2.0
123
+ */
124
+ class MatterError extends Error {}
125
+ class InvalidServerVersion extends MatterError {}
126
+
127
+ /**
128
+ * @license
129
+ * Copyright 2025-2026 Open Home Foundation
130
+ * SPDX-License-Identifier: Apache-2.0
131
+ */
132
+ class MatterNode {
133
+ constructor(data) {
134
+ this.data = data;
135
+ this.node_id = data.node_id;
136
+ this.date_commissioned = data.date_commissioned;
137
+ this.last_interview = data.last_interview;
138
+ this.interview_version = data.interview_version;
139
+ this.available = data.available;
140
+ this.is_bridge = data.is_bridge;
141
+ this.attributes = data.attributes;
142
+ this.attribute_subscriptions = data.attribute_subscriptions;
143
+ }
144
+ node_id;
145
+ date_commissioned;
146
+ last_interview;
147
+ interview_version;
148
+ available;
149
+ is_bridge;
150
+ attributes;
151
+ attribute_subscriptions;
152
+ get nodeLabel() {
153
+ const label = this.attributes["0/40/5"];
154
+ if (typeof label !== "string") return "";
155
+ if (label.includes("\0\0")) return "";
156
+ return label.trim();
157
+ }
158
+ get vendorName() {
159
+ const value = this.attributes["0/40/1"];
160
+ return typeof value === "string" ? value : "";
161
+ }
162
+ get productName() {
163
+ const value = this.attributes["0/40/3"];
164
+ return typeof value === "string" ? value : "";
165
+ }
166
+ get serialNumber() {
167
+ const value = this.attributes["0/40/15"];
168
+ return typeof value === "string" ? value : "";
169
+ }
170
+ get updateState() {
171
+ const value = this.attributes["0/42/2"];
172
+ return typeof value === "number" ? value : void 0;
173
+ }
174
+ get updateStateProgress() {
175
+ const value = this.attributes["0/42/3"];
176
+ return typeof value === "number" ? value : void 0;
177
+ }
178
+ update(data) {
179
+ return new MatterNode({
180
+ ...this.data,
181
+ ...data
182
+ });
183
+ }
184
+ }
185
+
186
+ /**
187
+ * @license
188
+ * Copyright 2025-2026 Open Home Foundation
189
+ * SPDX-License-Identifier: Apache-2.0
190
+ */
191
+ function toNodeKey(nodeId) {
192
+ return String(nodeId);
193
+ }
194
+ class MatterClient {
195
+ /**
196
+ * Create a new MatterClient.
197
+ * @param url WebSocket URL to connect to
198
+ * @param wsFactory Optional factory function to create WebSocket instances.
199
+ * For Node.js, pass: (url) => new WebSocket(url) from the 'ws' package.
200
+ * For browser, leave undefined to use native WebSocket.
201
+ */
202
+ constructor(url, wsFactory) {
203
+ this.url = url;
204
+ this.url = url;
205
+ this.connection = new Connection(this.url, wsFactory);
206
+ this.serverBaseAddress = this.url.split("://")[1].split(":")[0] || "";
207
+ }
208
+ connection;
209
+ nodes = {};
210
+ serverBaseAddress;
211
+ /** Whether this client is connected to a production server (optional, for UI purposes) */
212
+ isProduction = false;
213
+ // Using 'unknown' for resolve since the actual types vary by command
214
+ result_futures = {};
215
+ msgId = 0;
216
+ eventListeners = {};
217
+ get serverInfo() {
218
+ return this.connection.serverInfo;
219
+ }
220
+ addEventListener(event, listener) {
221
+ if (!this.eventListeners[event]) {
222
+ this.eventListeners[event] = [];
223
+ }
224
+ this.eventListeners[event].push(listener);
225
+ return () => {
226
+ this.eventListeners[event] = this.eventListeners[event].filter(l => l !== listener);
227
+ };
228
+ }
229
+ async commissionWithCode(code, networkOnly = true) {
230
+ return await this.sendCommand("commission_with_code", 0, {
231
+ code,
232
+ network_only: networkOnly
233
+ });
234
+ }
235
+ async setWifiCredentials(ssid, credentials) {
236
+ await this.sendCommand("set_wifi_credentials", 0, {
237
+ ssid,
238
+ credentials
239
+ });
240
+ }
241
+ async setThreadOperationalDataset(dataset) {
242
+ await this.sendCommand("set_thread_dataset", 0, {
243
+ dataset
244
+ });
245
+ }
246
+ async openCommissioningWindow(nodeId, timeout, iteration, option, discriminator) {
247
+ return await this.sendCommand("open_commissioning_window", 0, {
248
+ node_id: nodeId,
249
+ timeout,
250
+ iteration,
251
+ option,
252
+ discriminator
253
+ });
254
+ }
255
+ async discoverCommissionableNodes() {
256
+ return await this.sendCommand("discover_commissionable_nodes", 0, {});
257
+ }
258
+ async getMatterFabrics(nodeId) {
259
+ return await this.sendCommand("get_matter_fabrics", 3, {
260
+ node_id: nodeId
261
+ });
262
+ }
263
+ async removeMatterFabric(nodeId, fabricIndex) {
264
+ await this.sendCommand("remove_matter_fabric", 3, {
265
+ node_id: nodeId,
266
+ fabric_index: fabricIndex
267
+ });
268
+ }
269
+ async pingNode(nodeId, attempts = 1) {
270
+ return await this.sendCommand("ping_node", 0, {
271
+ node_id: nodeId,
272
+ attempts
273
+ });
274
+ }
275
+ async getNodeIPAddresses(nodeId, preferCache, scoped) {
276
+ return await this.sendCommand("get_node_ip_addresses", 8, {
277
+ node_id: nodeId,
278
+ prefer_cache: preferCache,
279
+ scoped
280
+ });
281
+ }
282
+ async removeNode(nodeId) {
283
+ await this.sendCommand("remove_node", 0, {
284
+ node_id: nodeId
285
+ });
286
+ }
287
+ async interviewNode(nodeId) {
288
+ await this.sendCommand("interview_node", 0, {
289
+ node_id: nodeId
290
+ });
291
+ }
292
+ async importTestNode(dump) {
293
+ await this.sendCommand("import_test_node", 0, {
294
+ dump
295
+ });
296
+ }
297
+ async readAttribute(nodeId, attributePath) {
298
+ return await this.sendCommand("read_attribute", 0, {
299
+ node_id: nodeId,
300
+ attribute_path: attributePath
301
+ });
302
+ }
303
+ async writeAttribute(nodeId, attributePath, value) {
304
+ return await this.sendCommand("write_attribute", 0, {
305
+ node_id: nodeId,
306
+ attribute_path: attributePath,
307
+ value
308
+ });
309
+ }
310
+ async checkNodeUpdate(nodeId) {
311
+ return await this.sendCommand("check_node_update", 10, {
312
+ node_id: nodeId
313
+ });
314
+ }
315
+ async updateNode(nodeId, softwareVersion) {
316
+ await this.sendCommand("update_node", 10, {
317
+ node_id: nodeId,
318
+ software_version: softwareVersion
319
+ });
320
+ }
321
+ async setACLEntry(nodeId, entry) {
322
+ return await this.sendCommand("set_acl_entry", 0, {
323
+ node_id: nodeId,
324
+ entry
325
+ });
326
+ }
327
+ async setNodeBinding(nodeId, endpoint, bindings) {
328
+ return await this.sendCommand("set_node_binding", 0, {
329
+ node_id: nodeId,
330
+ endpoint,
331
+ bindings
332
+ });
333
+ }
334
+ async deviceCommand(nodeId, endpointId, clusterId, commandName, payload = {}) {
335
+ return await this.sendCommand("device_command", 0, {
336
+ node_id: nodeId,
337
+ endpoint_id: endpointId,
338
+ cluster_id: clusterId,
339
+ command_name: commandName,
340
+ payload,
341
+ response_type: null
342
+ });
343
+ }
344
+ async getNodes(onlyAvailable = false) {
345
+ return await this.sendCommand("get_nodes", 0, {
346
+ only_available: onlyAvailable
347
+ });
348
+ }
349
+ async getNode(nodeId) {
350
+ return await this.sendCommand("get_node", 0, {
351
+ node_id: nodeId
352
+ });
353
+ }
354
+ async getVendorNames(filterVendors) {
355
+ return await this.sendCommand("get_vendor_names", 0, {
356
+ filter_vendors: filterVendors
357
+ });
358
+ }
359
+ async fetchServerInfo() {
360
+ return await this.sendCommand("server_info", 0, {});
361
+ }
362
+ async setDefaultFabricLabel(label) {
363
+ await this.sendCommand("set_default_fabric_label", 0, {
364
+ label
365
+ });
366
+ }
367
+ sendCommand(command, require_schema = void 0, args) {
368
+ if (require_schema && this.serverInfo.schema_version < require_schema) {
369
+ throw new InvalidServerVersion(`Command not available due to incompatible server version. Update the Matter Server to a version that supports at least api schema ${require_schema}.`);
370
+ }
371
+ const messageId = ++this.msgId;
372
+ const message = {
373
+ message_id: messageId.toString(),
374
+ command,
375
+ args
376
+ };
377
+ const messagePromise = new Promise((resolve, reject) => {
378
+ this.result_futures[messageId] = {
379
+ resolve,
380
+ reject
381
+ };
382
+ this.connection.sendMessage(message);
383
+ });
384
+ return messagePromise.finally(() => {
385
+ delete this.result_futures[messageId];
386
+ });
387
+ }
388
+ async connect() {
389
+ if (this.connection.connected) {
390
+ return;
391
+ }
392
+ await this.connection.connect(msg => this._handleIncomingMessage(msg), () => this.fireEvent("connection_lost"));
393
+ }
394
+ disconnect(clearStorage = false) {
395
+ if (this.connection && this.connection.connected) {
396
+ this.connection.disconnect();
397
+ }
398
+ if (clearStorage && typeof localStorage !== "undefined") {
399
+ localStorage.removeItem("matterURL");
400
+ location.reload();
401
+ }
402
+ }
403
+ async startListening() {
404
+ await this.connect();
405
+ const nodesArray = await this.sendCommand("start_listening", 0, {});
406
+ const nodes = {};
407
+ for (const node of nodesArray) {
408
+ nodes[toNodeKey(node.node_id)] = new MatterNode(node);
409
+ }
410
+ this.nodes = nodes;
411
+ }
412
+ _handleIncomingMessage(msg) {
413
+ if ("event" in msg) {
414
+ this._handleEventMessage(msg);
415
+ return;
416
+ }
417
+ if ("error_code" in msg) {
418
+ const promise = this.result_futures[msg.message_id];
419
+ if (promise) {
420
+ promise.reject(new Error(msg.details));
421
+ delete this.result_futures[msg.message_id];
422
+ }
423
+ return;
424
+ }
425
+ if ("result" in msg) {
426
+ const promise = this.result_futures[msg.message_id];
427
+ if (promise) {
428
+ promise.resolve(msg.result);
429
+ delete this.result_futures[msg.message_id];
430
+ }
431
+ return;
432
+ }
433
+ console.warn("Received message with unknown format", msg);
434
+ }
435
+ _handleEventMessage(event) {
436
+ console.log("Incoming event", event);
437
+ this.onRawEvent(event);
438
+ if (event.event === "node_added") {
439
+ const node = new MatterNode(event.data);
440
+ this.nodes = {
441
+ ...this.nodes,
442
+ [toNodeKey(node.node_id)]: node
443
+ };
444
+ this.fireEvent("nodes_changed");
445
+ return;
446
+ }
447
+ if (event.event === "node_removed") {
448
+ delete this.nodes[toNodeKey(event.data)];
449
+ this.nodes = {
450
+ ...this.nodes
451
+ };
452
+ this.fireEvent("nodes_changed");
453
+ return;
454
+ }
455
+ if (event.event === "node_updated") {
456
+ const node = new MatterNode(event.data);
457
+ this.nodes = {
458
+ ...this.nodes,
459
+ [toNodeKey(node.node_id)]: node
460
+ };
461
+ this.fireEvent("nodes_changed");
462
+ return;
463
+ }
464
+ if (event.event === "attribute_updated") {
465
+ const [nodeId, attributeKey, attributeValue] = event.data;
466
+ const nodeKey = toNodeKey(nodeId);
467
+ const existingNode = this.nodes[nodeKey];
468
+ if (existingNode) {
469
+ const node = new MatterNode(existingNode.data);
470
+ node.attributes[attributeKey] = attributeValue;
471
+ this.nodes = {
472
+ ...this.nodes,
473
+ [nodeKey]: node
474
+ };
475
+ this.fireEvent("nodes_changed");
476
+ }
477
+ return;
478
+ }
479
+ if (event.event === "server_info_updated") {
480
+ this.connection.serverInfo = event.data;
481
+ this.fireEvent("server_info_updated");
482
+ return;
483
+ }
484
+ if (event.event === "server_shutdown") {
485
+ this.fireEvent("server_shutdown");
486
+ this.disconnect();
487
+ return;
488
+ }
489
+ }
490
+ fireEvent(event) {
491
+ const listeners = this.eventListeners[event];
492
+ if (listeners) {
493
+ for (const listener of listeners) {
494
+ listener();
495
+ }
496
+ }
497
+ }
498
+ /**
499
+ * Hook for subclasses to receive raw events.
500
+ * Override this method to intercept all incoming events.
501
+ * @param event The raw event message
502
+ */
503
+ onRawEvent(_event) {}
504
+ }
505
+
506
+ /**
507
+ * @license
508
+ * Copyright 2025-2026 Open Home Foundation
509
+ * SPDX-License-Identifier: Apache-2.0
510
+ */
511
+ async function main() {
512
+ import('./matter-dashboard-app-5UjO1Ik8.js').then(function (n) { return n.s; });
513
+ let url = "";
514
+ const isProductionServer = location.origin.includes(":5580") || location.href.includes("hassio_ingress") || location.href.includes("/api/ingress/");
515
+ if (!isProductionServer) {
516
+ let storageUrl = localStorage.getItem("matterURL");
517
+ if (!storageUrl) {
518
+ const urlParams = new URLSearchParams(window.location.search);
519
+ const suggestedUrl = urlParams.get("url");
520
+ storageUrl = prompt("Enter Websocket URL to a running Matter Server", suggestedUrl || "ws://localhost:5580/ws");
521
+ if (!storageUrl) {
522
+ alert("Unable to connect without URL");
523
+ return;
524
+ }
525
+ if (suggestedUrl) {
526
+ history.pushState({}, "", window.location.pathname);
527
+ }
528
+ localStorage.setItem("matterURL", storageUrl);
529
+ }
530
+ url = storageUrl;
531
+ } else {
532
+ let baseUrl = window.location.origin + window.location.pathname;
533
+ if (baseUrl.endsWith("/")) {
534
+ baseUrl = baseUrl.slice(0, -1);
535
+ }
536
+ url = baseUrl.replace("http", "ws") + "/ws";
537
+ console.log(`Connecting to Matter Server API using url: ${url}`);
538
+ }
539
+ const client = new MatterClient(url);
540
+ client.isProduction = isProductionServer;
541
+ const dashboard = document.createElement("matter-dashboard-app");
542
+ dashboard.client = client;
543
+ document.body.append(dashboard);
544
+ }
545
+ main();
546
+
547
+ export { toBigIntAwareJson as t };