@matter-server/dashboard 0.2.7-alpha.0-20260118-45c7af0 → 0.2.7-alpha.0-20260119-49e7237
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/dist/esm/components/dialogs/binding/node-binding-dialog.d.ts.map +1 -1
- package/dist/esm/components/dialogs/binding/node-binding-dialog.js +3 -2
- package/dist/esm/components/dialogs/binding/node-binding-dialog.js.map +1 -1
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-existing.d.ts.map +1 -1
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-existing.js +2 -1
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-existing.js.map +1 -1
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-thread.d.ts.map +1 -1
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-thread.js +3 -2
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-thread.js.map +1 -1
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-wifi.d.ts.map +1 -1
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-wifi.js +5 -4
- package/dist/esm/components/dialogs/commission-node-dialog/commission-node-wifi.js.map +1 -1
- package/dist/esm/components/dialogs/settings/log-level-dialog.d.ts.map +1 -1
- package/dist/esm/components/dialogs/settings/log-level-dialog.js +6 -2
- package/dist/esm/components/dialogs/settings/log-level-dialog.js.map +1 -1
- package/dist/esm/pages/cluster-commands/clusters/level-control-commands.d.ts.map +1 -1
- package/dist/esm/pages/cluster-commands/clusters/level-control-commands.js +5 -2
- package/dist/esm/pages/cluster-commands/clusters/level-control-commands.js.map +1 -1
- package/dist/esm/pages/cluster-commands/clusters/on-off-commands.d.ts.map +1 -1
- package/dist/esm/pages/cluster-commands/clusters/on-off-commands.js +6 -3
- package/dist/esm/pages/cluster-commands/clusters/on-off-commands.js.map +1 -1
- package/dist/esm/pages/components/node-details.d.ts.map +1 -1
- package/dist/esm/pages/components/node-details.js +6 -5
- package/dist/esm/pages/components/node-details.js.map +1 -1
- package/dist/esm/pages/components/server-details.d.ts.map +1 -1
- package/dist/esm/pages/components/server-details.js +3 -2
- package/dist/esm/pages/components/server-details.js.map +1 -1
- package/dist/esm/pages/matter-server-view.d.ts.map +1 -1
- package/dist/esm/pages/matter-server-view.js +14 -1
- package/dist/esm/pages/matter-server-view.js.map +1 -1
- package/dist/esm/util/async-handler.d.ts +50 -0
- package/dist/esm/util/async-handler.d.ts.map +1 -0
- package/dist/esm/util/async-handler.js +33 -0
- package/dist/esm/util/async-handler.js.map +6 -0
- package/dist/esm/util/fire_event.d.ts.map +1 -1
- package/dist/esm/util/fire_event.js +1 -2
- package/dist/esm/util/fire_event.js.map +1 -1
- package/dist/esm/util/format_hex.d.ts +13 -2
- package/dist/esm/util/format_hex.d.ts.map +1 -1
- package/dist/esm/util/format_hex.js +6 -1
- package/dist/esm/util/format_hex.js.map +1 -1
- package/dist/web/js/{commission-node-dialog-CoaDIV2Y.js → commission-node-dialog-B4_wgFye.js} +5 -5
- package/dist/web/js/{commission-node-existing-DEU_mJjO.js → commission-node-existing-BktL7vHX.js} +6 -6
- package/dist/web/js/{commission-node-thread-DZ6DghSs.js → commission-node-thread-ox6fB3dO.js} +7 -7
- package/dist/web/js/{commission-node-wifi-DOyin0q3.js → commission-node-wifi-Dlayi41Z.js} +9 -9
- package/dist/web/js/{dialog-box-B5sunUPv.js → dialog-box-DFs0hcPv.js} +2 -2
- package/dist/web/js/{fire_event-C9Duc1j-.js → fire_event-oVtV3_P5.js} +2 -3
- package/dist/web/js/{log-level-dialog-B7LsZYUL.js → log-level-dialog-BVxKJJ49.js} +8 -5
- package/dist/web/js/main.js +151 -73
- package/dist/web/js/{matter-dashboard-app-DlHSE_Qh.js → matter-dashboard-app-Dr-IYMsD.js} +62 -17
- package/dist/web/js/{node-binding-dialog-BifZsigR.js → node-binding-dialog-CqE3VuZN.js} +6 -6
- package/dist/web/js/{outlined-text-field-D2BOt1yD.js → outlined-text-field-BVcHUxiS.js} +3 -3
- package/dist/web/js/{prevent_default-CuW2EnKR.js → prevent_default-tLhqZmsK.js} +1 -1
- package/dist/web/js/{validator-MOJiFndw.js → validator-muF28wYx.js} +1 -1
- package/package.json +3 -3
- package/src/components/dialogs/binding/node-binding-dialog.ts +3 -2
- package/src/components/dialogs/commission-node-dialog/commission-node-existing.ts +2 -1
- package/src/components/dialogs/commission-node-dialog/commission-node-thread.ts +3 -2
- package/src/components/dialogs/commission-node-dialog/commission-node-wifi.ts +5 -4
- package/src/components/dialogs/settings/log-level-dialog.ts +6 -2
- package/src/pages/cluster-commands/clusters/level-control-commands.ts +5 -2
- package/src/pages/cluster-commands/clusters/on-off-commands.ts +6 -3
- package/src/pages/components/node-details.ts +6 -5
- package/src/pages/components/server-details.ts +3 -3
- package/src/pages/matter-server-view.ts +17 -2
- package/src/util/async-handler.ts +74 -0
- package/src/util/fire_event.ts +1 -3
- package/src/util/format_hex.ts +17 -2
package/dist/web/js/main.js
CHANGED
|
@@ -190,6 +190,20 @@ class Connection {
|
|
|
190
190
|
*/
|
|
191
191
|
class MatterError extends Error {}
|
|
192
192
|
class InvalidServerVersion extends MatterError {}
|
|
193
|
+
class CommandTimeoutError extends MatterError {
|
|
194
|
+
constructor(command, timeoutMs) {
|
|
195
|
+
super(`Command '${command}' timed out after ${timeoutMs}ms`);
|
|
196
|
+
this.command = command;
|
|
197
|
+
this.timeoutMs = timeoutMs;
|
|
198
|
+
this.name = "CommandTimeoutError";
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
class ConnectionClosedError extends MatterError {
|
|
202
|
+
constructor(message = "Connection closed while command was pending") {
|
|
203
|
+
super(message);
|
|
204
|
+
this.name = "ConnectionClosedError";
|
|
205
|
+
}
|
|
206
|
+
}
|
|
193
207
|
|
|
194
208
|
/**
|
|
195
209
|
* @license
|
|
@@ -258,6 +272,7 @@ class MatterNode {
|
|
|
258
272
|
function toNodeKey(nodeId) {
|
|
259
273
|
return String(nodeId);
|
|
260
274
|
}
|
|
275
|
+
const DEFAULT_COMMAND_TIMEOUT = 5 * 60 * 1e3;
|
|
261
276
|
class MatterClient {
|
|
262
277
|
/**
|
|
263
278
|
* Create a new MatterClient.
|
|
@@ -277,9 +292,12 @@ class MatterClient {
|
|
|
277
292
|
serverBaseAddress;
|
|
278
293
|
/** Whether this client is connected to a production server (optional, for UI purposes) */
|
|
279
294
|
isProduction = false;
|
|
295
|
+
/** Default timeout for commands in milliseconds. Set to 0 to disable timeouts. */
|
|
296
|
+
commandTimeout = DEFAULT_COMMAND_TIMEOUT;
|
|
280
297
|
// Using 'unknown' for resolve since the actual types vary by command
|
|
281
298
|
result_futures = {};
|
|
282
|
-
|
|
299
|
+
// Start with random offset for defense-in-depth and easier debugging across sessions
|
|
300
|
+
msgId = Math.floor(Math.random() * 2147483647);
|
|
283
301
|
eventListeners = {};
|
|
284
302
|
get serverInfo() {
|
|
285
303
|
return this.connection.serverInfo;
|
|
@@ -293,112 +311,112 @@ class MatterClient {
|
|
|
293
311
|
this.eventListeners[event] = this.eventListeners[event].filter(l => l !== listener);
|
|
294
312
|
};
|
|
295
313
|
}
|
|
296
|
-
async commissionWithCode(code, networkOnly = true) {
|
|
314
|
+
async commissionWithCode(code, networkOnly = true, timeout) {
|
|
297
315
|
return await this.sendCommand("commission_with_code", 0, {
|
|
298
316
|
code,
|
|
299
317
|
network_only: networkOnly
|
|
300
|
-
});
|
|
318
|
+
}, timeout);
|
|
301
319
|
}
|
|
302
|
-
async setWifiCredentials(ssid, credentials) {
|
|
320
|
+
async setWifiCredentials(ssid, credentials, timeout) {
|
|
303
321
|
await this.sendCommand("set_wifi_credentials", 0, {
|
|
304
322
|
ssid,
|
|
305
323
|
credentials
|
|
306
|
-
});
|
|
324
|
+
}, timeout);
|
|
307
325
|
}
|
|
308
|
-
async setThreadOperationalDataset(dataset) {
|
|
326
|
+
async setThreadOperationalDataset(dataset, timeout) {
|
|
309
327
|
await this.sendCommand("set_thread_dataset", 0, {
|
|
310
328
|
dataset
|
|
311
|
-
});
|
|
329
|
+
}, timeout);
|
|
312
330
|
}
|
|
313
|
-
async openCommissioningWindow(nodeId,
|
|
331
|
+
async openCommissioningWindow(nodeId, windowTimeout, iteration, option, discriminator, timeout) {
|
|
314
332
|
return await this.sendCommand("open_commissioning_window", 0, {
|
|
315
333
|
node_id: nodeId,
|
|
316
|
-
timeout,
|
|
334
|
+
timeout: windowTimeout,
|
|
317
335
|
iteration,
|
|
318
336
|
option,
|
|
319
337
|
discriminator
|
|
320
|
-
});
|
|
338
|
+
}, timeout);
|
|
321
339
|
}
|
|
322
|
-
async discoverCommissionableNodes() {
|
|
323
|
-
return await this.sendCommand("discover_commissionable_nodes", 0, {});
|
|
340
|
+
async discoverCommissionableNodes(timeout) {
|
|
341
|
+
return await this.sendCommand("discover_commissionable_nodes", 0, {}, timeout);
|
|
324
342
|
}
|
|
325
|
-
async getMatterFabrics(nodeId) {
|
|
343
|
+
async getMatterFabrics(nodeId, timeout) {
|
|
326
344
|
return await this.sendCommand("get_matter_fabrics", 3, {
|
|
327
345
|
node_id: nodeId
|
|
328
|
-
});
|
|
346
|
+
}, timeout);
|
|
329
347
|
}
|
|
330
|
-
async removeMatterFabric(nodeId, fabricIndex) {
|
|
348
|
+
async removeMatterFabric(nodeId, fabricIndex, timeout) {
|
|
331
349
|
await this.sendCommand("remove_matter_fabric", 3, {
|
|
332
350
|
node_id: nodeId,
|
|
333
351
|
fabric_index: fabricIndex
|
|
334
|
-
});
|
|
352
|
+
}, timeout);
|
|
335
353
|
}
|
|
336
|
-
async pingNode(nodeId, attempts = 1) {
|
|
354
|
+
async pingNode(nodeId, attempts = 1, timeout) {
|
|
337
355
|
return await this.sendCommand("ping_node", 0, {
|
|
338
356
|
node_id: nodeId,
|
|
339
357
|
attempts
|
|
340
|
-
});
|
|
358
|
+
}, timeout);
|
|
341
359
|
}
|
|
342
|
-
async getNodeIPAddresses(nodeId, preferCache, scoped) {
|
|
360
|
+
async getNodeIPAddresses(nodeId, preferCache, scoped, timeout) {
|
|
343
361
|
return await this.sendCommand("get_node_ip_addresses", 8, {
|
|
344
362
|
node_id: nodeId,
|
|
345
363
|
prefer_cache: preferCache,
|
|
346
364
|
scoped
|
|
347
|
-
});
|
|
365
|
+
}, timeout);
|
|
348
366
|
}
|
|
349
|
-
async removeNode(nodeId) {
|
|
367
|
+
async removeNode(nodeId, timeout) {
|
|
350
368
|
await this.sendCommand("remove_node", 0, {
|
|
351
369
|
node_id: nodeId
|
|
352
|
-
});
|
|
370
|
+
}, timeout);
|
|
353
371
|
}
|
|
354
|
-
async interviewNode(nodeId) {
|
|
372
|
+
async interviewNode(nodeId, timeout) {
|
|
355
373
|
await this.sendCommand("interview_node", 0, {
|
|
356
374
|
node_id: nodeId
|
|
357
|
-
});
|
|
375
|
+
}, timeout);
|
|
358
376
|
}
|
|
359
|
-
async importTestNode(dump) {
|
|
377
|
+
async importTestNode(dump, timeout) {
|
|
360
378
|
await this.sendCommand("import_test_node", 0, {
|
|
361
379
|
dump
|
|
362
|
-
});
|
|
380
|
+
}, timeout);
|
|
363
381
|
}
|
|
364
|
-
async readAttribute(nodeId, attributePath) {
|
|
382
|
+
async readAttribute(nodeId, attributePath, timeout) {
|
|
365
383
|
return await this.sendCommand("read_attribute", 0, {
|
|
366
384
|
node_id: nodeId,
|
|
367
385
|
attribute_path: attributePath
|
|
368
|
-
});
|
|
386
|
+
}, timeout);
|
|
369
387
|
}
|
|
370
|
-
async writeAttribute(nodeId, attributePath, value) {
|
|
388
|
+
async writeAttribute(nodeId, attributePath, value, timeout) {
|
|
371
389
|
return await this.sendCommand("write_attribute", 0, {
|
|
372
390
|
node_id: nodeId,
|
|
373
391
|
attribute_path: attributePath,
|
|
374
392
|
value
|
|
375
|
-
});
|
|
393
|
+
}, timeout);
|
|
376
394
|
}
|
|
377
|
-
async checkNodeUpdate(nodeId) {
|
|
395
|
+
async checkNodeUpdate(nodeId, timeout) {
|
|
378
396
|
return await this.sendCommand("check_node_update", 10, {
|
|
379
397
|
node_id: nodeId
|
|
380
|
-
});
|
|
398
|
+
}, timeout);
|
|
381
399
|
}
|
|
382
|
-
async updateNode(nodeId, softwareVersion) {
|
|
400
|
+
async updateNode(nodeId, softwareVersion, timeout) {
|
|
383
401
|
await this.sendCommand("update_node", 10, {
|
|
384
402
|
node_id: nodeId,
|
|
385
403
|
software_version: softwareVersion
|
|
386
|
-
});
|
|
404
|
+
}, timeout);
|
|
387
405
|
}
|
|
388
|
-
async setACLEntry(nodeId, entry) {
|
|
406
|
+
async setACLEntry(nodeId, entry, timeout) {
|
|
389
407
|
return await this.sendCommand("set_acl_entry", 0, {
|
|
390
408
|
node_id: nodeId,
|
|
391
409
|
entry
|
|
392
|
-
});
|
|
410
|
+
}, timeout);
|
|
393
411
|
}
|
|
394
|
-
async setNodeBinding(nodeId, endpoint, bindings) {
|
|
412
|
+
async setNodeBinding(nodeId, endpoint, bindings, timeout) {
|
|
395
413
|
return await this.sendCommand("set_node_binding", 0, {
|
|
396
414
|
node_id: nodeId,
|
|
397
415
|
endpoint,
|
|
398
416
|
bindings
|
|
399
|
-
});
|
|
417
|
+
}, timeout);
|
|
400
418
|
}
|
|
401
|
-
async deviceCommand(nodeId, endpointId, clusterId, commandName, payload = {}) {
|
|
419
|
+
async deviceCommand(nodeId, endpointId, clusterId, commandName, payload = {}, timeout) {
|
|
402
420
|
return await this.sendCommand("device_command", 0, {
|
|
403
421
|
node_id: nodeId,
|
|
404
422
|
endpoint_id: endpointId,
|
|
@@ -406,79 +424,147 @@ class MatterClient {
|
|
|
406
424
|
command_name: commandName,
|
|
407
425
|
payload,
|
|
408
426
|
response_type: null
|
|
409
|
-
});
|
|
427
|
+
}, timeout);
|
|
410
428
|
}
|
|
411
|
-
async getNodes(onlyAvailable = false) {
|
|
429
|
+
async getNodes(onlyAvailable = false, timeout) {
|
|
412
430
|
return await this.sendCommand("get_nodes", 0, {
|
|
413
431
|
only_available: onlyAvailable
|
|
414
|
-
});
|
|
432
|
+
}, timeout);
|
|
415
433
|
}
|
|
416
|
-
async getNode(nodeId) {
|
|
434
|
+
async getNode(nodeId, timeout) {
|
|
417
435
|
return await this.sendCommand("get_node", 0, {
|
|
418
436
|
node_id: nodeId
|
|
419
|
-
});
|
|
437
|
+
}, timeout);
|
|
420
438
|
}
|
|
421
|
-
async getVendorNames(filterVendors) {
|
|
439
|
+
async getVendorNames(filterVendors, timeout) {
|
|
422
440
|
return await this.sendCommand("get_vendor_names", 0, {
|
|
423
441
|
filter_vendors: filterVendors
|
|
424
|
-
});
|
|
442
|
+
}, timeout);
|
|
425
443
|
}
|
|
426
|
-
async fetchServerInfo() {
|
|
427
|
-
return await this.sendCommand("server_info", 0, {});
|
|
444
|
+
async fetchServerInfo(timeout) {
|
|
445
|
+
return await this.sendCommand("server_info", 0, {}, timeout);
|
|
428
446
|
}
|
|
429
|
-
async setDefaultFabricLabel(label) {
|
|
447
|
+
async setDefaultFabricLabel(label, timeout) {
|
|
430
448
|
await this.sendCommand("set_default_fabric_label", 0, {
|
|
431
449
|
label
|
|
432
|
-
});
|
|
450
|
+
}, timeout);
|
|
433
451
|
}
|
|
434
452
|
/**
|
|
435
453
|
* Get the current log levels for console and file logging.
|
|
454
|
+
* @param timeout Optional command timeout in milliseconds
|
|
436
455
|
* @returns The current log level configuration
|
|
437
456
|
*/
|
|
438
|
-
async getLogLevel() {
|
|
439
|
-
return await this.sendCommand("get_loglevel", 0, {});
|
|
457
|
+
async getLogLevel(timeout) {
|
|
458
|
+
return await this.sendCommand("get_loglevel", 0, {}, timeout);
|
|
440
459
|
}
|
|
441
460
|
/**
|
|
442
461
|
* Set the log level for console and/or file logging.
|
|
443
462
|
* Changes are temporary and will be reset when the server restarts.
|
|
444
463
|
* @param consoleLoglevel Console log level to set (optional)
|
|
445
464
|
* @param fileLoglevel File log level to set, only applied if file logging is enabled (optional)
|
|
465
|
+
* @param timeout Optional command timeout in milliseconds
|
|
446
466
|
* @returns The log level configuration after the change
|
|
447
467
|
*/
|
|
448
|
-
async setLogLevel(consoleLoglevel, fileLoglevel) {
|
|
468
|
+
async setLogLevel(consoleLoglevel, fileLoglevel, timeout) {
|
|
449
469
|
return await this.sendCommand("set_loglevel", 0, {
|
|
450
470
|
console_loglevel: consoleLoglevel,
|
|
451
471
|
file_loglevel: fileLoglevel
|
|
452
|
-
});
|
|
472
|
+
}, timeout);
|
|
453
473
|
}
|
|
454
|
-
|
|
474
|
+
/**
|
|
475
|
+
* Send a command to the Matter server.
|
|
476
|
+
* @param command The command name
|
|
477
|
+
* @param require_schema Minimum schema version required (0 for any version)
|
|
478
|
+
* @param args Command arguments
|
|
479
|
+
* @param timeout Optional timeout in milliseconds. Defaults to `commandTimeout`. Set to 0 to disable.
|
|
480
|
+
* @returns Promise that resolves with the command result
|
|
481
|
+
* @throws Error if the command times out or fails
|
|
482
|
+
*/
|
|
483
|
+
sendCommand(command, require_schema = void 0, args, timeout = this.commandTimeout) {
|
|
455
484
|
if (require_schema && this.serverInfo.schema_version < require_schema) {
|
|
456
485
|
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}.`);
|
|
457
486
|
}
|
|
458
|
-
|
|
487
|
+
if (this.msgId >= Number.MAX_SAFE_INTEGER) {
|
|
488
|
+
this.msgId = 0;
|
|
489
|
+
}
|
|
490
|
+
const messageId = String(++this.msgId);
|
|
459
491
|
const message = {
|
|
460
|
-
message_id: messageId
|
|
492
|
+
message_id: messageId,
|
|
461
493
|
command,
|
|
462
494
|
args
|
|
463
495
|
};
|
|
464
|
-
|
|
496
|
+
return new Promise((resolve, reject) => {
|
|
497
|
+
let timeoutId;
|
|
498
|
+
if (timeout > 0) {
|
|
499
|
+
timeoutId = setTimeout(() => {
|
|
500
|
+
const pending = this.result_futures[messageId];
|
|
501
|
+
if (pending) {
|
|
502
|
+
if (pending.timeoutId) {
|
|
503
|
+
clearTimeout(pending.timeoutId);
|
|
504
|
+
}
|
|
505
|
+
delete this.result_futures[messageId];
|
|
506
|
+
reject(new CommandTimeoutError(command, timeout));
|
|
507
|
+
}
|
|
508
|
+
}, timeout);
|
|
509
|
+
}
|
|
465
510
|
this.result_futures[messageId] = {
|
|
466
511
|
resolve,
|
|
467
|
-
reject
|
|
512
|
+
reject,
|
|
513
|
+
timeoutId
|
|
468
514
|
};
|
|
469
515
|
this.connection.sendMessage(message);
|
|
470
516
|
});
|
|
471
|
-
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Safely resolve a pending command, ensuring it's only resolved once.
|
|
520
|
+
* Clears timeout and removes from pending futures before resolving.
|
|
521
|
+
*/
|
|
522
|
+
_resolvePendingCommand(messageId, result) {
|
|
523
|
+
const pending = this.result_futures[messageId];
|
|
524
|
+
if (pending) {
|
|
525
|
+
if (pending.timeoutId) {
|
|
526
|
+
clearTimeout(pending.timeoutId);
|
|
527
|
+
}
|
|
472
528
|
delete this.result_futures[messageId];
|
|
473
|
-
|
|
529
|
+
pending.resolve(result);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Safely reject a pending command, ensuring it's only rejected once.
|
|
534
|
+
* Clears timeout and removes from pending futures before rejecting.
|
|
535
|
+
*/
|
|
536
|
+
_rejectPendingCommand(messageId, error) {
|
|
537
|
+
const pending = this.result_futures[messageId];
|
|
538
|
+
if (pending) {
|
|
539
|
+
if (pending.timeoutId) {
|
|
540
|
+
clearTimeout(pending.timeoutId);
|
|
541
|
+
}
|
|
542
|
+
delete this.result_futures[messageId];
|
|
543
|
+
pending.reject(error);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
/**
|
|
547
|
+
* Reject all pending commands with a ConnectionClosedError.
|
|
548
|
+
* Called when the connection is closed or lost.
|
|
549
|
+
*/
|
|
550
|
+
_rejectAllPendingCommands() {
|
|
551
|
+
const error = new ConnectionClosedError();
|
|
552
|
+
const pendingIds = Object.keys(this.result_futures);
|
|
553
|
+
for (const messageId of pendingIds) {
|
|
554
|
+
this._rejectPendingCommand(messageId, error);
|
|
555
|
+
}
|
|
474
556
|
}
|
|
475
557
|
async connect() {
|
|
476
558
|
if (this.connection.connected) {
|
|
477
559
|
return;
|
|
478
560
|
}
|
|
479
|
-
await this.connection.connect(msg => this._handleIncomingMessage(msg), () =>
|
|
561
|
+
await this.connection.connect(msg => this._handleIncomingMessage(msg), () => {
|
|
562
|
+
this._rejectAllPendingCommands();
|
|
563
|
+
this.fireEvent("connection_lost");
|
|
564
|
+
});
|
|
480
565
|
}
|
|
481
566
|
disconnect(clearStorage = false) {
|
|
567
|
+
this._rejectAllPendingCommands();
|
|
482
568
|
if (this.connection && this.connection.connected) {
|
|
483
569
|
this.connection.disconnect();
|
|
484
570
|
}
|
|
@@ -502,19 +588,11 @@ class MatterClient {
|
|
|
502
588
|
return;
|
|
503
589
|
}
|
|
504
590
|
if ("error_code" in msg) {
|
|
505
|
-
|
|
506
|
-
if (promise) {
|
|
507
|
-
promise.reject(new Error(msg.details));
|
|
508
|
-
delete this.result_futures[msg.message_id];
|
|
509
|
-
}
|
|
591
|
+
this._rejectPendingCommand(msg.message_id, new Error(msg.details));
|
|
510
592
|
return;
|
|
511
593
|
}
|
|
512
594
|
if ("result" in msg) {
|
|
513
|
-
|
|
514
|
-
if (promise) {
|
|
515
|
-
promise.resolve(msg.result);
|
|
516
|
-
delete this.result_futures[msg.message_id];
|
|
517
|
-
}
|
|
595
|
+
this._resolvePendingCommand(msg.message_id, msg.result);
|
|
518
596
|
return;
|
|
519
597
|
}
|
|
520
598
|
console.warn("Received message with unknown format", msg);
|
|
@@ -664,7 +742,7 @@ const ThemeService = new ThemeServiceImpl();
|
|
|
664
742
|
* SPDX-License-Identifier: Apache-2.0
|
|
665
743
|
*/
|
|
666
744
|
async function main() {
|
|
667
|
-
import('./matter-dashboard-app-
|
|
745
|
+
import('./matter-dashboard-app-Dr-IYMsD.js').then(function (n) { return n.C; });
|
|
668
746
|
let url = "";
|
|
669
747
|
const isProductionServer = location.origin.includes(":5580") || location.href.includes("hassio_ingress") || location.href.includes("/api/ingress/");
|
|
670
748
|
if (!isProductionServer) {
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { T as ThemeService, t as toBigIntAwareJson } from './main.js';
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
6
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
7
|
+
*/
|
|
8
|
+
const TEST_NODE_START = 0xfffffffe00000000n;
|
|
9
|
+
function isTestNodeId(nodeId) {
|
|
10
|
+
const bigId = typeof nodeId === "bigint" ? nodeId : BigInt(nodeId);
|
|
11
|
+
return bigId >= TEST_NODE_START;
|
|
12
|
+
}
|
|
13
|
+
|
|
3
14
|
/**
|
|
4
15
|
* @license
|
|
5
16
|
* Copyright 2021 Google LLC
|
|
@@ -4009,7 +4020,7 @@ MdListItem = __decorate([t$1('md-list-item')], MdListItem);
|
|
|
4009
4020
|
*/
|
|
4010
4021
|
const showLogLevelDialog = async client => {
|
|
4011
4022
|
var _document$querySelect;
|
|
4012
|
-
await import('./log-level-dialog-
|
|
4023
|
+
await import('./log-level-dialog-BVxKJJ49.js');
|
|
4013
4024
|
const dialog = document.createElement("log-level-dialog");
|
|
4014
4025
|
dialog.client = client;
|
|
4015
4026
|
(_document$querySelect = document.querySelector("matter-dashboard-app")) === null || _document$querySelect === void 0 || _document$querySelect.renderRoot.appendChild(dialog);
|
|
@@ -15581,7 +15592,7 @@ const clusters = {
|
|
|
15581
15592
|
* SPDX-License-Identifier: Apache-2.0
|
|
15582
15593
|
*/
|
|
15583
15594
|
const showDialogBox = async (type, dialogParams) => {
|
|
15584
|
-
await import('./dialog-box-
|
|
15595
|
+
await import('./dialog-box-DFs0hcPv.js');
|
|
15585
15596
|
return new Promise(resolve => {
|
|
15586
15597
|
const dialog = document.createElement("dialox-box");
|
|
15587
15598
|
dialog.params = dialogParams;
|
|
@@ -15755,7 +15766,7 @@ MdTextButton = __decorate([t$1('md-text-button')], MdTextButton);
|
|
|
15755
15766
|
*/
|
|
15756
15767
|
const showNodeBindingDialog = async (client, node, endpoint) => {
|
|
15757
15768
|
var _document$querySelect;
|
|
15758
|
-
await import('./node-binding-dialog-
|
|
15769
|
+
await import('./node-binding-dialog-CqE3VuZN.js');
|
|
15759
15770
|
const dialog = document.createElement("node-binding-dialog");
|
|
15760
15771
|
dialog.client = client;
|
|
15761
15772
|
dialog.node = node;
|
|
@@ -15763,6 +15774,24 @@ const showNodeBindingDialog = async (client, node, endpoint) => {
|
|
|
15763
15774
|
(_document$querySelect = document.querySelector("matter-dashboard-app")) === null || _document$querySelect === void 0 || _document$querySelect.renderRoot.appendChild(dialog);
|
|
15764
15775
|
};
|
|
15765
15776
|
|
|
15777
|
+
/**
|
|
15778
|
+
* @license
|
|
15779
|
+
* Copyright 2025-2026 Open Home Foundation
|
|
15780
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
15781
|
+
*/
|
|
15782
|
+
function handleAsync(fn, onError) {
|
|
15783
|
+
return () => {
|
|
15784
|
+
fn().catch(error => {
|
|
15785
|
+
console.error("Async operation failed:", error);
|
|
15786
|
+
});
|
|
15787
|
+
};
|
|
15788
|
+
}
|
|
15789
|
+
function fireAndForget(promise, onError) {
|
|
15790
|
+
promise.catch(error => {
|
|
15791
|
+
console.error("Async operation failed:", error);
|
|
15792
|
+
});
|
|
15793
|
+
}
|
|
15794
|
+
|
|
15766
15795
|
/**
|
|
15767
15796
|
* @license
|
|
15768
15797
|
* Copyright 2018 Google LLC
|
|
@@ -15798,6 +15827,10 @@ function formatHex(value) {
|
|
|
15798
15827
|
}
|
|
15799
15828
|
return `0x${hex}`;
|
|
15800
15829
|
}
|
|
15830
|
+
function formatNodeAddress(fabricIndex, nodeId) {
|
|
15831
|
+
const fabricPart = fabricIndex !== void 0 ? fabricIndex : "?";
|
|
15832
|
+
return `@${fabricPart}:${nodeId.toString(16)}`;
|
|
15833
|
+
}
|
|
15801
15834
|
|
|
15802
15835
|
var __defProp$7 = Object.defineProperty;
|
|
15803
15836
|
var __getOwnPropDesc$9 = Object.getOwnPropertyDescriptor;
|
|
@@ -15997,27 +16030,27 @@ let NodeDetails = class extends i$3 {
|
|
|
15997
16030
|
</div>`}
|
|
15998
16031
|
</md-list-item>
|
|
15999
16032
|
<md-list-item class="btn">
|
|
16000
|
-
<md-outlined-button @click=${this._reinterview}
|
|
16033
|
+
<md-outlined-button @click=${handleAsync(() => this._reinterview())}
|
|
16001
16034
|
>Interview<ha-svg-icon slot="icon" .path=${mdiChatProcessing}></ha-svg-icon
|
|
16002
16035
|
></md-outlined-button>
|
|
16003
16036
|
${this._updateInitiated ? b` <md-outlined-button disabled
|
|
16004
16037
|
>Checking for updates<ha-svg-icon slot="icon" .path=${mdiUpdate}></ha-svg-icon
|
|
16005
16038
|
></md-outlined-button>` : (this.node.updateState || 0) > 1 ? b` <md-outlined-button disabled
|
|
16006
16039
|
>${getUpdateStateLabel(this.node.updateState, this.node.updateStateProgress)}<ha-svg-icon slot="icon" .path=${mdiUpdate}></ha-svg-icon
|
|
16007
|
-
></md-outlined-button>` : b`<md-outlined-button @click=${this._searchUpdate}
|
|
16040
|
+
></md-outlined-button>` : b`<md-outlined-button @click=${handleAsync(() => this._searchUpdate())}
|
|
16008
16041
|
>Update<ha-svg-icon slot="icon" .path=${mdiUpdate}></ha-svg-icon
|
|
16009
16042
|
></md-outlined-button>`}
|
|
16010
16043
|
${bindings ? b`
|
|
16011
|
-
<md-outlined-button @click=${this._binding}>
|
|
16044
|
+
<md-outlined-button @click=${handleAsync(() => this._binding())}>
|
|
16012
16045
|
Binding
|
|
16013
16046
|
<ha-svg-icon slot="icon" .path=${mdiLink}></ha-svg-icon>
|
|
16014
16047
|
</md-outlined-button>
|
|
16015
16048
|
` : A}
|
|
16016
16049
|
|
|
16017
|
-
<md-outlined-button @click=${this._openCommissioningWindow}
|
|
16050
|
+
<md-outlined-button @click=${handleAsync(() => this._openCommissioningWindow())}
|
|
16018
16051
|
>Share<ha-svg-icon slot="icon" .path=${mdiShareVariant}></ha-svg-icon
|
|
16019
16052
|
></md-outlined-button>
|
|
16020
|
-
<md-outlined-button @click=${this._remove}
|
|
16053
|
+
<md-outlined-button @click=${handleAsync(() => this._remove())}
|
|
16021
16054
|
>Remove<ha-svg-icon slot="icon" .path=${mdiTrashCan}></ha-svg-icon
|
|
16022
16055
|
></md-outlined-button>
|
|
16023
16056
|
</md-list-item>
|
|
@@ -16332,8 +16365,10 @@ let LevelControlClusterCommands = class extends BaseClusterCommands {
|
|
|
16332
16365
|
/>
|
|
16333
16366
|
Execute if Off
|
|
16334
16367
|
</label>
|
|
16335
|
-
<md-outlined-button @click=${this._handleMoveToLevel}
|
|
16336
|
-
|
|
16368
|
+
<md-outlined-button @click=${handleAsync(() => this._handleMoveToLevel())}
|
|
16369
|
+
>MoveToLevel</md-outlined-button
|
|
16370
|
+
>
|
|
16371
|
+
<md-outlined-button @click=${handleAsync(() => this._handleMoveToLevelWithOnOff())}
|
|
16337
16372
|
>MoveToLevelWithOnOff</md-outlined-button
|
|
16338
16373
|
>
|
|
16339
16374
|
</div>
|
|
@@ -16410,9 +16445,11 @@ let OnOffClusterCommands = class extends BaseClusterCommands {
|
|
|
16410
16445
|
<summary>OnOff Commands</summary>
|
|
16411
16446
|
<div class="command-content">
|
|
16412
16447
|
<div class="command-row">
|
|
16413
|
-
<md-outlined-button @click=${this._handleOn}>On</md-outlined-button>
|
|
16414
|
-
<md-outlined-button @click=${this._handleOff}>Off</md-outlined-button>
|
|
16415
|
-
<md-outlined-button @click=${this._handleToggle}
|
|
16448
|
+
<md-outlined-button @click=${handleAsync(() => this._handleOn())}>On</md-outlined-button>
|
|
16449
|
+
<md-outlined-button @click=${handleAsync(() => this._handleOff())}>Off</md-outlined-button>
|
|
16450
|
+
<md-outlined-button @click=${handleAsync(() => this._handleToggle())}
|
|
16451
|
+
>Toggle</md-outlined-button
|
|
16452
|
+
>
|
|
16416
16453
|
</div>
|
|
16417
16454
|
</div>
|
|
16418
16455
|
</details>
|
|
@@ -16750,7 +16787,7 @@ DashboardFooter = __decorateClass$3([t$1("dashboard-footer")], DashboardFooter);
|
|
|
16750
16787
|
*/
|
|
16751
16788
|
const showCommissionNodeDialog = async client => {
|
|
16752
16789
|
var _document$querySelect;
|
|
16753
|
-
await import('./commission-node-dialog-
|
|
16790
|
+
await import('./commission-node-dialog-B4_wgFye.js');
|
|
16754
16791
|
const dialog = document.createElement("commission-node-dialog");
|
|
16755
16792
|
dialog.client = client;
|
|
16756
16793
|
(_document$querySelect = document.querySelector("matter-dashboard-app")) === null || _document$querySelect === void 0 || _document$querySelect.renderRoot.appendChild(dialog);
|
|
@@ -16816,7 +16853,7 @@ let ServerDetails = class extends i$3 {
|
|
|
16816
16853
|
<md-list-item class="btn">
|
|
16817
16854
|
<span>
|
|
16818
16855
|
<md-outlined-button @click=${this._commissionNode}>Commission node<ha-svg-icon slot="icon" .path=${mdiPlus}></ha-svg-icon></md-outlined-button>
|
|
16819
|
-
<md-outlined-button @click=${this._uploadDiagnosticsDumpFile}>Import node<ha-svg-icon slot="icon" .path=${mdiFile}></ha-svg-icon></md-outlined-button>
|
|
16856
|
+
<md-outlined-button @click=${handleAsync(() => this._uploadDiagnosticsDumpFile())}>Import node<ha-svg-icon slot="icon" .path=${mdiFile}></ha-svg-icon></md-outlined-button>
|
|
16820
16857
|
</md-list-item>
|
|
16821
16858
|
</md-list>
|
|
16822
16859
|
<!-- hidden file element for the upload diagnostics -->
|
|
@@ -16841,7 +16878,7 @@ let ServerDetails = class extends i$3 {
|
|
|
16841
16878
|
}))) {
|
|
16842
16879
|
return;
|
|
16843
16880
|
}
|
|
16844
|
-
const fileElem = this.
|
|
16881
|
+
const fileElem = this.shadowRoot.getElementById("fileElem");
|
|
16845
16882
|
fileElem.click();
|
|
16846
16883
|
}
|
|
16847
16884
|
};
|
|
@@ -16899,6 +16936,9 @@ let MatterServerView = class extends i$3 {
|
|
|
16899
16936
|
<md-list-item type="link" href=${`#node/${node.node_id}`}>
|
|
16900
16937
|
<div slot="headline">
|
|
16901
16938
|
Node ${node.node_id}
|
|
16939
|
+
<span class="hex-id"
|
|
16940
|
+
>(${formatNodeAddress(isTestNodeId(node.node_id) || this.client.serverInfo.fabric_index === void 0 ? void 0 : this.client.serverInfo.fabric_index, node.node_id)})</span
|
|
16941
|
+
>
|
|
16902
16942
|
${node.available ? "" : b`<span class="status">OFFLINE</span>`}
|
|
16903
16943
|
</div>
|
|
16904
16944
|
<div slot="supporting-text">
|
|
@@ -16947,6 +16987,11 @@ MatterServerView.styles = i$6`
|
|
|
16947
16987
|
font-weight: bold;
|
|
16948
16988
|
font-size: 0.8em;
|
|
16949
16989
|
}
|
|
16990
|
+
|
|
16991
|
+
.hex-id {
|
|
16992
|
+
color: var(--text-color, rgba(0, 0, 0, 0.6));
|
|
16993
|
+
font-size: 0.85em;
|
|
16994
|
+
}
|
|
16950
16995
|
`;
|
|
16951
16996
|
__decorateClass$1([n$1()], MatterServerView.prototype, "nodes", 2);
|
|
16952
16997
|
MatterServerView = __decorateClass$1([t$1("matter-server-view")], MatterServerView);
|
|
@@ -17147,4 +17192,4 @@ var matterDashboardApp = /*#__PURE__*/Object.freeze({
|
|
|
17147
17192
|
__proto__: null
|
|
17148
17193
|
});
|
|
17149
17194
|
|
|
17150
|
-
export { A, D, EASING as E, ListController as L, NavigableKeys as N, __decorate as _, e$5 as a, getLastActivatableItem as b, createAnimationSignal as c, getFirstActivatableItem as d, e$6 as e, e$2 as f, getActiveItem as g, b as h, i$3 as i, i$6 as j, mixinElementInternals as k, i$1 as l, mixinDelegatesAria as m, n$1 as n, o$2 as o,
|
|
17195
|
+
export { A, internals as B, matterDashboardApp as C, D, EASING as E, ListController as L, NavigableKeys as N, __decorate as _, e$5 as a, getLastActivatableItem as b, createAnimationSignal as c, getFirstActivatableItem as d, e$6 as e, e$2 as f, getActiveItem as g, b as h, i$3 as i, i$6 as j, mixinElementInternals as k, i$1 as l, mixinDelegatesAria as m, n$1 as n, o$2 as o, fireAndForget as p, handleAsync as q, r$1 as r, c$3 as s, t$1 as t, u, clientContext as v, e$3 as w, i$2 as x, t as y, E as z };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { j as i,
|
|
2
|
-
import { p as preventDefault } from './prevent_default-
|
|
3
|
-
import './outlined-text-field-
|
|
1
|
+
import { j as i, s as c, n, v as clientContext, a as e, i as i$1, q as handleAsync, A, h as b, t } from './matter-dashboard-app-Dr-IYMsD.js';
|
|
2
|
+
import { p as preventDefault } from './prevent_default-tLhqZmsK.js';
|
|
3
|
+
import './outlined-text-field-BVcHUxiS.js';
|
|
4
4
|
import './main.js';
|
|
5
|
-
import './validator-
|
|
5
|
+
import './validator-muF28wYx.js';
|
|
6
6
|
|
|
7
7
|
var _staticBlock$1;
|
|
8
8
|
/**
|
|
@@ -331,7 +331,7 @@ let NodeBindingDialog = class extends i$1 {
|
|
|
331
331
|
</div>
|
|
332
332
|
<div slot="end">
|
|
333
333
|
<md-text-button
|
|
334
|
-
@click=${() => this.deleteBindingHandler(index)}
|
|
334
|
+
@click=${handleAsync(() => this.deleteBindingHandler(index))}
|
|
335
335
|
>delete</md-text-button
|
|
336
336
|
</div>
|
|
337
337
|
</md-list-item>
|
|
@@ -384,7 +384,7 @@ let NodeBindingDialog = class extends i$1 {
|
|
|
384
384
|
</div>
|
|
385
385
|
</div>
|
|
386
386
|
<div slot="actions">
|
|
387
|
-
<md-text-button @click=${this.addBindingHandler}>Add</md-text-button>
|
|
387
|
+
<md-text-button @click=${handleAsync(() => this.addBindingHandler())}>Add</md-text-button>
|
|
388
388
|
<md-text-button @click=${this._close}>Cancel</md-text-button>
|
|
389
389
|
</div>
|
|
390
390
|
</md-dialog>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { j as i,
|
|
2
|
-
import { V as Validator, m as mixinOnReportValidity, a as mixinConstraintValidation, b as mixinFormAssociated, o as o$1, g as getFormValue, d as createValidator, e as getValidityAnchor, c as onReportValidity } from './validator-
|
|
3
|
-
import { r as redispatchEvent } from './prevent_default-
|
|
1
|
+
import { j as i, w as e, x as i$1, y as t, z as E, A, m as mixinDelegatesAria, k as mixinElementInternals, i as i$2, _ as __decorate, n, r as r$1, a as e$1, o, f as e$2, h as b, u, l as i$3, t as t$1 } from './matter-dashboard-app-Dr-IYMsD.js';
|
|
2
|
+
import { V as Validator, m as mixinOnReportValidity, a as mixinConstraintValidation, b as mixinFormAssociated, o as o$1, g as getFormValue, d as createValidator, e as getValidityAnchor, c as onReportValidity } from './validator-muF28wYx.js';
|
|
3
|
+
import { r as redispatchEvent } from './prevent_default-tLhqZmsK.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* @license
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as EASING, m as mixinDelegatesAria, i, _ as __decorate, n, a as e, r, h as b, f as e$1, A, j as i$1, t } from './matter-dashboard-app-
|
|
1
|
+
import { E as EASING, m as mixinDelegatesAria, i, _ as __decorate, n, a as e, r, h as b, f as e$1, A, j as i$1, t } from './matter-dashboard-app-Dr-IYMsD.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @license
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { _ as __decorate, n as n$1, o as o$1, r, a as e, i as i$1, f as e$1, A, h as b, D, E as EASING, j as i$2, t,
|
|
1
|
+
import { _ as __decorate, n as n$1, o as o$1, r, a as e, i as i$1, f as e$1, A, h as b, D, E as EASING, j as i$2, t, w as e$2, x as i$3, y as t$1, z as E, B as internals } from './matter-dashboard-app-Dr-IYMsD.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @license
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matter-server/dashboard",
|
|
3
|
-
"version": "0.2.7-alpha.0-
|
|
3
|
+
"version": "0.2.7-alpha.0-20260119-49e7237",
|
|
4
4
|
"description": "Dashboard for OHF Matter Server",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/matter-js/matterjs-server/issues"
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@lit/context": "^1.1.6",
|
|
39
39
|
"@material/web": "^2.4.1",
|
|
40
|
-
"@matter-server/ws-client": "0.2.7-alpha.0-
|
|
41
|
-
"@matter-server/custom-clusters": "0.2.7-alpha.0-
|
|
40
|
+
"@matter-server/ws-client": "0.2.7-alpha.0-20260119-49e7237",
|
|
41
|
+
"@matter-server/custom-clusters": "0.2.7-alpha.0-20260119-49e7237",
|
|
42
42
|
"@mdi/js": "^7.4.47",
|
|
43
43
|
"lit": "^3.3.1",
|
|
44
44
|
"tslib": "^2.8.1"
|