matterbridge 3.3.8-dev-20251115-920acfc → 3.3.8-dev-20251116-59b0ba9

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.
@@ -47,13 +47,9 @@ export class Oven extends MatterbridgeEndpoint {
47
47
  endpoint.behaviors.require(MatterbridgeOvenCavityOperationalStateServer, {
48
48
  phaseList: phaseList || null,
49
49
  currentPhase: currentPhase || null,
50
- operationalStateList: [
51
- { operationalStateId: OperationalState.OperationalStateEnum.Stopped, operationalStateLabel: 'Stopped' },
52
- { operationalStateId: OperationalState.OperationalStateEnum.Running, operationalStateLabel: 'Running' },
53
- { operationalStateId: OperationalState.OperationalStateEnum.Error, operationalStateLabel: 'Error' },
54
- ],
50
+ operationalStateList: [{ operationalStateId: OperationalState.OperationalStateEnum.Stopped }, { operationalStateId: OperationalState.OperationalStateEnum.Running }, { operationalStateId: OperationalState.OperationalStateEnum.Error }],
55
51
  operationalState,
56
- operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
52
+ operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
57
53
  });
58
54
  return endpoint;
59
55
  }
@@ -82,24 +78,24 @@ export class MatterbridgeOvenCavityOperationalStateServer extends OvenCavityOper
82
78
  const device = this.endpoint.stateOf(MatterbridgeServer);
83
79
  device.log.info('MatterbridgeOvenCavityOperationalStateServer initialized: setting operational state to Stopped and operational error to No error');
84
80
  this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
85
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
81
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
86
82
  }
87
83
  stop() {
88
84
  const device = this.endpoint.stateOf(MatterbridgeServer);
89
85
  device.log.info(`MatterbridgeOvenCavityOperationalStateServer: stop (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber}) called setting operational state to Stopped and operational error to No error`);
90
86
  this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
91
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
87
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
92
88
  return {
93
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
89
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
94
90
  };
95
91
  }
96
92
  start() {
97
93
  const device = this.endpoint.stateOf(MatterbridgeServer);
98
94
  device.log.info(`MatterbridgeOvenCavityOperationalStateServer: start (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber}) called setting operational state to Running and operational error to No error`);
99
95
  this.state.operationalState = OperationalState.OperationalStateEnum.Running;
100
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
96
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
101
97
  return {
102
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
98
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
103
99
  };
104
100
  }
105
101
  }
@@ -82,16 +82,16 @@ export class RoboticVacuumCleaner extends MatterbridgeEndpoint {
82
82
  phaseList,
83
83
  currentPhase,
84
84
  operationalStateList: operationalStateList ?? [
85
- { operationalStateId: RvcOperationalState.OperationalState.Stopped, operationalStateLabel: 'Stopped' },
86
- { operationalStateId: RvcOperationalState.OperationalState.Running, operationalStateLabel: 'Running' },
87
- { operationalStateId: RvcOperationalState.OperationalState.Paused, operationalStateLabel: 'Paused' },
88
- { operationalStateId: RvcOperationalState.OperationalState.Error, operationalStateLabel: 'Error' },
89
- { operationalStateId: RvcOperationalState.OperationalState.SeekingCharger, operationalStateLabel: 'SeekingCharger' },
90
- { operationalStateId: RvcOperationalState.OperationalState.Charging, operationalStateLabel: 'Charging' },
91
- { operationalStateId: RvcOperationalState.OperationalState.Docked, operationalStateLabel: 'Docked' },
85
+ { operationalStateId: RvcOperationalState.OperationalState.Stopped },
86
+ { operationalStateId: RvcOperationalState.OperationalState.Running },
87
+ { operationalStateId: RvcOperationalState.OperationalState.Paused },
88
+ { operationalStateId: RvcOperationalState.OperationalState.Error },
89
+ { operationalStateId: RvcOperationalState.OperationalState.SeekingCharger },
90
+ { operationalStateId: RvcOperationalState.OperationalState.Charging },
91
+ { operationalStateId: RvcOperationalState.OperationalState.Docked },
92
92
  ],
93
93
  operationalState: operationalState ?? RvcOperationalState.OperationalState.Docked,
94
- operationalError: operationalError ?? { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' },
94
+ operationalError: operationalError ?? { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
95
95
  });
96
96
  return this;
97
97
  }
