@matterbridge/core 3.10.14-dev-20261010-607ee18 → 3.10.14-dev-20261013-e87a0c8

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 (77) hide show
  1. package/dist/backendExpress.js +14 -9
  2. package/dist/backendWsServer.d.ts +1 -5
  3. package/dist/backendWsServer.js +4 -35
  4. package/dist/behaviors/bindingServer.d.ts +1 -1
  5. package/dist/behaviors/booleanStateConfigurationServer.js +2 -1
  6. package/dist/behaviors/cameraAvSettingsUserLevelManagementServer.d.ts +1 -1
  7. package/dist/behaviors/cameraAvSettingsUserLevelManagementServer.js +2 -1
  8. package/dist/behaviors/cameraAvStreamManagementServer.d.ts +1 -2
  9. package/dist/behaviors/cameraAvStreamManagementServer.js +2 -1
  10. package/dist/behaviors/chimeServer.js +2 -1
  11. package/dist/behaviors/deviceEnergyManagementServer.js +2 -1
  12. package/dist/behaviors/fanControlServer.js +2 -1
  13. package/dist/behaviors/pumpConfigurationAndControlServer.js +2 -1
  14. package/dist/behaviors/smokeCoAlarmServer.js +2 -1
  15. package/dist/behaviors/temperatureAlarmServer.js +2 -1
  16. package/dist/behaviors/thermostatServer.js +2 -1
  17. package/dist/behaviors/valveConfigurationAndControlServer.js +2 -1
  18. package/dist/behaviors/webRtcTransportProviderServer.js +3 -1
  19. package/dist/chipTests.js +3 -2
  20. package/dist/cli.js +36 -4
  21. package/dist/cliEmitter.d.ts +0 -3
  22. package/dist/deviceManager.d.ts +0 -1
  23. package/dist/deviceManager.js +15 -47
  24. package/dist/devices/airConditioner.d.ts +1 -1
  25. package/dist/devices/audioDoorbell.d.ts +1 -1
  26. package/dist/devices/audioDoorbell.js +1 -1
  27. package/dist/devices/batteryStorage.d.ts +1 -1
  28. package/dist/devices/camera.d.ts +1 -2
  29. package/dist/devices/camera.js +1 -1
  30. package/dist/devices/closure.d.ts +2 -2
  31. package/dist/devices/closure.js +1 -1
  32. package/dist/devices/closurePanel.js +1 -1
  33. package/dist/devices/cooktop.d.ts +2 -1
  34. package/dist/devices/dishwasher.d.ts +2 -2
  35. package/dist/devices/dishwasher.js +2 -1
  36. package/dist/devices/electricalUtilityMeter.d.ts +1 -1
  37. package/dist/devices/electricalUtilityMeter.js +1 -1
  38. package/dist/devices/evse.d.ts +1 -1
  39. package/dist/devices/evse.js +2 -1
  40. package/dist/devices/extractorHood.d.ts +1 -1
  41. package/dist/devices/floodlightCamera.d.ts +1 -1
  42. package/dist/devices/floodlightCamera.js +1 -1
  43. package/dist/devices/heatPump.d.ts +1 -1
  44. package/dist/devices/intercom.d.ts +1 -1
  45. package/dist/devices/intercom.js +1 -1
  46. package/dist/devices/irrigationSystem.d.ts +1 -1
  47. package/dist/devices/laundryDryer.d.ts +2 -2
  48. package/dist/devices/laundryDryer.js +2 -1
  49. package/dist/devices/laundryWasher.d.ts +2 -2
  50. package/dist/devices/laundryWasher.js +2 -1
  51. package/dist/devices/microwaveOven.d.ts +2 -2
  52. package/dist/devices/microwaveOven.js +2 -1
  53. package/dist/devices/oven.d.ts +2 -1
  54. package/dist/devices/refrigerator.d.ts +2 -1
  55. package/dist/devices/roboticVacuumCleaner.d.ts +1 -1
  56. package/dist/devices/snapshotCamera.d.ts +1 -1
  57. package/dist/devices/snapshotCamera.js +1 -1
  58. package/dist/devices/solarPower.d.ts +1 -1
  59. package/dist/devices/temperatureControl.js +2 -1
  60. package/dist/devices/videoDoorbell.d.ts +1 -1
  61. package/dist/devices/videoDoorbell.js +1 -1
  62. package/dist/devices/waterHeater.d.ts +1 -1
  63. package/dist/frontend.d.ts +1 -8
  64. package/dist/frontend.js +23 -82
  65. package/dist/matterNode.d.ts +4 -2
  66. package/dist/matterNode.js +116 -67
  67. package/dist/matterNodeHelpers.d.ts +3 -1
  68. package/dist/matterNodeHelpers.js +48 -0
  69. package/dist/matterbridge.js +14 -24
  70. package/dist/matterbridgeDeviceTypes.d.ts +1 -1
  71. package/dist/matterbridgeEndpoint.js +43 -29
  72. package/dist/matterbridgePlatform.js +39 -3
  73. package/dist/pluginManager.js +10 -1
  74. package/dist/runners/threadBackend.js +20 -6
  75. package/dist/runners/threadRootNode.js +32 -12
  76. package/dist/runners/threadTracker.js +23 -6
  77. package/package.json +5 -5
