@matterbridge/core 3.5.6 → 3.6.0-dev-20260302-e3a7eb0

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.
@@ -10,10 +10,15 @@ export declare class Evse extends MatterbridgeEndpoint {
10
10
  createDefaultEnergyEvseClusterServer(state?: EnergyEvse.State, supplyState?: EnergyEvse.SupplyState, faultState?: EnergyEvse.FaultState): this;
11
11
  createDefaultEnergyEvseModeClusterServer(currentMode?: number, supportedModes?: EnergyEvseMode.ModeOption[]): this;
12
12
  }
13
- export declare class MatterbridgeEnergyEvseServer extends EnergyEvseServer {
13
+ declare const MatterbridgeEnergyEvseServer_base: import("@matter/node").ClusterBehavior.Type<import("@matter/types").ClusterComposer.WithFeatures<EnergyEvse.Cluster, readonly [EnergyEvse.Feature.ChargingPreferences]>, typeof EnergyEvseServer, import("@matter/node/behaviors/energy-evse").EnergyEvseInterface>;
14
+ export declare class MatterbridgeEnergyEvseServer extends MatterbridgeEnergyEvseServer_base {
14
15
  disable(): MaybePromise;
15
16
  enableCharging(request: EnergyEvse.EnableChargingRequest): MaybePromise;
17
+ setTargets(request: EnergyEvse.SetTargetsRequest): MaybePromise;
18
+ getTargets(): MaybePromise<EnergyEvse.GetTargetsResponse>;
19
+ clearTargets(): MaybePromise;
16
20
  }
17
21
  export declare class MatterbridgeEnergyEvseModeServer extends EnergyEvseModeServer {
18
22
  changeToMode(request: ModeBase.ChangeToModeRequest): MaybePromise<ModeBase.ChangeToModeResponse>;
19
23
  }
24
+ export {};
@@ -9,21 +9,27 @@ import { deviceEnergyManagement, electricalSensor, evse, powerSource } from '../
9
9
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
10
10
  export class Evse extends MatterbridgeEndpoint {
11
11
  constructor(name, serial, currentMode, supportedModes, state, supplyState, faultState, voltage = null, current = null, power = null, energy = null, absMinPower, absMaxPower) {
12
- super([evse, powerSource, electricalSensor, deviceEnergyManagement], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
12
+ super([evse], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
13
13
  this.createDefaultIdentifyClusterServer()
14
14
  .createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Evse')
15
- .createDefaultPowerSourceWiredClusterServer()
15
+ .createDefaultEnergyEvseClusterServer(state, supplyState, faultState)
16
+ .createDefaultEnergyEvseModeClusterServer(currentMode, supportedModes)
17
+ .createDefaultTemperatureMeasurementClusterServer(24_00)
18
+ .addRequiredClusterServers();
19
+ this.addFixedLabel('composed', 'EVSE');
20
+ this.addChildDeviceType('PowerSource', powerSource).createDefaultPowerSourceWiredClusterServer().addRequiredClusterServers();
21
+ this.addChildDeviceType('ElectricalSensor', electricalSensor)
16
22
  .createDefaultPowerTopologyClusterServer()
17
23
  .createDefaultElectricalPowerMeasurementClusterServer(voltage, current, power)
18
24
  .createDefaultElectricalEnergyMeasurementClusterServer(energy, 0)
25
+ .addRequiredClusterServers();
26
+ this.addChildDeviceType('DeviceEnergyManagement', deviceEnergyManagement)
19
27
  .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.Evse, false, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
20
28
  .createDefaultDeviceEnergyManagementModeClusterServer()
21
- .createDefaultEnergyEvseClusterServer(state, supplyState, faultState)
22
- .createDefaultEnergyEvseModeClusterServer(currentMode, supportedModes)
23
29
  .addRequiredClusterServers();
24
30
  }
25
31
  createDefaultEnergyEvseClusterServer(state, supplyState, faultState) {
26
- this.behaviors.require(MatterbridgeEnergyEvseServer, {
32
+ this.behaviors.require(MatterbridgeEnergyEvseServer.with(EnergyEvse.Feature.ChargingPreferences), {
27
33
  state: state !== undefined ? state : EnergyEvse.State.NotPluggedIn,
28
34
  supplyState: supplyState !== undefined ? supplyState : EnergyEvse.SupplyState.ChargingEnabled,
29
35
  faultState: faultState !== undefined ? faultState : EnergyEvse.FaultState.NoError,
@@ -50,7 +56,7 @@ export class Evse extends MatterbridgeEndpoint {
50
56
  return this;
51
57
  }
52
58
  }
53
- export class MatterbridgeEnergyEvseServer extends EnergyEvseServer {
59
+ export class MatterbridgeEnergyEvseServer extends EnergyEvseServer.with(EnergyEvse.Feature.ChargingPreferences) {
54
60
  disable() {
55
61
  const device = this.endpoint.stateOf(MatterbridgeServer);
56
62
  device.log.info(`Disable charging (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
@@ -74,6 +80,21 @@ export class MatterbridgeEnergyEvseServer extends EnergyEvseServer {
74
80
  this.state.minimumChargeCurrent = request.minimumChargeCurrent;
75
81
  this.state.maximumChargeCurrent = request.maximumChargeCurrent;
76
82
  }
83
+ setTargets(request) {
84
+ const device = this.endpoint.stateOf(MatterbridgeServer);
85
+ device.log.info(`SetTargets request ${request.chargingTargetSchedules} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
86
+ return;
87
+ }
88
+ getTargets() {
89
+ const device = this.endpoint.stateOf(MatterbridgeServer);
90
+ device.log.info(`GetTargets (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
91
+ return { chargingTargetSchedules: [] };
92
+ }
93
+ clearTargets() {
94
+ const device = this.endpoint.stateOf(MatterbridgeServer);
95
+ device.log.info(`ClearTargets (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
96
+ return;
97
+ }
77
98
  }
78
99
  export class MatterbridgeEnergyEvseModeServer extends EnergyEvseModeServer {
79
100
  changeToMode(request) {
@@ -8,7 +8,7 @@ import { OvenMode } from '@matter/types/clusters/oven-mode';
8
8
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
9
9
  export declare class Oven extends MatterbridgeEndpoint {
10
10
  constructor(name: string, serial: string);
11
- addCabinet(name: string, tagList: Semtag[], currentMode?: number, supportedModes?: OvenMode.ModeOption[], selectedTemperatureLevel?: number, supportedTemperatureLevels?: string[], operationalState?: OperationalState.OperationalStateEnum, currentPhase?: number, phaseList?: string[]): MatterbridgeEndpoint;
11
+ addCabinet(name: string, tagList: Semtag[], currentMode?: number, supportedModes?: OvenMode.ModeOption[], targetTemperature?: number, minTemperature?: number, maxTemperature?: number, step?: number, currentTemperature?: number, operationalState?: OperationalState.OperationalStateEnum, currentPhase?: number, phaseList?: string[]): MatterbridgeEndpoint;
12
12
  createDefaultOvenModeClusterServer(endpoint: MatterbridgeEndpoint, currentMode: number, supportedModes: OvenMode.ModeOption[]): MatterbridgeEndpoint;
13
13
  createDefaultOvenCavityOperationalStateClusterServer(endpoint: MatterbridgeEndpoint, operationalState?: OperationalState.OperationalStateEnum, currentPhase?: number, phaseList?: string[]): MatterbridgeEndpoint;
14
14
  }
@@ -6,7 +6,7 @@ import { OvenMode } from '@matter/types/clusters/oven-mode';
6
6
  import { MatterbridgeServer } from '../matterbridgeBehaviors.js';
7
7
  import { oven, powerSource, temperatureControlledCabinetHeater } from '../matterbridgeDeviceTypes.js';
8
8
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
9
- import { createLevelTemperatureControlClusterServer } from './temperatureControl.js';
9
+ import { createNumberTemperatureControlClusterServer } from './temperatureControl.js';
10
10
  export class Oven extends MatterbridgeEndpoint {
11
11
  constructor(name, serial) {
12
12
  super([oven, powerSource], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
@@ -26,12 +26,11 @@ export class Oven extends MatterbridgeEndpoint {
26
26
  { label: 'Warming', mode: 8, modeTags: [{ value: OvenMode.ModeTag.Warming }] },
27
27
  { label: 'Proofing', mode: 9, modeTags: [{ value: OvenMode.ModeTag.Proofing }] },
28
28
  { label: 'Steam', mode: 10, modeTags: [{ value: OvenMode.ModeTag.Steam }] },
29
- ], selectedTemperatureLevel = 1, supportedTemperatureLevels = ['Defrost', '180°', '190°', '200°', '250°', '300°'], operationalState = OperationalState.OperationalStateEnum.Stopped, currentPhase, phaseList) {
29
+ ], targetTemperature = 180 * 100, minTemperature = 30 * 100, maxTemperature = 300 * 100, step = 10 * 100, currentTemperature = 20 * 100, operationalState = OperationalState.OperationalStateEnum.Stopped, currentPhase, phaseList) {
30
30
  const cabinet = this.addChildDeviceType(name, temperatureControlledCabinetHeater, { tagList }, true);
31
31
  cabinet.log.logName = name;
32
- cabinet.createDefaultIdentifyClusterServer();
33
- createLevelTemperatureControlClusterServer(cabinet, selectedTemperatureLevel, supportedTemperatureLevels);
34
- cabinet.createDefaultTemperatureMeasurementClusterServer(2000);
32
+ createNumberTemperatureControlClusterServer(cabinet, targetTemperature, minTemperature, maxTemperature, step);
33
+ cabinet.createDefaultTemperatureMeasurementClusterServer(currentTemperature);
35
34
  this.createDefaultOvenModeClusterServer(cabinet, currentMode, supportedModes);
36
35
  this.createDefaultOvenCavityOperationalStateClusterServer(cabinet, operationalState, currentPhase, phaseList);
37
36
  return cabinet;
@@ -5,12 +5,12 @@ import { ModeBase } from '@matter/types/clusters/mode-base';
5
5
  import { RefrigeratorAndTemperatureControlledCabinetMode } from '@matter/types/clusters/refrigerator-and-temperature-controlled-cabinet-mode';
6
6
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
7
7
  export declare class Refrigerator extends MatterbridgeEndpoint {
8
- constructor(name: string, serial: string);
9
- addCabinet(name: string, tagList: Semtag[], currentMode?: number, supportedModes?: RefrigeratorAndTemperatureControlledCabinetMode.ModeOption[], selectedTemperatureLevel?: number, supportedTemperatureLevels?: string[], currentTemperature?: number): MatterbridgeEndpoint;
8
+ constructor(name: string, serial: string, currentMode?: number, supportedModes?: RefrigeratorAndTemperatureControlledCabinetMode.ModeOption[]);
9
+ addCabinet(name: string, tagList: Semtag[], targetTemperature?: number, minTemperature?: number, maxTemperature?: number, step?: number, currentTemperature?: number): MatterbridgeEndpoint;
10
10
  createDefaultRefrigeratorAndTemperatureControlledCabinetModeClusterServer(endpoint: MatterbridgeEndpoint, currentMode: number, supportedModes: RefrigeratorAndTemperatureControlledCabinetMode.ModeOption[]): MatterbridgeEndpoint;
11
11
  createDefaultRefrigeratorAlarmClusterServer(endpoint: MatterbridgeEndpoint, doorOpen?: boolean): MatterbridgeEndpoint;
12
- setDoorOpenState(cabinetName: string, doorOpen: boolean): Promise<MatterbridgeEndpoint | undefined>;
13
- triggerDoorOpenState(cabinetName: string, doorOpen: boolean): Promise<MatterbridgeEndpoint | undefined>;
12
+ setDoorOpenState(doorOpen: boolean): Promise<MatterbridgeEndpoint>;
13
+ triggerDoorOpenState(doorOpen: boolean): Promise<MatterbridgeEndpoint>;
14
14
  }
15
15
  export declare class MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer extends RefrigeratorAndTemperatureControlledCabinetModeServer {
16
16
  initialize(): void;
@@ -5,26 +5,25 @@ import { RefrigeratorAndTemperatureControlledCabinetMode } from '@matter/types/c
5
5
  import { MatterbridgeServer } from '../matterbridgeBehaviors.js';
6
6
  import { powerSource, refrigerator, temperatureControlledCabinetCooler } from '../matterbridgeDeviceTypes.js';
7
7
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
8
- import { createLevelTemperatureControlClusterServer } from './temperatureControl.js';
8
+ import { createNumberTemperatureControlClusterServer } from './temperatureControl.js';
9
9
  export class Refrigerator extends MatterbridgeEndpoint {
10
- constructor(name, serial) {
10
+ constructor(name, serial, currentMode = 1, supportedModes = [
11
+ { label: 'Auto', mode: 1, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.Auto }] },
12
+ { label: 'RapidCool', mode: 2, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.RapidCool }] },
13
+ { label: 'RapidFreeze', mode: 3, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.RapidFreeze }] },
14
+ ]) {
11
15
  super([refrigerator, powerSource], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
12
16
  this.createDefaultIdentifyClusterServer();
13
17
  this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Refrigerator');
14
18
  this.createDefaultPowerSourceWiredClusterServer();
15
19
  this.addFixedLabel('composed', 'Refrigerator');
20
+ this.createDefaultRefrigeratorAndTemperatureControlledCabinetModeClusterServer(this, currentMode, supportedModes);
21
+ this.createDefaultRefrigeratorAlarmClusterServer(this, false);
16
22
  }
17
- addCabinet(name, tagList, currentMode = 1, supportedModes = [
18
- { label: 'Auto', mode: 1, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.Auto }] },
19
- { label: 'RapidCool', mode: 2, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.RapidCool }] },
20
- { label: 'RapidFreeze', mode: 3, modeTags: [{ value: RefrigeratorAndTemperatureControlledCabinetMode.ModeTag.RapidFreeze }] },
21
- ], selectedTemperatureLevel = 2, supportedTemperatureLevels = ['Level 1', 'Level 2', 'Level 3', 'Level 4', 'Level 5'], currentTemperature = 1000) {
23
+ addCabinet(name, tagList, targetTemperature = 10 * 100, minTemperature = -30 * 100, maxTemperature = 20 * 100, step = 1 * 100, currentTemperature = 10 * 100) {
22
24
  const cabinet = this.addChildDeviceType(name, temperatureControlledCabinetCooler, { tagList });
23
25
  cabinet.log.logName = name;
24
- cabinet.createDefaultIdentifyClusterServer();
25
- createLevelTemperatureControlClusterServer(cabinet, selectedTemperatureLevel, supportedTemperatureLevels);
26
- this.createDefaultRefrigeratorAndTemperatureControlledCabinetModeClusterServer(cabinet, currentMode, supportedModes);
27
- this.createDefaultRefrigeratorAlarmClusterServer(cabinet, false);
26
+ createNumberTemperatureControlClusterServer(cabinet, targetTemperature, minTemperature, maxTemperature, step);
28
27
  cabinet.createDefaultTemperatureMeasurementClusterServer(currentTemperature);
29
28
  return cabinet;
30
29
  }
@@ -43,24 +42,18 @@ export class Refrigerator extends MatterbridgeEndpoint {
43
42
  });
44
43
  return endpoint;
45
44
  }
46
- async setDoorOpenState(cabinetName, doorOpen) {
47
- const endpoint = this.getChildEndpointByName(cabinetName);
48
- if (endpoint) {
49
- await endpoint.setAttribute('RefrigeratorAlarm', 'state', { doorOpen }, endpoint.log);
50
- return endpoint;
51
- }
45
+ async setDoorOpenState(doorOpen) {
46
+ await this.setAttribute('RefrigeratorAlarm', 'state', { doorOpen }, this.log);
47
+ return this;
52
48
  }
53
- async triggerDoorOpenState(cabinetName, doorOpen) {
54
- const endpoint = this.getChildEndpointByName(cabinetName);
55
- if (endpoint) {
56
- if (doorOpen) {
57
- await endpoint.triggerEvent('RefrigeratorAlarm', 'notify', { active: { doorOpen: true }, inactive: { doorOpen: false }, state: { doorOpen: true }, mask: { doorOpen: true } }, endpoint.log);
58
- }
59
- else {
60
- await endpoint.triggerEvent('RefrigeratorAlarm', 'notify', { active: { doorOpen: false }, inactive: { doorOpen: true }, state: { doorOpen: false }, mask: { doorOpen: true } }, endpoint.log);
61
- }
62
- return endpoint;
49
+ async triggerDoorOpenState(doorOpen) {
50
+ if (doorOpen) {
51
+ await this.triggerEvent('RefrigeratorAlarm', 'notify', { active: { doorOpen: true }, inactive: { doorOpen: false }, state: { doorOpen: true }, mask: { doorOpen: true } }, this.log);
52
+ }
53
+ else {
54
+ await this.triggerEvent('RefrigeratorAlarm', 'notify', { active: { doorOpen: false }, inactive: { doorOpen: true }, state: { doorOpen: false }, mask: { doorOpen: true } }, this.log);
63
55
  }
56
+ return this;
64
57
  }
65
58
  }
66
59
  export class MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer extends RefrigeratorAndTemperatureControlledCabinetModeServer {
@@ -5,22 +5,27 @@ import { ModeBase } from '@matter/types/clusters/mode-base';
5
5
  import { WaterHeaterManagement } from '@matter/types/clusters/water-heater-management';
6
6
  import { WaterHeaterMode } from '@matter/types/clusters/water-heater-mode';
7
7
  import { MatterbridgeServer } from '../matterbridgeBehaviors.js';
8
- import { electricalSensor, powerSource, waterHeater } from '../matterbridgeDeviceTypes.js';
8
+ import { deviceEnergyManagement, electricalSensor, powerSource, waterHeater } from '../matterbridgeDeviceTypes.js';
9
9
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
10
10
  export class WaterHeater extends MatterbridgeEndpoint {
11
11
  constructor(name, serial, waterTemperature = 50, targetWaterTemperature = 55, minHeatSetpointLimit = 20, maxHeatSetpointLimit = 80, heaterTypes = { immersionElement1: true }, tankPercentage = 90, voltage = null, current = null, power = null, energy = null, absMinPower = 0, absMaxPower = 0) {
12
- super([waterHeater, powerSource, electricalSensor], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
12
+ super([waterHeater], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
13
13
  this.createDefaultIdentifyClusterServer()
14
14
  .createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Water Heater')
15
- .createDefaultPowerSourceWiredClusterServer()
16
15
  .createDefaultHeatingThermostatClusterServer(waterTemperature, targetWaterTemperature, minHeatSetpointLimit, maxHeatSetpointLimit)
17
16
  .createDefaultWaterHeaterManagementClusterServer(heaterTypes, {}, tankPercentage)
18
- .createDefaultWaterHeaterModeClusterServer()
17
+ .createDefaultWaterHeaterModeClusterServer();
18
+ this.addFixedLabel('composed', 'Water Heater');
19
+ this.addChildDeviceType('PowerSource', powerSource).createDefaultPowerSourceWiredClusterServer().addRequiredClusterServers();
20
+ this.addChildDeviceType('ElectricalSensor', electricalSensor)
19
21
  .createDefaultPowerTopologyClusterServer()
20
22
  .createDefaultElectricalPowerMeasurementClusterServer(voltage, current, power)
21
- .createDefaultElectricalEnergyMeasurementClusterServer(energy)
22
- .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.WaterHeating, true, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
23
- .createDefaultDeviceEnergyManagementModeClusterServer();
23
+ .createDefaultElectricalEnergyMeasurementClusterServer(energy, 0)
24
+ .addRequiredClusterServers();
25
+ this.addChildDeviceType('DeviceEnergyManagement', deviceEnergyManagement)
26
+ .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.WaterHeating, false, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
27
+ .createDefaultDeviceEnergyManagementModeClusterServer()
28
+ .addRequiredClusterServers();
24
29
  }
25
30
  createDefaultWaterHeaterManagementClusterServer(heaterTypes, heatDemand, tankPercentage, boostState) {
26
31
  this.behaviors.require(MatterbridgeWaterHeaterManagementServer.with(WaterHeaterManagement.Feature.TankPercent), {
@@ -43,7 +43,8 @@ export declare class Frontend extends EventEmitter<FrontendEvents> {
43
43
  private wsMessageHandler;
44
44
  wssSendLogMessage(level: string, time: string, name: string, message: string): void;
45
45
  wssSendRefreshRequired(changed: RefreshRequiredChanged, params?: {
46
- matter: ApiMatter;
46
+ matter?: ApiMatter;
47
+ lock?: string;
47
48
  }): void;
48
49
  wssSendRestartRequired(snackbar?: boolean, fixed?: boolean): void;
49
50
  wssSendRestartNotRequired(snackbar?: boolean): void;
package/dist/frontend.js CHANGED
@@ -1891,6 +1891,7 @@ export class Frontend extends EventEmitter {
1891
1891
  plugin.configJson = config;
1892
1892
  await this.matterbridge.plugins.saveConfigFromPlugin(plugin, true);
1893
1893
  this.wssSendRestartRequired(false);
1894
+ this.wssSendRefreshRequired('plugins', { lock: plugin.name });
1894
1895
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
1895
1896
  }
1896
1897
  else {
@@ -1938,6 +1939,7 @@ export class Frontend extends EventEmitter {
1938
1939
  plugin.configJson = config;
1939
1940
  await this.matterbridge.plugins.saveConfigFromPlugin(plugin, true);
1940
1941
  this.wssSendRestartRequired(false);
1942
+ this.wssSendRefreshRequired('plugins', { lock: plugin.name });
1941
1943
  sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
1942
1944
  }
1943
1945
  else {
@@ -1986,7 +1988,7 @@ export class Frontend extends EventEmitter {
1986
1988
  if (!this.listening || this.webSocketServer?.clients.size === 0)
1987
1989
  return;
1988
1990
  this.log.debug('Sending a refresh required message to all connected clients');
1989
- this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', success: true, response: { changed, ...params } });
1991
+ this.wssBroadcastMessage({ id: 0, src: 'Matterbridge', dst: 'Frontend', method: 'refresh_required', success: true, response: { changed, lock: params?.lock, ...params } });
1990
1992
  }
1991
1993
  wssSendRestartRequired(snackbar = true, fixed = false) {
1992
1994
  if (!this.listening || this.webSocketServer?.clients.size === 0)
@@ -255,7 +255,7 @@ export async function createMatterbridgeEnvironment(name, createOnly = false) {
255
255
  matterbridge = await Matterbridge.loadInstance(false);
256
256
  expect(matterbridge).toBeDefined();
257
257
  expect(matterbridge).toBeInstanceOf(Matterbridge);
258
- matterbridge.matterbridgeVersion = '3.5.6';
258
+ matterbridge.matterbridgeVersion = '3.6.0';
259
259
  matterbridge.bridgeMode = 'bridge';
260
260
  matterbridge.rootDirectory = path.join('jest', name);
261
261
  matterbridge.homeDirectory = path.join('jest', name);
@@ -1037,9 +1037,13 @@ export class Matterbridge extends EventEmitter {
1037
1037
  async unregisterAndShutdownProcess(timeout = 1000) {
1038
1038
  const { wait } = await import('@matterbridge/utils');
1039
1039
  this.log.info('Unregistering all devices and shutting down...');
1040
+ if (this.serverNode)
1041
+ await this.serverNode.setStateOf(BasicInformationServer, { configurationVersion: this.serverNode.state.basicInformation.configurationVersion + 1 });
1040
1042
  for (const plugin of this.plugins.array()) {
1041
1043
  if (plugin.error || !plugin.enabled)
1042
1044
  continue;
1045
+ if (plugin.serverNode)
1046
+ await plugin.serverNode.setStateOf(BasicInformationServer, { configurationVersion: plugin.serverNode.state.basicInformation.configurationVersion + 1 });
1043
1047
  const registeredDevices = plugin.registeredDevices;
1044
1048
  await this.plugins.shutdown(plugin, 'unregistering all devices and shutting down...', false, true);
1045
1049
  plugin.registeredDevices = registeredDevices;
@@ -1615,6 +1615,7 @@ declare const MatterbridgeThermostatServer_base: import("@matter/node").ClusterB
1615
1615
  }];
1616
1616
  }>, readonly [Thermostat.Feature.Cooling, Thermostat.Feature.Heating, Thermostat.Feature.AutoMode]>, typeof ThermostatServer, import("@matter/node/behaviors/thermostat").ThermostatInterface>;
1617
1617
  export declare class MatterbridgeThermostatServer extends MatterbridgeThermostatServer_base {
1618
+ initialize(): Promise<void>;
1618
1619
  setpointRaiseLower(request: Thermostat.SetpointRaiseLowerRequest): MaybePromise;
1619
1620
  }
1620
1621
  declare const MatterbridgePresetThermostatServer_base: import("@matter/node").ClusterBehavior.Type<import("@matter/types").ClusterComposer.WithFeatures<import("@matter/types").ClusterType.Of<{
@@ -320,6 +320,17 @@ export class MatterbridgeFanControlServer extends FanControlServer.with(FanContr
320
320
  }
321
321
  }
322
322
  export class MatterbridgeThermostatServer extends ThermostatServer.with(Thermostat.Feature.Cooling, Thermostat.Feature.Heating, Thermostat.Feature.AutoMode) {
323
+ async initialize() {
324
+ await super.initialize();
325
+ this.endpoint.construction.onSuccess(async () => {
326
+ const device = this.endpoint.stateOf(MatterbridgeServer);
327
+ device.log.debug(`Removing atomic commands (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
328
+ await this.endpoint.setStateOf(ThermostatServer, {
329
+ acceptedCommandList: [0],
330
+ generatedCommandList: [],
331
+ });
332
+ });
333
+ }
323
334
  setpointRaiseLower(request) {
324
335
  const device = this.endpoint.stateOf(MatterbridgeServer);
325
336
  device.log.info(`Setting setpoint by ${request.amount} in mode ${request.mode} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
@@ -61,7 +61,7 @@ import { WindowCovering } from '@matter/types/clusters/window-covering';
61
61
  import { VendorId } from '@matter/types/datatype';
62
62
  import { inspectError, isValidNumber, isValidObject, isValidString } from '@matterbridge/utils';
63
63
  import { AnsiLogger, CYAN, db, debugStringify, hk, or, YELLOW, zb } from 'node-ansi-logger';
64
- import { MatterbridgeActivatedCarbonFilterMonitoringServer, MatterbridgeBooleanStateConfigurationServer, MatterbridgeColorControlServer, MatterbridgeDeviceEnergyManagementModeServer, MatterbridgeDeviceEnergyManagementServer, MatterbridgeDoorLockServer, MatterbridgeEnhancedColorControlServer, MatterbridgeFanControlServer, MatterbridgeHepaFilterMonitoringServer, MatterbridgeIdentifyServer, MatterbridgeLevelControlServer, MatterbridgeLiftTiltWindowCoveringServer, MatterbridgeLiftWindowCoveringServer, MatterbridgeModeSelectServer, MatterbridgeOnOffServer, MatterbridgeOperationalStateServer, MatterbridgePowerSourceServer, MatterbridgeServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeSwitchServer, MatterbridgeThermostatServer, MatterbridgeValveConfigurationAndControlServer, } from './matterbridgeBehaviors.js';
64
+ import { MatterbridgeActivatedCarbonFilterMonitoringServer, MatterbridgeBooleanStateConfigurationServer, MatterbridgeColorControlServer, MatterbridgeDeviceEnergyManagementModeServer, MatterbridgeDeviceEnergyManagementServer, MatterbridgeDoorLockServer, MatterbridgeEnhancedColorControlServer, MatterbridgeFanControlServer, MatterbridgeHepaFilterMonitoringServer, MatterbridgeIdentifyServer, MatterbridgeLevelControlServer, MatterbridgeLiftTiltWindowCoveringServer, MatterbridgeLiftWindowCoveringServer, MatterbridgeModeSelectServer, MatterbridgeOnOffServer, MatterbridgeOperationalStateServer, MatterbridgePowerSourceServer, MatterbridgePresetThermostatServer, MatterbridgeServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeSwitchServer, MatterbridgeThermostatServer, MatterbridgeValveConfigurationAndControlServer, } from './matterbridgeBehaviors.js';
65
65
  import { addClusterServers, addFixedLabel, addOptionalClusterServers, addRequiredClusterServers, addUserLabel, checkNotLatinCharacters, createUniqueId, featuresFor, generateUniqueId, getApparentElectricalPowerMeasurementClusterServer, getAttribute, getAttributeId, getBehavior, getBehaviourTypesFromClusterClientIds, getBehaviourTypesFromClusterServerIds, getClusterId, getDefaultDeviceEnergyManagementClusterServer, getDefaultDeviceEnergyManagementModeClusterServer, getDefaultElectricalEnergyMeasurementClusterServer, getDefaultElectricalPowerMeasurementClusterServer, getDefaultFlowMeasurementClusterServer, getDefaultIlluminanceMeasurementClusterServer, getDefaultOccupancySensingClusterServer, getDefaultOperationalStateClusterServer, getDefaultPowerSourceBatteryClusterServer, getDefaultPowerSourceRechargeableBatteryClusterServer, getDefaultPowerSourceReplaceableBatteryClusterServer, getDefaultPowerSourceWiredClusterServer, getDefaultPressureMeasurementClusterServer, getDefaultRelativeHumidityMeasurementClusterServer, getDefaultTemperatureMeasurementClusterServer, invokeBehaviorCommand, lowercaseFirstLetter, setAttribute, subscribeAttribute, triggerEvent, updateAttribute, } from './matterbridgeEndpointHelpers.js';
66
66
  const MATTERBRIDGE_ENDPOINT_BRAND = Symbol('MatterbridgeEndpoint.brand');
67
67
  export function isMatterbridgeEndpoint(value) {
@@ -881,7 +881,7 @@ export class MatterbridgeEndpoint extends Endpoint {
881
881
  return this;
882
882
  }
883
883
  createDefaultPresetsThermostatClusterServer(localTemperature = 23, occupiedHeatingSetpoint = 21, occupiedCoolingSetpoint = 25, minSetpointDeadBand = 2, minHeatSetpointLimit = 0, maxHeatSetpointLimit = 50, minCoolSetpointLimit = 0, maxCoolSetpointLimit = 50, unoccupiedHeatingSetpoint = undefined, unoccupiedCoolingSetpoint = undefined, occupied = undefined, outdoorTemperature = undefined, activePresetHandle = undefined, presetsList = undefined, presetTypes = undefined) {
884
- this.behaviors.require(MatterbridgeThermostatServer.with(Thermostat.Feature.Heating, Thermostat.Feature.Cooling, Thermostat.Feature.AutoMode, ...(occupied !== undefined ? [Thermostat.Feature.Occupancy] : []), Thermostat.Feature.Presets), {
884
+ this.behaviors.require(MatterbridgePresetThermostatServer.with(Thermostat.Feature.Heating, Thermostat.Feature.Cooling, Thermostat.Feature.AutoMode, ...(occupied !== undefined ? [Thermostat.Feature.Occupancy] : []), Thermostat.Feature.Presets), {
885
885
  localTemperature: localTemperature * 100,
886
886
  externalMeasuredIndoorTemperature: localTemperature * 100,
887
887
  ...(outdoorTemperature !== undefined ? { outdoorTemperature: outdoorTemperature !== null ? outdoorTemperature * 100 : outdoorTemperature } : {}),
@@ -67,6 +67,9 @@ export interface MatterbridgeEndpointCommands {
67
67
  cancelBoost: HandlerFunction;
68
68
  enableCharging: HandlerFunction;
69
69
  disable: HandlerFunction;
70
+ setTargets: HandlerFunction;
71
+ getTargets: HandlerFunction;
72
+ clearTargets: HandlerFunction;
70
73
  powerAdjustRequest: HandlerFunction;
71
74
  cancelPowerAdjustRequest: HandlerFunction;
72
75
  setTemperature: HandlerFunction;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/core",
3
- "version": "3.5.6",
3
+ "version": "3.6.0-dev-20260302-e3a7eb0",
4
4
  "description": "Matterbridge core library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -122,14 +122,14 @@
122
122
  ],
123
123
  "dependencies": {
124
124
  "@matter/main": "0.16.10",
125
- "@matterbridge/dgram": "3.5.6",
126
- "@matterbridge/thread": "3.5.6",
127
- "@matterbridge/types": "3.5.6",
128
- "@matterbridge/utils": "3.5.6",
125
+ "@matterbridge/dgram": "3.6.0-dev-20260302-e3a7eb0",
126
+ "@matterbridge/thread": "3.6.0-dev-20260302-e3a7eb0",
127
+ "@matterbridge/types": "3.6.0-dev-20260302-e3a7eb0",
128
+ "@matterbridge/utils": "3.6.0-dev-20260302-e3a7eb0",
129
129
  "archiver": "7.0.1",
130
130
  "express": "5.2.1",
131
131
  "glob": "13.0.6",
132
- "multer": "2.0.2",
132
+ "multer": "2.1.0",
133
133
  "node-ansi-logger": "3.2.0",
134
134
  "node-persist-manager": "2.0.1",
135
135
  "ws": "8.19.0"