@@ -145,9 +145,9 @@ export class MatterbridgeRvcOperationalStateServer extends RvcOperationalStateSe
145
145
  device.log.debug('MatterbridgeRvcOperationalStateServer: pause called setting operational state to Paused and currentMode to Idle');
146
146
  this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
147
147
  this.state.operationalState = RvcOperationalState.OperationalState.Paused;
148
- this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
148
+ this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
149
149
  return {
150
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
150
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
151
151
  };
152
152
  }
153
153
  resume() {
@@ -157,9 +157,9 @@ export class MatterbridgeRvcOperationalStateServer extends RvcOperationalStateSe
157
157
  device.log.debug('MatterbridgeRvcOperationalStateServer: resume called setting operational state to Running and currentMode to Cleaning');
158
158
  this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 2;
159
159
  this.state.operationalState = RvcOperationalState.OperationalState.Running;
160
- this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
160
+ this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
161
161
  return {
162
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
162
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
163
163
  };
164
164
  }
165
165
  goHome() {
@@ -169,9 +169,9 @@ export class MatterbridgeRvcOperationalStateServer extends RvcOperationalStateSe
169
169
  device.log.debug('MatterbridgeRvcOperationalStateServer: goHome called setting operational state to Docked and currentMode to Idle');
170
170
  this.agent.get(MatterbridgeRvcRunModeServer).state.currentMode = 1;
171
171
  this.state.operationalState = RvcOperationalState.OperationalState.Docked;
172
- this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateLabel: 'No Error', errorStateDetails: 'Fully operational' };
172
+ this.state.operationalError = { errorStateId: RvcOperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
173
173
  return {
174
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
174
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
175
175
  };
176
176
  }
177
177
  }
@@ -1,14 +1,15 @@
1
1
  import { rmSync } from 'node:fs';
2
2
  import { inspect } from 'node:util';
3
3
  import path from 'node:path';
4
- import { AnsiLogger } from 'node-ansi-logger';
4
+ import { AnsiLogger, er, rs } from 'node-ansi-logger';
5
5
  import { LogLevel as MatterLogLevel, LogFormat as MatterLogFormat, Environment, Lifecycle } from '@matter/general';
6
6
  import { Endpoint, ServerNode, ServerNodeStore } from '@matter/node';
7
7
  import { DeviceTypeId, VendorId } from '@matter/types/datatype';
8
- import { AggregatorEndpoint, RootEndpoint } from '@matter/node/endpoints';
8
+ import { AggregatorEndpoint } from '@matter/node/endpoints';
9
9
  import { MdnsService } from '@matter/main/protocol';
10
10
  import { Matterbridge } from '../matterbridge.js';
11
11
  import { MATTER_STORAGE_NAME } from '../matterbridgeTypes.js';
12
+ import { bridge } from '../matterbridgeDeviceTypes.js';
12
13
  export let loggerLogSpy;
13
14
  export let loggerDebugSpy;
14
15
  export let loggerInfoSpy;
@@ -255,13 +256,15 @@ export async function assertAllEndpointNumbersPersisted(targetServer) {
255
256
  }
256
257
  return all.length;
257
258
  }