@@ -327,8 +327,6 @@ export class MatterbridgeEndpoint extends Endpoint {
327
327
  if (!this.lifecycle.isReady || this.construction.status !== Lifecycle.Status.Active)
328
328
  return;
329
329
  for (const [clusterName, clusterAttributes] of Object.entries(this.state)) {
330
- if (!Number.isNaN(Number(clusterName)))
331
- continue;
332
330
  for (const [attributeName, attributeValue] of Object.entries(clusterAttributes)) {
333
331
  const clusterId = getClusterId(this, clusterName);
334
332
  if (clusterId === undefined) {
@@ -601,20 +599,22 @@ export class MatterbridgeEndpoint extends Endpoint {
601
599
  return this;
602
600
  }
603
601
  createDefaultPowerTopologyClusterServer(feature = PowerTopology.Feature.TreeTopology, availableEndpoints = [], activeEndpoints = []) {
604
- if (feature === PowerTopology.Feature.NodeTopology) {
605
- this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.NodeTopology));
606
- }
607
- else if (feature === PowerTopology.Feature.TreeTopology) {
608
- this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.TreeTopology));
609
- }
610
- else if (feature === PowerTopology.Feature.SetTopology) {
611
- this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.SetTopology), { availableEndpoints });
612
- }
613
- else if (feature === PowerTopology.Feature.DynamicPowerFlow) {
614
- this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.SetTopology, PowerTopology.Feature.DynamicPowerFlow), {
615
- availableEndpoints,
616
- activeEndpoints,
617
- });
602
+ switch (feature) {
603
+ case PowerTopology.Feature.NodeTopology:
604
+ this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.NodeTopology));
605
+ break;
606
+ case PowerTopology.Feature.TreeTopology:
607
+ this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.TreeTopology));
608
+ break;
609
+ case PowerTopology.Feature.SetTopology:
610
+ this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.SetTopology), { availableEndpoints });
611
+ break;
612
+ case PowerTopology.Feature.DynamicPowerFlow:
613
+ this.behaviors.require(PowerTopologyServer.with(PowerTopology.Feature.SetTopology, PowerTopology.Feature.DynamicPowerFlow), {
614
+ availableEndpoints,
615
+ activeEndpoints,
616
+ });
617
+ break;
618
618
  }
619
619
  return this;
620
620
  }
@@ -882,7 +882,7 @@ export class MatterbridgeEndpoint extends Endpoint {
882
882
  });
883
883
  return this;
884
884
  }
