matterbridge 3.3.3-dev-20251016-70a1c5b → 3.3.3-dev-20251018-66ae7a4

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/CHANGELOG.md CHANGED
@@ -33,6 +33,8 @@ Advantages:
33
33
  - [frontend]: Added icon to open the cpu and memory usage in System Information panel.
34
34
  - [thermostat]: Added thermostatRunningState attribute. Thanks Ludovic BOUÉ (https://github.com/Luligu/matterbridge/pull/410).
35
35
  - [ElectricalPowerMeasurement]: Added createApparentElectricalPowerMeasurementClusterServer cluster helper. Thanks Ludovic BOUÉ (https://github.com/Luligu/matterbridge/pull/411).
36
+ - [DeviceEnergyManagementMode]: Added logic to set optOutState. Thanks Ludovic BOUÉ (https://github.com/Luligu/matterbridge-example-dynamic-platform/issues/34).
37
+ - [Thermostat]: Added provisional support for setActivePresetRequest. Thanks Ludovic BOUÉ (https://github.com/Luligu/matterbridge-example-dynamic-platform/issues/38).
36
38
 
37
39
  ### Changed
38
40
 
@@ -1,12 +1,13 @@
1
1
  import { AnsiLogger, BLUE, CYAN, db, debugStringify, er, wr } from 'node-ansi-logger';
2
2
  import { dev } from './matterbridgeTypes.js';
3
3
  import { BroadcastServer } from './broadcastServer.js';
4
+ import { hasParameter } from './utils/commandLine.js';
4
5
  export class DeviceManager {
5
6
  _devices = new Map();
6
7
  log;
7
8
  server;
8
9
  constructor() {
9
- this.log = new AnsiLogger({ logName: 'DeviceManager', logTimestampFormat: 4, logLevel: "info" });
10
+ this.log = new AnsiLogger({ logName: 'DeviceManager', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
10
11
  this.log.debug('Matterbridge device manager starting...');
11
12
  this.server = new BroadcastServer('devices', this.log);
12
13
  this.server.on('broadcast_message', this.msgHandler.bind(this));
package/dist/frontend.js CHANGED
@@ -35,7 +35,7 @@ export class Frontend extends EventEmitter {
35
35
  this.matterbridge = matterbridge;
36
36
  this.log = new AnsiLogger({ logName: 'Frontend', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
37
37
  this.log.logNameColor = '\x1b[38;5;97m';
38
- this.server = new BroadcastServer('plugins', this.log);
38
+ this.server = new BroadcastServer('frontend', this.log);
39
39
  this.server.on('broadcast_message', this.msgHandler.bind(this));
40
40
  }
41
41
  destroy() {
@@ -1547,6 +1547,13 @@ export class Frontend extends EventEmitter {
1547
1547
  else if (data.params.value === 'Fatal') {
1548
1548
  Logger.level = MatterLogLevel.FATAL;
1549
1549
  }
1550
+ let callbackLogLevel = "notice";
1551
+ if (this.matterbridge.getLogLevel() === "info" || Logger.level === MatterLogLevel.INFO)
1552
+ callbackLogLevel = "info";
1553
+ if (this.matterbridge.getLogLevel() === "debug" || Logger.level === MatterLogLevel.DEBUG)
1554
+ callbackLogLevel = "debug";
1555
+ AnsiLogger.setGlobalCallbackLevel(callbackLogLevel);
1556
+ this.log.debug(`WebSocketServer logger global callback set to ${callbackLogLevel}`);
1550
1557
  await this.matterbridge.nodeContext?.set('matterLogLevel', Logger.level);
1551
1558
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
1552
1559
  }
@@ -1133,8 +1133,12 @@ export class Matterbridge extends EventEmitter {
1133
1133
  this.emit('cleanup_completed');
1134
1134
  }
1135
1135
  else {
1136
- if (!this.initialized)
1136
+ if (!this.initialized) {
1137
1137
  this.log.debug('Cleanup with instance not initialized...');
1138
+ this.frontend.destroy();
1139
+ this.plugins.destroy();
1140
+ this.devices.destroy();
1141
+ }
1138
1142
  if (this.hasCleanupStarted)
1139
1143
  this.log.debug('Cleanup already started...');
1140
1144
  }
@@ -1,21 +1,23 @@
1
1
  import { Behavior } from '@matter/main';
2
- import { BooleanStateConfiguration } from '@matter/main/clusters/boolean-state-configuration';
3
- import { ColorControl } from '@matter/main/clusters/color-control';
4
- import { FanControl } from '@matter/main/clusters/fan-control';
5
- import { WindowCovering } from '@matter/main/clusters/window-covering';
6
- import { Thermostat } from '@matter/main/clusters/thermostat';
7
- import { ValveConfigurationAndControl } from '@matter/main/clusters/valve-configuration-and-control';
8
- import { SmokeCoAlarm } from '@matter/main/clusters/smoke-co-alarm';
9
- import { BooleanStateConfigurationServer } from '@matter/main/behaviors/boolean-state-configuration';
10
- import { OperationalState } from '@matter/main/clusters/operational-state';
11
- import { ModeBase } from '@matter/main/clusters/mode-base';
12
- import { ServiceArea } from '@matter/main/clusters/service-area';
2
+ import { BooleanStateConfiguration } from '@matter/types/clusters/boolean-state-configuration';
3
+ import { ColorControl } from '@matter/types/clusters/color-control';
4
+ import { FanControl } from '@matter/types/clusters/fan-control';
5
+ import { WindowCovering } from '@matter/types/clusters/window-covering';
6
+ import { Thermostat } from '@matter/types/clusters/thermostat';
7
+ import { ValveConfigurationAndControl } from '@matter/types/clusters/valve-configuration-and-control';
8
+ import { SmokeCoAlarm } from '@matter/types/clusters/smoke-co-alarm';
9
+ import { OperationalState } from '@matter/types/clusters/operational-state';
10
+ import { ModeBase } from '@matter/types/clusters/mode-base';
11
+ import { ServiceArea } from '@matter/types/clusters/service-area';
12
+ import { DeviceEnergyManagement } from '@matter/types/clusters/device-energy-management';
13
13
  import { ResourceMonitoring } from '@matter/types/clusters/resource-monitoring';
14
+ import { DeviceEnergyManagementMode } from '@matter/types/clusters/device-energy-management-mode';
14
15
  import { IdentifyServer } from '@matter/main/behaviors/identify';
15
16
  import { OnOffServer } from '@matter/main/behaviors/on-off';
16
17
  import { LevelControlServer } from '@matter/main/behaviors/level-control';
17
18
  import { ColorControlServer } from '@matter/main/behaviors/color-control';
18
19
  import { WindowCoveringServer } from '@matter/main/behaviors/window-covering';
20
+ import { BooleanStateConfigurationServer } from '@matter/main/behaviors/boolean-state-configuration';
19
21
  import { DoorLockServer } from '@matter/main/behaviors/door-lock';
20
22
  import { FanControlServer } from '@matter/main/behaviors/fan-control';
21
23
  import { ThermostatServer } from '@matter/main/behaviors/thermostat';
@@ -321,6 +323,35 @@ export class MatterbridgeThermostatServer extends ThermostatServer.with(Thermost
321
323
  }
322
324
  }
323
325
  }
326
+ export class MatterbridgePresetThermostatServer extends ThermostatServer.with(Thermostat.Feature.Presets, Thermostat.Feature.Cooling, Thermostat.Feature.Heating, Thermostat.Feature.AutoMode) {
327
+ setpointRaiseLower(request) {
328
+ const device = this.endpoint.stateOf(MatterbridgeServer);
329
+ device.log.info(`Setting setpoint by ${request.amount} in mode ${request.mode} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
330
+ device.commandHandler.executeHandler('setpointRaiseLower', { request, cluster: ThermostatServer.id, attributes: this.state, endpoint: this.endpoint });
331
+ const lookupSetpointAdjustMode = ['Heat', 'Cool', 'Both'];
332
+ device.log.debug(`MatterbridgeThermostatServer: setpointRaiseLower called with mode: ${lookupSetpointAdjustMode[request.mode]} amount: ${request.amount / 10}`);
333
+ if (this.state.occupiedHeatingSetpoint !== undefined)
334
+ device.log.debug(`- current occupiedHeatingSetpoint: ${this.state.occupiedHeatingSetpoint / 100}`);
335
+ if (this.state.occupiedCoolingSetpoint !== undefined)
336
+ device.log.debug(`- current occupiedCoolingSetpoint: ${this.state.occupiedCoolingSetpoint / 100}`);
337
+ if ((request.mode === Thermostat.SetpointRaiseLowerMode.Heat || request.mode === Thermostat.SetpointRaiseLowerMode.Both) && this.state.occupiedHeatingSetpoint !== undefined) {
338
+ const setpoint = this.state.occupiedHeatingSetpoint / 100 + request.amount / 10;
339
+ this.state.occupiedHeatingSetpoint = setpoint * 100;
340
+ device.log.debug(`Set occupiedHeatingSetpoint to ${setpoint}`);
341
+ }
342
+ if ((request.mode === Thermostat.SetpointRaiseLowerMode.Cool || request.mode === Thermostat.SetpointRaiseLowerMode.Both) && this.state.occupiedCoolingSetpoint !== undefined) {
343
+ const setpoint = this.state.occupiedCoolingSetpoint / 100 + request.amount / 10;
344
+ this.state.occupiedCoolingSetpoint = setpoint * 100;
345
+ device.log.debug(`Set occupiedCoolingSetpoint to ${setpoint}`);
346
+ }
347
+ }
348
+ setActivePresetRequest(request) {
349
+ const device = this.endpoint.stateOf(MatterbridgeServer);
350
+ device.log.info(`Setting preset to ${request.presetHandle} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
351
+ device.commandHandler.executeHandler('setActivePresetRequest', { request, cluster: ThermostatServer.id, attributes: this.state, endpoint: this.endpoint });
352
+ device.log.debug(`MatterbridgePresetThermostatServer: setActivePresetRequest called with presetHandle: ${request.presetHandle}`);
353
+ }
354
+ }
324
355
  export class MatterbridgeValveConfigurationAndControlServer extends ValveConfigurationAndControlServer.with(ValveConfigurationAndControl.Feature.Level) {
325
356
  open(request) {
326
357
  const device = this.endpoint.stateOf(MatterbridgeServer);
@@ -467,7 +498,7 @@ export class MatterbridgeActivatedCarbonFilterMonitoringServer extends Activated
467
498
  device.log.debug(`MatterbridgeActivatedCarbonFilterMonitoringServer: resetCondition called`);
468
499
  }
469
500
  }
470
- export class MatterbridgeDeviceEnergyManagementServer extends DeviceEnergyManagementServer {
501
+ export class MatterbridgeDeviceEnergyManagementServer extends DeviceEnergyManagementServer.with(DeviceEnergyManagement.Feature.PowerForecastReporting, DeviceEnergyManagement.Feature.PowerAdjustment) {
471
502
  powerAdjustRequest(request) {
472
503
  const device = this.endpoint.stateOf(MatterbridgeServer);
473
504
  device.log.info(`Adjusting power to ${request.power} duration ${request.duration} cause ${request.cause} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
@@ -492,6 +523,14 @@ export class MatterbridgeDeviceEnergyManagementModeServer extends DeviceEnergyMa
492
523
  return { status: ModeBase.ModeChangeStatus.UnsupportedMode, statusText: 'Unsupported mode' };
493
524
  }
494
525
  this.state.currentMode = request.newMode;
526
+ if (supported.modeTags.find((tag) => tag.value === DeviceEnergyManagementMode.ModeTag.NoOptimization)) {
527
+ if (this.endpoint.behaviors.has(DeviceEnergyManagementServer))
528
+ this.endpoint.setStateOf(DeviceEnergyManagementServer.with(DeviceEnergyManagement.Feature.PowerForecastReporting, DeviceEnergyManagement.Feature.PowerAdjustment), { optOutState: DeviceEnergyManagement.OptOutState.OptOut });
529
+ }
530
+ else {
531
+ if (this.endpoint.behaviors.has(DeviceEnergyManagementServer))
532
+ this.endpoint.setStateOf(DeviceEnergyManagementServer.with(DeviceEnergyManagement.Feature.PowerForecastReporting, DeviceEnergyManagement.Feature.PowerAdjustment), { optOutState: DeviceEnergyManagement.OptOutState.NoOptOut });
533
+ }
495
534
  device.log.debug(`MatterbridgeDeviceEnergyManagementModeServer changeToMode called with newMode ${request.newMode} => ${supported.label}`);
496
535
  return super.changeToMode(request);
497
536
  }
@@ -1157,13 +1157,14 @@ export class MatterbridgeEndpoint extends Endpoint {
1157
1157
  }
1158
1158
  createDefaultDeviceEnergyManagementClusterServer(esaType = DeviceEnergyManagement.EsaType.Other, esaCanGenerate = false, esaState = DeviceEnergyManagement.EsaState.Online, absMinPower = 0, absMaxPower = 0) {
1159
1159
  this.behaviors.require(MatterbridgeDeviceEnergyManagementServer.with(DeviceEnergyManagement.Feature.PowerForecastReporting, DeviceEnergyManagement.Feature.PowerAdjustment), {
1160
- forecast: null,
1161
- powerAdjustmentCapability: null,
1162
1160
  esaType,
1163
1161
  esaCanGenerate,
1164
1162
  esaState,
1165
1163
  absMinPower,
1166
1164
  absMaxPower,
1165
+ powerAdjustmentCapability: null,
1166
+ optOutState: DeviceEnergyManagement.OptOutState.NoOptOut,
1167
+ forecast: null,
1167
1168
  });
1168
1169
  return this;
1169
1170
  }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.3.3-dev-20251016-70a1c5b",
3
+ "version": "3.3.3-dev-20251018-66ae7a4",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge",
9
- "version": "3.3.3-dev-20251016-70a1c5b",
9
+ "version": "3.3.3-dev-20251018-66ae7a4",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@matter/main": "0.15.5",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.3.3-dev-20251016-70a1c5b",
3
+ "version": "3.3.3-dev-20251018-66ae7a4",
4
4
  "description": "Matterbridge plugin manager for Matter",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",