258
- export async function startServerNode(name, port) {
259
+ export async function startServerNode(name, port, deviceType = bridge.code) {
260
+ const { randomBytes } = await import('node:crypto');
261
+ const random = randomBytes(8).toString('hex');
259
262
  server = await ServerNode.create({
260
263
  id: name + 'ServerNode',
261
264
  environment,
262
265
  productDescription: {
263
266
  name: name + 'ServerNode',
264
- deviceType: DeviceTypeId(RootEndpoint.deviceType),
267
+ deviceType: DeviceTypeId(deviceType),
265
268
  vendorId: VendorId(0xfff1),
266
269
  productId: 0x8000,
267
270
  },
@@ -274,10 +277,17 @@ export async function startServerNode(name, port) {
274
277
  hardwareVersion: 1,
275
278
  softwareVersion: 1,
276
279
  reachable: true,
280
+ serialNumber: 'SN' + random,
281
+ uniqueId: 'UI' + random,
277
282
  },
278
283
  network: {
284
+ listeningAddressIpv4: undefined,
285
+ listeningAddressIpv6: undefined,
279
286
  port,
280
287
  },
288
+ operationalCredentials: {
289
+ certification: undefined,
290
+ },
281
291
  });
282
292
  expect(server).toBeDefined();
283
293
  expect(server.lifecycle.isReady).toBeTruthy();
@@ -338,7 +348,7 @@ export async function addDevice(owner, device, pause = 10) {
338
348
  catch (error) {
339
349
  const errorMessage = error instanceof Error ? error.message : error;
340
350
  const errorInspect = inspect(error, { depth: 10 });
341
- console.error(`Error adding device ${device.maybeId}.${device.maybeNumber}: ${errorMessage}\nstack: ${errorInspect}`);
351
+ process.stderr.write(`${er}Error adding device ${device.maybeId}.${device.maybeNumber}: ${errorMessage}${rs}\nStack: ${errorInspect}\n`);
342
352
  return false;
343
353
  }
344
354
  expect(owner.parts.has(device)).toBeTruthy();
@@ -363,7 +373,7 @@ export async function deleteDevice(owner, device, pause = 10) {
363
373
  catch (error) {
364
374
  const errorMessage = error instanceof Error ? error.message : error;
365
375
  const errorInspect = inspect(error, { depth: 10 });
366
- console.error(`Error deleting device ${device.maybeId}.${device.maybeNumber}: ${errorMessage}\nstack: ${errorInspect}`);
376
+ process.stderr.write(`${er}Error deleting device ${device.maybeId}.${device.maybeNumber}: ${errorMessage}${rs}\nStack: ${errorInspect}\n`);
367
377
  return false;
368
378
  }
369
379
  expect(owner.parts.has(device)).toBeFalsy();
@@ -423,7 +423,7 @@ export class MatterbridgeOperationalStateServer extends OperationalStateServer {
423
423
  const device = this.endpoint.stateOf(MatterbridgeServer);
424
424
  device.log.debug('MatterbridgeOperationalStateServer initialized: setting operational state to Stopped');
425
425
  this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
426
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
426
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
427
427
  super.initialize();
428
428
  }
429
429
  pause() {
@@ -432,9 +432,9 @@ export class MatterbridgeOperationalStateServer extends OperationalStateServer {
432
432
  device.commandHandler.executeHandler('pause', { request: {}, cluster: OperationalStateServer.id, attributes: this.state, endpoint: this.endpoint });
433
433
  device.log.debug('MatterbridgeOperationalStateServer: pause called setting operational state to Paused');
434
434
  this.state.operationalState = OperationalState.OperationalStateEnum.Paused;
435
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
435
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
436
436
  return {
437
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
437
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
438
438
  };
439
439
  }
440
440
  stop() {
@@ -443,9 +443,9 @@ export class MatterbridgeOperationalStateServer extends OperationalStateServer {
443
443
  device.commandHandler.executeHandler('stop', { request: {}, cluster: OperationalStateServer.id, attributes: this.state, endpoint: this.endpoint });
444
444
  device.log.debug('MatterbridgeOperationalStateServer: stop called setting operational state to Stopped');
445
445
  this.state.operationalState = OperationalState.OperationalStateEnum.Stopped;
446
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
446
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
447
447
  return {
448
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
448
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
449
449
  };
450
450
  }
451
451
  start() {
@@ -454,9 +454,9 @@ export class MatterbridgeOperationalStateServer extends OperationalStateServer {
454
454
  device.commandHandler.executeHandler('start', { request: {}, cluster: OperationalStateServer.id, attributes: this.state, endpoint: this.endpoint });
455
455
  device.log.debug('MatterbridgeOperationalStateServer: start called setting operational state to Running');
456
456
  this.state.operationalState = OperationalState.OperationalStateEnum.Running;
457
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
457
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
458
458
  return {
459
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
459
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
460
460
  };
461
461
  }
462
462
  resume() {
@@ -465,9 +465,9 @@ export class MatterbridgeOperationalStateServer extends OperationalStateServer {
465
465
  device.commandHandler.executeHandler('resume', { request: {}, cluster: OperationalStateServer.id, attributes: this.state, endpoint: this.endpoint });
466
466
  device.log.debug('MatterbridgeOperationalStateServer: resume called setting operational state to Running');
467
467
  this.state.operationalState = OperationalState.OperationalStateEnum.Running;
468
- this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' };
468
+ this.state.operationalError = { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' };
469
469
  return {
470
- commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
470
+ commandResponseState: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
471
471
  };
472
472
  }
473
473
  }
@@ -113,8 +113,13 @@ export function createUniqueId(param1, param2, param3, param4) {
113
113
  hash.update(param1 + param2 + param3 + param4);
114
114
  return hash.digest('hex');
115
115
  }
116
- export function featuresFor(endpoint, behavior) {
117
- return endpoint.behaviors.supported[lowercaseFirstLetter(behavior)]['cluster']['supportedFeatures'];
116
+ export function featuresFor(endpoint, cluster) {
117
+ const behaviorId = getBehavior(endpoint, cluster)?.id;
118
+ if (!behaviorId) {
119
+ endpoint.log?.error(`featuresFor error: cluster not found on endpoint ${or}${endpoint.maybeId}${er}:${or}${endpoint.maybeNumber}${er}`);
120
+ return {};
121
+ }
122
+ return endpoint.behaviors.supported[lowercaseFirstLetter(behaviorId)]['cluster']['supportedFeatures'];
118
123
  }
119
124
  export function getBehaviourTypesFromClusterServerIds(clusterServerList) {
120
125
  const behaviorTypes = [];
@@ -731,13 +736,13 @@ export function getDefaultOperationalStateClusterServer(operationalState = Opera
731
736
  currentPhase: null,
732
737
  countdownTime: null,
733
738
  operationalStateList: [
734
- { operationalStateId: OperationalState.OperationalStateEnum.Stopped, operationalStateLabel: 'Stopped' },
735
- { operationalStateId: OperationalState.OperationalStateEnum.Running, operationalStateLabel: 'Running' },
736
- { operationalStateId: OperationalState.OperationalStateEnum.Paused, operationalStateLabel: 'Paused' },
737
- { operationalStateId: OperationalState.OperationalStateEnum.Error, operationalStateLabel: 'Error' },
739
+ { operationalStateId: OperationalState.OperationalStateEnum.Stopped },
740
+ { operationalStateId: OperationalState.OperationalStateEnum.Running },
741
+ { operationalStateId: OperationalState.OperationalStateEnum.Paused },
742
+ { operationalStateId: OperationalState.OperationalStateEnum.Error },
738
743
  ],
739
744
  operationalState,
740
- operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateLabel: 'No error', errorStateDetails: 'Fully operational' },
745
+ operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
741
746
  });
742
747
  }
743
748
  export function getDefaultTemperatureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.3.8-dev-20251115-920acfc",
3
+ "version": "3.3.8-dev-20251116-59b0ba9",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge",
9
- "version": "3.3.8-dev-20251115-920acfc",
9
+ "version": "3.3.8-dev-20251116-59b0ba9",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@matter/main": "0.15.6",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.3.8-dev-20251115-920acfc",
3
+ "version": "3.3.8-dev-20251116-59b0ba9",
4
4
  "description": "Matterbridge plugin manager for Matter",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",