885
- createDefaultTiltWindowCoveringClusterServer(positionTiltPercent100ths = 0, type = WindowCovering.WindowCoveringType.TiltBlindTiltOnly, endProductType = WindowCovering.EndProductType.InteriorVenetianBlind, movementDuration = 0) {
885
+ createDefaultTiltWindowCoveringClusterServer(positionTiltPercent100ths = 0, type = WindowCovering.WindowCoveringType.TiltBlindTiltOnly, endProductType = WindowCovering.EndProductType.TiltOnlyInteriorBlind, movementDuration = 0) {
886
886
  this.behaviors.require(MatterbridgeWindowCoveringServer.with(WindowCovering.Feature.Tilt, WindowCovering.Feature.PositionAwareTilt), {
887
887
  type,
888
888
  numberOfActuationsTilt: 0,
@@ -927,15 +927,22 @@ export class MatterbridgeEndpoint extends Endpoint {
927
927
  }, this.log);
928
928
  }
929
929
  async setWindowCoveringCurrentTargetStatus(current, target, status) {
930
- await this.setAttribute(WindowCovering, 'currentPositionLiftPercent100ths', current, this.log);
931
- await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', target, this.log);
932
930
  const { lift, tilt } = featuresFor(this, WindowCovering);
931
+ const axis = lift ? 'Lift' : 'Tilt';
932
+ if (lift) {
933
+ await this.setAttribute(WindowCovering, 'currentPositionLiftPercent100ths', current, this.log);
934
+ await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', target, this.log);
935
+ }
936
+ else {
937
+ await this.setAttribute(WindowCovering, 'currentPositionTiltPercent100ths', current, this.log);
938
+ await this.setAttribute(WindowCovering, 'targetPositionTiltPercent100ths', target, this.log);
939
+ }
933
940
  await this.setAttribute(WindowCovering, 'operationalStatus', {
934
941
  global: status,
935
942
  ...(lift ? { lift: status } : {}),
936
943
  ...(tilt ? { tilt: status } : {}),
937
944
  }, this.log);
938
- this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths: ${current}, targetPositionLiftPercent100ths: ${target} and operationalStatus: ${status}.`);
945
+ this.log.debug(`Set WindowCovering currentPosition${axis}Percent100ths: ${current}, targetPosition${axis}Percent100ths: ${target} and operationalStatus: ${status}.`);
939
946
  }
940
947
  async setWindowCoveringStatus(status) {
941
948
  const { lift, tilt } = featuresFor(this, WindowCovering);
@@ -1052,9 +1059,9 @@ export class MatterbridgeEndpoint extends Endpoint {
1052
1059
  ...(occupied !== undefined ? { unoccupiedCoolingSetpoint: unoccupiedCoolingSetpoint !== undefined ? unoccupiedCoolingSetpoint * 100 : 2700 } : {}),
1053
1060
  ...(occupied !== undefined ? { occupancy: { occupied } } : {}),
1054
1061
  ...(occupied !== undefined ? { externallyMeasuredOccupancy: true } : {}),
1055
- numberOfPresets: Math.max(Array.isArray(presets) ? presets.length : 0, Array.isArray(presetTypes) ? Math.max(0, ...presetTypes.map((pt) => pt.numberOfPresets ?? 0)) : 0, 1),
1062
+ numberOfPresets: Math.max(Array.isArray(presets) ? presets.length : 0, Array.isArray(presetTypes) ? Math.max(0, ...presetTypes.map((pt) => pt.numberOfPresets)) : 0, 1),
1056
1063
  activePresetHandle: activePresetHandle ? Uint8Array.from(activePresetHandle) : null,
1057
- presets: (presets ?? []).map((p) => ({
1064
+ presets: presets.map((p) => ({
1058
1065
  presetHandle: p.presetHandle ? Uint8Array.from(p.presetHandle) : null,
1059
1066
  presetScenario: p.presetScenario,
1060
1067
  name: p.name,
@@ -1099,11 +1106,13 @@ export class MatterbridgeEndpoint extends Endpoint {
1099
1106
  ...(occupied !== undefined ? { unoccupiedCoolingSetpoint: unoccupiedCoolingSetpoint !== undefined ? unoccupiedCoolingSetpoint * 100 : 2700 } : {}),
1100
1107
  ...(occupied !== undefined ? { occupancy: { occupied } } : {}),
1101
1108
  ...(occupied !== undefined ? { externallyMeasuredOccupancy: true } : {}),
1102
- numberOfSchedules: Math.max(Array.isArray(schedules) ? schedules.length : 0, Array.isArray(scheduleTypes) ? Math.max(0, ...scheduleTypes.map((st) => st.numberOfSchedules ?? 0)) : 0, 1),
1109
+ numberOfSchedules: Math.max(Array.isArray(schedules) ? schedules.length : 0, Array.isArray(scheduleTypes)
1110
+ ? Math.max(0, ...scheduleTypes.map((st) => st.numberOfSchedules))
1111
+ : 0, 1),
1103
1112
  numberOfScheduleTransitions,
1104
1113
  numberOfScheduleTransitionPerDay,
1105
1114
  activeScheduleHandle: activeScheduleHandle ? Uint8Array.from(activeScheduleHandle) : null,
1106
- schedules: (schedules ?? []).map((s) => ({
1115
+ schedules: schedules.map((s) => ({
1107
1116
  scheduleHandle: s.scheduleHandle ? Uint8Array.from(s.scheduleHandle) : null,
1108
1117
  systemMode: s.systemMode,
1109
1118
  name: s.name,
@@ -1111,10 +1120,15 @@ export class MatterbridgeEndpoint extends Endpoint {
1111
1120
  transitions: s.transitions ?? [],
1112
1121
  builtIn: s.builtIn ?? true,
1113
1122
  })),
1114
- scheduleTypes: (scheduleTypes ?? []).map((st) => ({
1123
+ scheduleTypes: scheduleTypes.map((st) => ({
1115
1124
  ...st,
1116
1125
  numberOfSchedules: st.numberOfSchedules ?? 0,
1117
- scheduleTypeFeatures: st.scheduleTypeFeatures ?? { supportsSetpoints: true, supportsNames: true, supportsPresets: false, supportsOff: false },
1126
+ scheduleTypeFeatures: st.scheduleTypeFeatures ?? {
1127
+ supportsSetpoints: true,
1128
+ supportsNames: true,
1129
+ supportsPresets: false,
1130
+ supportsOff: false,
1131
+ },
1118
1132
  })),
1119
1133
  });
1120
1134
  return this;
@@ -1145,9 +1159,9 @@ export class MatterbridgeEndpoint extends Endpoint {
1145
1159
  ...(occupied !== undefined ? { unoccupiedCoolingSetpoint: unoccupiedCoolingSetpoint !== undefined ? unoccupiedCoolingSetpoint * 100 : 2700 } : {}),
1146
1160
  ...(occupied !== undefined ? { occupancy: { occupied } } : {}),
1147
1161
  ...(occupied !== undefined ? { externallyMeasuredOccupancy: true } : {}),
1148
- numberOfPresets: Math.max(Array.isArray(presets) ? presets.length : 0, Array.isArray(presetTypes) ? Math.max(0, ...presetTypes.map((pt) => pt.numberOfPresets ?? 0)) : 0, 1),
1162
+ numberOfPresets: Math.max(Array.isArray(presets) ? presets.length : 0, Array.isArray(presetTypes) ? Math.max(0, ...presetTypes.map((pt) => pt.numberOfPresets)) : 0, 1),
1149
1163
  activePresetHandle: activePresetHandle ? Uint8Array.from(activePresetHandle) : null,
1150
- presets: (presets ?? []).map((p) => ({
1164
+ presets: presets.map((p) => ({
1151
1165
  presetHandle: p.presetHandle ? Uint8Array.from(p.presetHandle) : null,
1152
1166
  presetScenario: p.presetScenario,
1153
1167
  name: p.name,
@@ -1161,7 +1175,7 @@ export class MatterbridgeEndpoint extends Endpoint {
1161
1175
  presetTypeFeatures: pt.presetTypeFeatures ?? { automatic: false, supportsNames: true },
1162
1176
  })),
1163
1177
  maxThermostatSuggestions: Math.max(Array.isArray(thermostatSuggestions) ? thermostatSuggestions.length : 0, 5),
1164
- thermostatSuggestions: (thermostatSuggestions ?? []).map((s) => ({
1178
+ thermostatSuggestions: thermostatSuggestions.map((s) => ({
1165
1179
  uniqueId: s.uniqueId,
1166
1180
  presetHandle: Uint8Array.from(s.presetHandle),
1167
1181
  effectiveTime: s.effectiveTime,
@@ -6,11 +6,12 @@ import { hasParameter } from '@matterbridge/utils/cli';
6
6
  import { logModuleLoaded } from '@matterbridge/utils/loader';
7
7
  import { isValidArray, isValidObject, isValidString } from '@matterbridge/utils/validate';
8
8
  import { fireAndForget } from '@matterbridge/utils/wait';
9
- import { CYAN, db, er, nf, wr } from 'node-ansi-logger';
9
+ import { CYAN, db, debugStringify, er, nf, wr } from 'node-ansi-logger';
10
10
  import { NodeStorageManager } from 'node-persist-manager';
11
11
  import { bridgedNode } from './matterbridgeDeviceTypes.js';
12
12
  import { assertMatterbridgeEndpoint } from './matterbridgeEndpoint.js';
13
13
  import { checkNotLatinCharacters } from './matterbridgeEndpointHelpers.js';
14
+ import { toApiDevice } from './matterNodeHelpers.js';
14
15
  logModuleLoaded('MatterbridgePlatform');
15
16
  const MATTERBRIDGE_PLATFORM_BRAND = Symbol('MatterbridgePlatform.brand');
16
17
  export function isMatterbridgePlatform(value) {
@@ -71,6 +72,7 @@ export class MatterbridgePlatform {
71
72
  this.config = config;
72
73
  this.name = config.name;
73
74
  this.#server = new BroadcastServer('platform', this.log);
75
+ this.#server.on('broadcast_message', this.#msgHandler.bind(this));
74
76
  Object.defineProperty(this, MATTERBRIDGE_PLATFORM_BRAND, {
75
77
  value: true,
76
78
  writable: false,
@@ -121,6 +123,39 @@ export class MatterbridgePlatform {
121
123
  return;
122
124
  });
123
125
  }
126
+ #msgHandler(msg) {
127
+ if (!this.#server.isWorkerRequest(msg))
128
+ return;
129
+ if (this.#verbose)
130
+ this.log.debug(`Received broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}: ${debugStringify(msg)}${db}`);
131
+ switch (msg.type) {
132
+ case 'platform_get_apidevices':
133
+ if (msg.params.plugin !== this.name)
134
+ return;
135
+ this.#server.respond({
136
+ ...msg,
137
+ result: {
138
+ devices: this.getDevices()
139
+ .map(toApiDevice)
140
+ .filter((device) => device !== undefined),
141
+ },
142
+ });
143
+ break;
144
+ case 'platform_get_apiselectdevices':
145
+ if (msg.params.plugin !== this.name)
146
+ return;
147
+ this.#server.respond({ ...msg, result: { devices: this.getSelectDevices() } });
148
+ break;
149
+ case 'platform_get_apiselectentities':
150
+ if (msg.params.plugin !== this.name)
151
+ return;
152
+ this.#server.respond({ ...msg, result: { entities: this.getSelectEntities() } });
153
+ break;
154
+ default:
155
+ if (this.#verbose)
156
+ this.log.debug(`Unknown broadcast request ${CYAN}${msg.type}${db} from ${CYAN}${msg.src}${db}`);
157
+ }
158
+ }
124
159
  async destroy() {
125
160
  if (this.#verbose)
126
161
  this.log.debug(`Destroying MatterbridgePlatform for plugin ${this.config.name}`);
@@ -319,7 +354,8 @@ export class MatterbridgePlatform {
319
354
  getSelectDevices() {
320
355
  const selectDevices = [];
321
356
  for (const device of this.#selectDevices.values()) {
322
- selectDevices.push({ pluginName: this.name, ...device });
357
+ const { serial, name, ...rest } = device;
358
+ selectDevices.push({ plugin: this.name, serialNumber: serial, deviceName: name, ...rest });
323
359
  }
324
360
  return selectDevices;
325
361
  }
@@ -332,7 +368,7 @@ export class MatterbridgePlatform {
332
368
  getSelectEntities() {
333
369
  const selectEntities = [];
334
370
  for (const entity of this.#selectEntities.values()) {
335
- selectEntities.push({ pluginName: this.name, ...entity });
371
+ selectEntities.push({ plugin: this.name, ...entity });
336
372
  }
337
373
  return selectEntities;
338
374
  }
@@ -104,7 +104,16 @@ export class PluginManager extends EventEmitter {
104
104
  }
105
105
  break;
106
106
  case 'plugins_set':
107
- this.server.respond({ ...msg, result: { plugin: this.set(msg.params.plugin) } });
107
+ {
108
+ const plugin = this.get(msg.params.plugin.name);
109
+ if (plugin) {
110
+ Object.assign(plugin, msg.params.plugin);
111
+ this.server.respond({ ...msg, result: { plugin: this.toApiPlugin(plugin) } });
112
+ }
113
+ else {
114
+ this.server.respond({ ...msg, error: `Plugin ${msg.params.plugin.name} not found` });
115
+ }
116
+ }
108
117
  break;
109
118
  case 'plugins_storagepluginarray':
110
119
  this.server.respond({ ...msg, result: { plugins: this.storagePluginArray() } });
@@ -2,7 +2,9 @@ import { ThreadsWrapper } from '@matterbridge/thread/wrapper';
2
2
  import { inspectError } from '@matterbridge/utils/error';
3
3
  import { logModuleLoaded } from '@matterbridge/utils/loader';
4
4
  logModuleLoaded('Backend', '\u001B[35m');
5
- export default new ThreadsWrapper('Backend', async (worker) => {
5
+ export default new ThreadsWrapper('Backend', entrypoint, startup, shutdown);
6
+ let backend;
7
+ async function entrypoint(worker) {
6
8
  worker.logger("info", 'Creating backend...');
7
9
  try {
8
10
  worker.logger("debug", 'Fetching shared Matterbridge state...');
@@ -10,10 +12,8 @@ export default new ThreadsWrapper('Backend', async (worker) => {
10
12
  worker.logger("debug", 'Shared Matterbridge state fetched; importing Backend...');
11
13
  const { Backend } = await import('../backend.js');
12
14
  worker.logger("debug", 'Backend imported; creating instance...');
13
- const backend = new Backend(shared);
14
- worker.logger("debug", 'Starting Backend...');
15
- await backend.start();
16
- worker.logger("debug", 'Backend started');
15
+ backend = new Backend(shared);
16
+ worker.logger("debug", 'Backend instance created');
17
17
  return true;
18
18
  }
19
19
  catch (error) {
@@ -21,4 +21,18 @@ export default new ThreadsWrapper('Backend', async (worker) => {
21
21
  worker.logger("error", errorMessage);
22
22
  return false;
23
23
  }
24
- });
24
+ }
25
+ async function startup(worker) {
26
+ if (!backend)
27
+ return;
28
+ worker.logger("debug", 'Starting up Backend...');
29
+ await backend.start();
30
+ worker.logger("debug", 'Backend has been started');
31
+ }
32
+ async function shutdown(worker) {
33
+ if (!backend)
34
+ return;
35
+ worker.logger("debug", 'Shutting down Backend...');
36
+ await backend.stop();
37
+ worker.logger("debug", 'Backend has been shut down');
38
+ }
@@ -3,28 +3,48 @@ import { isRootNodeWorkerData } from '@matterbridge/types';
3
3
  import { inspectError } from '@matterbridge/utils/error';
4
4
  import { logModuleLoaded } from '@matterbridge/utils/loader';
5
5
  logModuleLoaded('RootNode', '\u001B[35m');
6
- export default new ThreadsWrapper('RootNode', async (worker) => {
7
- worker.logger("info", 'Creating root node...');
6
+ export default new ThreadsWrapper('RootNode', entrypoint, startup, shutdown);
7
+ let matterNode;
8
+ async function entrypoint(worker) {
9
+ worker.logger("info", 'Creating MatterNode...');
8
10
  try {
9
11
  if (!isRootNodeWorkerData(worker.workerData)) {
10
- worker.logger("error", 'Invalid root node worker data');
12
+ worker.logger("error", 'Invalid MatterNode worker data');
11
13
  return false;
12
14
  }
13
15
  const { sharedMatterbridge, pluginName } = worker.workerData;
14
- const target = pluginName ? `plugin ${pluginName}` : 'bridge';
16
+ const target = pluginName ? `plugin ${pluginName}` : 'Matterbridge';
15
17
  worker.logger("debug", `Importing MatterNode for ${target}...`);
16
18
  const { MatterNode } = await import('../matterNode.js');
17
- worker.logger("debug", 'MatterNode imported; creating instance...');
18
- const matterNode = new MatterNode(sharedMatterbridge, pluginName);
19
- await matterNode.create();
20
- worker.logger("debug", 'Starting MatterNode...');
21
- await matterNode.start();
22
- worker.logger("debug", `Root node for ${target} started`);
19
+ worker.logger("debug", `Creating instance for ${target}...`);
20
+ matterNode = new MatterNode(sharedMatterbridge, pluginName);
21
+ worker.logger("debug", `Instance for ${target} created.`);
23
22
  return true;
24
23
  }
25
24
  catch (error) {
26
- const errorMessage = inspectError(worker.log, 'Failed to create root node', error);
25
+ const errorMessage = inspectError(worker.log, `Failed to create MatterNode`, error);
27
26
  worker.logger("error", errorMessage);
28
27
  return false;
29
28
  }
30
- });
29
+ }
30
+ async function startup(worker) {
31
+ if (!matterNode)
32
+ return;
33
+ worker.logger("info", `Starting up MatterNode for ${matterNode.storeId}...`);
34
+ worker.logger("debug", `Creating MatterNode for ${matterNode.storeId}...`);
35
+ await matterNode.create();
36
+ worker.logger("debug", `Starting MatterNode for ${matterNode.storeId}...`);
37
+ await matterNode.start();
38
+ worker.logger("debug", `MatterNode for ${matterNode.storeId} started`);
39
+ }
40
+ async function shutdown(worker) {
41
+ if (!matterNode)
42
+ return;
43
+ worker.logger("info", `Shutting down MatterNode for ${matterNode.storeId}...`);
44
+ worker.logger("debug", `Stopping MatterNode for ${matterNode.storeId}...`);
45
+ await matterNode.stop();
46
+ worker.logger("debug", `MatterNode for ${matterNode.storeId} stopped`);
47
+ await matterNode.destroy();
48
+ worker.logger("debug", `MatterNode for ${matterNode.storeId} destroyed`);
49
+ matterNode = undefined;
50
+ }
@@ -1,19 +1,22 @@
1
1
  import { ThreadsWrapper } from '@matterbridge/thread/wrapper';
2
2
  import { inspectError } from '@matterbridge/utils/error';
3
3
  import { logModuleLoaded } from '@matterbridge/utils/loader';
4
- import { Tracker } from '@matterbridge/utils/tracker';
5
4
  logModuleLoaded('Tracker', '\u001B[35m');
6
- export default new ThreadsWrapper('Tracker', async (worker) => {
5
+ export default new ThreadsWrapper('Tracker', entrypoint, startup, shutdown);
6
+ let tracker;
7
+ async function entrypoint(worker) {
7
8
  worker.logger("info", 'Creating tracker...');
8
9
  try {
9
- const tracker = new Tracker('Tracker', true, false, true);
10
+ worker.logger("debug", 'Importing Tracker...');
11
+ const { Tracker } = await import('@matterbridge/utils/tracker');
12
+ worker.logger("debug", 'Tracker imported; creating instance...');
13
+ tracker = new Tracker('Tracker', false, false, true);
14
+ worker.logger("debug", 'Tracker instance created');
10
15
  worker.on('startup', () => {
11
16
  worker.logger("notice", 'Tracker received startup');
12
- tracker.start();
13
17
  });
14
18
  worker.on('shutdown', () => {
15
19
  worker.logger("notice", 'Tracker received shutdown');
16
- tracker.stop();
17
20
  });
18
21
  worker.logger("debug", 'Tracker created');
19
22
  return true;
@@ -23,4 +26,18 @@ export default new ThreadsWrapper('Tracker', async (worker) => {
23
26
  worker.logger("error", errorMessage);
24
27
  return false;
25
28
  }
26
- });
29
+ }
30
+ async function startup(worker) {
31
+ if (!tracker)
32
+ return;
33
+ worker.logger("debug", 'Starting up tracker...');
34
+ tracker.start();
35
+ worker.logger("debug", 'Tracker startup complete');
36
+ }
37
+ async function shutdown(worker) {
38
+ if (!tracker)
39
+ return;
40
+ worker.logger("debug", 'Shutting down tracker...');
41
+ tracker.stop();
42
+ worker.logger("debug", 'Tracker shutdown complete');
43
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/core",
3
- "version": "3.10.14-dev-20261010-607ee18",
3
+ "version": "3.10.14-dev-20261013-e87a0c8",
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.14-dev-20261010-607ee18",
140
- "@matterbridge/thread": "3.10.14-dev-20261010-607ee18",
141
- "@matterbridge/types": "3.10.14-dev-20261010-607ee18",
142
- "@matterbridge/utils": "3.10.14-dev-20261010-607ee18",
139
+ "@matterbridge/dgram": "3.10.14-dev-20261013-e87a0c8",
140
+ "@matterbridge/thread": "3.10.14-dev-20261013-e87a0c8",
141
+ "@matterbridge/types": "3.10.14-dev-20261013-e87a0c8",
142
+ "@matterbridge/utils": "3.10.14-dev-20261013-e87a0c8",
143
143
  "escape-html": "1.0.3",
144
144
  "express": "5.2.1",
145
145
  "express-rate-limit": "8.7.1",