@matterbridge/core 3.10.13-dev-20261005-49e0dbd → 3.10.13-dev-20261007-320f739

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.
@@ -5,7 +5,7 @@ import { Endpoint, ServerNode } from '@matter/node';
5
5
  import { AggregatorEndpoint } from '@matter/node/endpoints/aggregator';
6
6
  import { type DeviceCertification } from '@matter/protocol';
7
7
  import { DeviceTypeId, VendorId } from '@matter/types/datatype';
8
- import type { ApiMatter, ApiSettings, BridgeMode, BridgeStatus, MaybePromise, PlatformMatterbridge, RestartMode, SharedMatterbridge, SystemInformation, VirtualMode } from '@matterbridge/types';
8
+ import type { ApiSettings, BridgeMode, BridgeStatus, MaybePromise, PlatformMatterbridge, RestartMode, SharedMatterbridge, SystemInformation, VirtualMode } from '@matterbridge/types';
9
9
  import { AnsiLogger, LogLevel } from 'node-ansi-logger';
10
10
  import { type NodeStorage, NodeStorageManager } from 'node-persist-manager';
11
11
  import { DeviceManager } from './deviceManager.js';
@@ -120,7 +120,6 @@ export declare class Matterbridge extends EventEmitter<MatterbridgeEvents> {
120
120
  controllerVendorName: string;
121
121
  controllerProductId: number;
122
122
  controllerProductName: string;
123
- advertisingNodes: Map<string, number>;
124
123
  private readonly server;
125
124
  private constructor();
126
125
  destroy(): void;
@@ -154,7 +153,6 @@ export declare class Matterbridge extends EventEmitter<MatterbridgeEvents> {
154
153
  private stopMatterStorage;
155
154
  private createServerNodeContext;
156
155
  private createServerNode;
157
- getServerNodeData(serverNode: ServerNode): ApiMatter;
158
156
  private startServerNode;
159
157
  private stopServerNode;
160
158
  private createAggregatorNode;
@@ -166,9 +164,6 @@ export declare class Matterbridge extends EventEmitter<MatterbridgeEvents> {
166
164
  removeAllBridgedEndpoints(pluginName: string, delay?: number): Promise<void>;
167
165
  addVirtualEndpoint(pluginName: string, name: string, type: 'light' | 'outlet' | 'switch' | 'mounted_switch', callback: () => Promise<void>): Promise<boolean>;
168
166
  private subscribeAttributeChanged;
169
- private sanitizeFabricInformations;
170
- private sanitizeSessionInformation;
171
167
  private setAggregatorReachability;
172
- private getVendorIdName;
173
168
  }
174
169
  export {};
@@ -16,7 +16,7 @@ import { DeviceTypeId, EndpointNumber, VendorId } from '@matter/types/datatype';
16
16
  import { ManualPairingCodeCodec } from '@matter/types/schema';
17
17
  import { BroadcastServer } from '@matterbridge/thread/server';
18
18
  import { dev, MATTER_LOGGER_FILE, MATTER_STORAGE_DIR, MATTERBRIDGE_LOGGER_FILE, NODE_STORAGE_DIR, plg, typ } from '@matterbridge/types';
19
- import { isBun, getGlobalBunModules } from '@matterbridge/utils/bun';
19
+ import { isBun, getGlobalBunModules, memoryFootprint } from '@matterbridge/utils/bun';
20
20
  import { getIntParameter, getParameter, hasAnyParameter, hasParameter } from '@matterbridge/utils/cli';
21
21
  import { copyDirectory } from '@matterbridge/utils/copy-dir';
22
22
  import { createDirectory } from '@matterbridge/utils/create-dir';
@@ -33,6 +33,7 @@ import { Frontend } from './frontend.js';
33
33
  import { addVirtualDevice, addVirtualDevices, resolveRootDirectory } from './helpers.js';
34
34
  import { bridge } from './matterbridgeDeviceTypes.js';
35
35
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
36
+ import { clearAdvertisingNodes, deleteAdvertisingNode, getServerNodeData, setAdvertisingNode } from './matterNodeHelpers.js';
36
37
  import { PluginManager } from './pluginManager.js';
37
38
  logModuleLoaded('Matterbridge');
38
39
  export class Matterbridge extends EventEmitter {
@@ -159,7 +160,6 @@ export class Matterbridge extends EventEmitter {
159
160
  controllerVendorName = getParameter('vendorName') ?? 'Matterbridge';
160
161
  controllerProductId = getIntParameter('productId') ?? 0x8000;
161
162
  controllerProductName = getParameter('productName') ?? 'Matterbridge Controller';
162
- advertisingNodes = new Map();
163
163
  server;
164
164
  constructor() {
165
165
  super();
@@ -231,6 +231,13 @@ export class Matterbridge extends EventEmitter {
231
231
  };
232
232
  }
233
233
  getApiSettings() {
234
+ this.systemInformation.totalMemory = formatBytes(os.totalmem());
235
+ this.systemInformation.freeMemory = formatBytes(os.freemem());
236
+ this.systemInformation.systemUptime = formatUptime(os.uptime());
237
+ this.systemInformation.processUptime = formatUptime(Math.floor(process.uptime()));
238
+ this.systemInformation.rss = formatBytes(memoryFootprint());
239
+ this.systemInformation.heapTotal = formatBytes(process.memoryUsage().heapTotal);
240
+ this.systemInformation.heapUsed = formatBytes(process.memoryUsage().heapUsed);
234
241
  return {
235
242
  systemInformation: { ...this.systemInformation },
236
243
  matterbridgeInformation: {
@@ -317,6 +324,29 @@ export class Matterbridge extends EventEmitter {
317
324
  case 'matterbridge_shared':
318
325
  this.server.respond({ ...msg, result: { data: this.getSharedMatterbridge(), success: true } });
319
326
  break;
327
+ case 'matterbridge_restart':
328
+ this.server.respond({ ...msg, result: { success: true } });
329
+ await this.restartProcess();
330
+ break;
331
+ case 'matterbridge_shutdown':
332
+ this.server.respond({ ...msg, result: { success: true } });
333
+ await this.shutdownProcess();
334
+ break;
335
+ case 'matterbridge_apimatter': {
336
+ let serverNode;
337
+ if (msg.params.id === 'Matterbridge')
338
+ serverNode = this.serverNode;
339
+ else
340
+ serverNode =
341
+ this.plugins.array().find((p) => p.serverNode && p.serverNode.id === msg.params.id)?.serverNode ??
342
+ this.devices.array().find((d) => d.serverNode && d.serverNode.id === msg.params.id)?.serverNode;
343
+ if (!serverNode) {
344
+ this.server.respond({ ...msg, result: { matter: undefined } });
345
+ break;
346
+ }
347
+ this.server.respond({ ...msg, result: { matter: getServerNodeData(serverNode) } });
348
+ break;
349
+ }
320
350
  case 'matterbridge_apisettings':
321
351
  this.server.respond({ ...msg, result: { data: this.getApiSettings(), success: true } });
322
352
  break;
@@ -1123,7 +1153,7 @@ export class Matterbridge extends EventEmitter {
1123
1153
  this.systemInformation.processUptime = formatUptime(process.uptime());
1124
1154
  this.systemInformation.cpuUsage = formatPercent(0);
1125
1155
  this.systemInformation.processCpuUsage = formatPercent(0);
1126
- this.systemInformation.rss = formatBytes(process.memoryUsage().rss);
1156
+ this.systemInformation.rss = formatBytes(memoryFootprint());
1127
1157
  this.systemInformation.heapTotal = formatBytes(process.memoryUsage().heapTotal);
1128
1158
  this.systemInformation.heapUsed = formatBytes(process.memoryUsage().heapUsed);
1129
1159
  this.log.debug('Host System Information:');
@@ -1408,6 +1438,7 @@ export class Matterbridge extends EventEmitter {
1408
1438
  this.log.info('Matter storage reset done!');
1409
1439
  }
1410
1440
  await this.stopMatterStorage();
1441
+ clearAdvertisingNodes();
1411
1442
  function unlinkSafe(path, log) {
1412
1443
  try {
1413
1444
  log.debug(`Removing ${path}...`);
@@ -1956,14 +1987,14 @@ export class Matterbridge extends EventEmitter {
1956
1987
  });
1957
1988
  serverNode.lifecycle.commissioned.on(() => {
1958
1989
  this.log.notice(`Server node for ${storeId} commissioned successfully!`);
1959
- this.advertisingNodes.delete(storeId);
1960
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
1990
+ deleteAdvertisingNode(storeId);
1991
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
1961
1992
  this.frontend.wssSendSnackbarMessage(`Server node for ${storeId} commissioned successfully!`, 5, 'success');
1962
1993
  });
1963
1994
  serverNode.lifecycle.decommissioned.on(() => {
1964
1995
  this.log.notice(`Server node for ${storeId} fully decommissioned successfully!`);
1965
- this.advertisingNodes.delete(storeId);
1966
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
1996
+ deleteAdvertisingNode(storeId);
1997
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
1967
1998
  this.frontend.wssSendSnackbarMessage(`${storeId} is offline`, 5, 'warning');
1968
1999
  this.frontend.wssSendSnackbarMessage(`Server node for ${storeId} fully decommissioned successfully!`, 5, 'success');
1969
2000
  });
@@ -1978,24 +2009,24 @@ export class Matterbridge extends EventEmitter {
1978
2009
  }
1979
2010
  if (serverNode.lifecycle.isCommissioned) {
1980
2011
  this.log.notice(`Server node for ${storeId} is already commissioned.`);
1981
- this.advertisingNodes.delete(storeId);
2012
+ deleteAdvertisingNode(storeId);
1982
2013
  }
1983
2014
  else {
1984
2015
  this.log.notice(`Server node for ${storeId} is not commissioned. Pair to commission.`);
1985
- this.advertisingNodes.set(storeId, Date.now());
2016
+ setAdvertisingNode(storeId, Date.now());
1986
2017
  const { qrPairingCode, manualPairingCode } = serverNode.state.commissioning.pairingCodes;
1987
2018
  const pairingData = ManualPairingCodeCodec.decode(manualPairingCode);
1988
2019
  this.log.notice(`QR Code URL: https://project-chip.github.io/connectedhomeip/qrcode.html?data=${qrPairingCode}`);
1989
2020
  this.log.notice(`Manual pairing code ${CYAN}${manualPairingCode}${nt} discriminator ${CYAN}${discriminator}${nt} short discriminator ${CYAN}${pairingData.shortDiscriminator}${nt} passcode ${CYAN}${passcode}${nt}`);
1990
2021
  }
1991
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
2022
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
1992
2023
  this.frontend.wssSendSnackbarMessage(`${storeId} is online`, 5, 'success');
1993
2024
  this.emit('online', storeId);
1994
2025
  });
1995
2026
  serverNode.lifecycle.offline.on(() => {
1996
2027
  this.log.notice(`Server node for ${storeId} is offline`);
1997
- this.advertisingNodes.delete(storeId);
1998
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
2028
+ deleteAdvertisingNode(storeId);
2029
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
1999
2030
  this.frontend.wssSendSnackbarMessage(`${storeId} is offline`, 5, 'warning');
2000
2031
  this.emit('offline', storeId);
2001
2032
  });
@@ -2003,7 +2034,7 @@ export class Matterbridge extends EventEmitter {
2003
2034
  let action = '';
2004
2035
  switch (fabricAction) {
2005
2036
  case 'added':
2006
- this.advertisingNodes.delete(storeId);
2037
+ deleteAdvertisingNode(storeId);
2007
2038
  action = 'added';
2008
2039
  break;
2009
2040
  case 'deleted':
@@ -2014,39 +2045,23 @@ export class Matterbridge extends EventEmitter {
2014
2045
  break;
2015
2046
  }
2016
2047
  this.log.notice(`Commissioned fabric index ${fabricIndex} ${action} on server node for ${storeId}: ${debugStringify(serverNode.state.commissioning.fabrics[fabricIndex])}`);
2017
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
2048
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
2018
2049
  });
2019
2050
  serverNode.events.sessions.opened.on((session) => {
2020
2051
  this.log.notice(`Session opened on server node for ${storeId}: ${debugStringify(session)}`);
2021
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
2052
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
2022
2053
  });
2023
2054
  serverNode.events.sessions.closed.on((session) => {
2024
2055
  this.log.notice(`Session closed on server node for ${storeId}: ${debugStringify(session)}`);
2025
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
2056
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
2026
2057
  });
2027
2058
  serverNode.events.sessions.subscriptionsChanged.on((session) => {
2028
2059
  this.log.notice(`Session subscriptions changed on server node for ${storeId}: ${debugStringify(session)}`);
2029
- this.frontend.wssSendRefreshRequired('matter', { matter: { ...this.getServerNodeData(serverNode) } });
2060
+ this.frontend.wssSendRefreshRequired('matter', { matter: { ...getServerNodeData(serverNode) } });
2030
2061
  });
2031
2062
  this.log.info(`Created server node for ${storeId}`);
2032
2063
  return serverNode;
2033
2064
  }
2034
- getServerNodeData(serverNode) {
2035
- const advertiseTime = this.advertisingNodes.get(serverNode.id) ?? 0;
2036
- return {
2037
- id: serverNode.id,
2038
- online: serverNode.lifecycle.isOnline,
2039
- commissioned: serverNode.state.commissioning.commissioned,
2040
- advertising: advertiseTime > 0,
2041
- advertiseTime,
2042
- windowStatus: serverNode.state.administratorCommissioning.windowStatus,
2043
- qrPairingCode: serverNode.state.commissioning.pairingCodes.qrPairingCode,
2044
- manualPairingCode: serverNode.state.commissioning.pairingCodes.manualPairingCode,
2045
- fabricInformations: this.sanitizeFabricInformations(Object.values(serverNode.state.commissioning.fabrics)),
2046
- sessionInformations: this.sanitizeSessionInformation(Object.values(serverNode.state.sessions.sessions)),
2047
- serialNumber: serverNode.state.basicInformation.serialNumber,
2048
- };
2049
- }
2050
2065
  async startServerNode(matterServerNode) {
2051
2066
  if (!matterServerNode)
2052
2067
  return;
@@ -2353,89 +2368,6 @@ export class Matterbridge extends EventEmitter {
2353
2368
  }
2354
2369
  }
2355
2370
  }
2356
- sanitizeFabricInformations(fabricInfo) {
2357
- return fabricInfo.map((info) => {
2358
- return {
2359
- fabricIndex: info.fabricIndex,
2360
- fabricId: info.fabricId.toString(),
2361
- nodeId: info.nodeId.toString(),
2362
- rootNodeId: info.rootNodeId.toString(),
2363
- rootVendorId: info.rootVendorId,
2364
- rootVendorName: this.getVendorIdName(info.rootVendorId),
2365
- label: info.label,
2366
- };
2367
- });
2368
- }
2369
- sanitizeSessionInformation(sessions) {
2370
- return sessions
2371
- .filter((session) => session.isPeerActive)
2372
- .map((session) => {
2373
- return {
2374
- name: session.name,
2375
- nodeId: session.nodeId.toString(),
2376
- peerNodeId: session.peerNodeId.toString(),
2377
- fabric: session.fabric
2378
- ? {
2379
- fabricIndex: session.fabric.fabricIndex,
2380
- fabricId: session.fabric.fabricId.toString(),
2381
- nodeId: session.fabric.nodeId.toString(),
2382
- rootNodeId: session.fabric.rootNodeId.toString(),
2383
- rootVendorId: session.fabric.rootVendorId,
2384
- rootVendorName: this.getVendorIdName(session.fabric.rootVendorId),
2385
- label: session.fabric.label,
2386
- }
2387
- : undefined,
2388
- isPeerActive: session.isPeerActive,
2389
- lastInteractionTimestamp: session.lastInteractionTimestamp?.toString(),
2390
- lastActiveTimestamp: session.lastActiveTimestamp?.toString(),
2391
- numberOfActiveSubscriptions: session.numberOfActiveSubscriptions,
2392
- };
2393
- });
2394
- }
2395
2371
  async setAggregatorReachability(aggregatorNode, reachable) {
2396
2372
  }
2397
- getVendorIdName = (vendorId) => {
2398
- if (!vendorId)
2399
- return '';
2400
- let vendorName = '(Unknown vendorId)';
2401
- switch (vendorId) {
2402
- case 4937:
2403
- vendorName = '(AppleHome)';
2404
- break;
2405
- case 4996:
2406
- vendorName = '(AppleKeyChain)';
2407
- break;
2408
- case 4362:
2409
- vendorName = '(SmartThings)';
2410
- break;
2411
- case 4939:
2412
- vendorName = '(HomeAssistant)';
2413
- break;
2414
- case 24582:
2415
- vendorName = '(GoogleHome)';
2416
- break;
2417
- case 4631:
2418
- vendorName = '(Alexa)';
2419
- break;
2420
- case 4701:
2421
- vendorName = '(Tuya)';
2422
- break;
2423
- case 4718:
2424
- vendorName = '(Xiaomi)';
2425
- break;
2426
- case 4742:
2427
- vendorName = '(eWeLink)';
2428
- break;
2429
- case 5264:
2430
- vendorName = '(Shelly)';
2431
- break;
2432
- case 0x1488:
2433
- vendorName = '(ShortcutLabsFlic)';
2434
- break;
2435
- case 65521:
2436
- vendorName = '(MatterTest)';
2437
- break;
2438
- }
2439
- return vendorName;
2440
- };
2441
2373
  }
@@ -11,6 +11,7 @@ import { AnsiLogger, BLUE, CYAN, db, debugStringify, er, nf, nt, rs, UNDERLINE,
11
11
  import { isMatterbridgeAccessoryPlatform } from './matterbridgeAccessoryPlatform.js';
12
12
  import { isMatterbridgeDynamicPlatform } from './matterbridgeDynamicPlatform.js';
13
13
  import { assertMatterbridgePlatform } from './matterbridgePlatform.js';
14
+ import { getServerNodeData } from './matterNodeHelpers.js';
14
15
  logModuleLoaded('Plugin Manager');
15
16
  export class PluginManager extends EventEmitter {
16
17
  matterbridge;
@@ -389,7 +390,7 @@ export class PluginManager extends EventEmitter {
389
390
  schemaJson: plugin.schemaJson,
390
391
  hasWhiteList: plugin.hasWhiteList,
391
392
  hasBlackList: plugin.hasBlackList,
392
- matter: plugin.serverNode ? this.matterbridge.getServerNodeData(plugin.serverNode) : undefined,
393
+ matter: plugin.serverNode ? getServerNodeData(plugin.serverNode) : undefined,
393
394
  };
394
395
  }
395
396
  array() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/core",
3
- "version": "3.10.13-dev-20261005-49e0dbd",
3
+ "version": "3.10.13-dev-20261007-320f739",
4
4
  "description": "Matterbridge core library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -136,10 +136,10 @@
136
136
  },
137
137
  "dependencies": {
138
138
  "@matter/main": "0.17.9",
139
- "@matterbridge/dgram": "3.10.13-dev-20261005-49e0dbd",
140
- "@matterbridge/thread": "3.10.13-dev-20261005-49e0dbd",
141
- "@matterbridge/types": "3.10.13-dev-20261005-49e0dbd",
142
- "@matterbridge/utils": "3.10.13-dev-20261005-49e0dbd",
139
+ "@matterbridge/dgram": "3.10.13-dev-20261007-320f739",
140
+ "@matterbridge/thread": "3.10.13-dev-20261007-320f739",
141
+ "@matterbridge/types": "3.10.13-dev-20261007-320f739",
142
+ "@matterbridge/utils": "3.10.13-dev-20261007-320f739",
143
143
  "escape-html": "1.0.3",
144
144
  "express": "5.2.1",
145
145
  "express-rate-limit": "8.7.0",
package/dist/backend.d.ts DELETED
@@ -1,37 +0,0 @@
1
- import EventEmitter from 'node:events';
2
- import type { ApiDevice, ApiPlugin, ApiSettings, SharedMatterbridge } from '@matterbridge/types';
3
- import type { BackendExpress } from './backendExpress.js';
4
- import type { BackendWsServer } from './backendWsServer.js';
5
- interface BackendEvents {
6
- server_listening: [protocol: string, port: number, address?: string];
7
- server_error: [error: unknown];
8
- server_stopped: [];
9
- websocket_server_listening: [protocol: string];
10
- websocket_server_stopped: [];
11
- }
12
- export declare class Backend extends EventEmitter<BackendEvents> {
13
- private debug;
14
- private verbose;
15
- private log;
16
- private matterbridge;
17
- private readonly server;
18
- private port;
19
- private listening;
20
- private httpServer;
21
- private httpsServer;
22
- backendExpress: BackendExpress | undefined;
23
- backendWsServer: BackendWsServer | undefined;
24
- storedPassword: string | undefined;
25
- authClients: Set<string>;
26
- authClientsTimeout: NodeJS.Timeout | undefined;
27
- constructor(matterbridge: SharedMatterbridge);
28
- destroy(): void;
29
- private broadcastMsgHandler;
30
- start(port?: number): Promise<void>;
31
- stop(): Promise<void>;
32
- getApiSettings(): Promise<ApiSettings>;
33
- getApiPlugins(): Promise<ApiPlugin[]>;
34
- getApiDevices(pluginName?: string): Promise<ApiDevice[]>;
35
- generateDiagnostic(): Promise<void>;
36
- }
37
- export {};