matterbridge 3.0.0-edge.3 → 3.0.0-edge.5

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
@@ -47,12 +47,17 @@ Modified clusters:
47
47
  ### Added
48
48
 
49
49
  - [addEndpoint]: Added an error handler with deep stack on aggregatorNode.add() and serverNode.add() calls.
50
+ - [endpoint]: Added createOffOnlyOnOffClusterServer().
51
+ - [endpoint]: Added createBaseFanControlClusterServer().
52
+ - [endpoint]: Added createDefaultHepaFilterMonitoringClusterServer().
53
+ - [endpoint]: Added createDefaultActivatedCarbonFilterMonitoringClusterServer().
50
54
 
51
55
  ### Changed
52
56
 
53
57
  - [deviceTypes]: Updated device types to Matter 1.4
54
58
  - [matter.js]: Update to 0.13.0-alpha.0-20250405-7fc7db48.
55
59
  - [matter.js]: Update to 0.13.0-alpha.0-20250408-c916c7e8.
60
+ - [matter.js]: Update to 0.13.0-alpha.0-20250412-5fad64e7b.
56
61
 
57
62
  ### Fixed
58
63
 
@@ -1728,12 +1728,14 @@ export class Matterbridge extends EventEmitter {
1728
1728
  this.devices.remove(device);
1729
1729
  }
1730
1730
  async removeAllBridgedEndpoints(pluginName, delay = 0) {
1731
- this.log.debug(`Removing all bridged endpoints for plugin ${plg}${pluginName}${db}`);
1731
+ this.log.debug(`Removing all bridged endpoints for plugin ${plg}${pluginName}${db}${delay > 0 ? ` with delay ${delay} ms` : ''}`);
1732
1732
  for (const device of this.devices.array().filter((device) => device.plugin === pluginName)) {
1733
1733
  await this.removeBridgedEndpoint(pluginName, device);
1734
1734
  if (delay > 0)
1735
1735
  await new Promise((resolve) => setTimeout(resolve, delay));
1736
1736
  }
1737
+ if (delay > 0)
1738
+ await new Promise((resolve) => setTimeout(resolve, 2000));
1737
1739
  }
1738
1740
  async subscribeAttributeChanged(plugin, device) {
1739
1741
  this.log.info(`Subscribing attributes for endpoint ${dev}${device.deviceName}${nf} (${dev}${device.id}${nf}) plugin ${plg}${plugin.name}${nf}`);
@@ -19,7 +19,7 @@ import { ValveConfigurationAndControlBehavior } from '@matter/main/behaviors/val
19
19
  import { ModeSelectServer } from '@matter/main/behaviors/mode-select';
20
20
  import { SmokeCoAlarmServer } from '@matter/main/behaviors/smoke-co-alarm';
21
21
  import { SwitchServer } from '@matter/main/behaviors/switch';
22
- export class MatterbridgeBehaviorDevice {
22
+ export class MatterbridgeServerDevice {
23
23
  log;
24
24
  commandHandler;
25
25
  device;
@@ -141,107 +141,107 @@ export class MatterbridgeBehaviorDevice {
141
141
  this.commandHandler.executeHandler('enableDisableAlarm', { request: { alarmsToEnableDisable }, attributes: {}, endpoint: { number: this.endpointNumber, uniqueStorageKey: this.endpointId } });
142
142
  }
143
143
  }
144
- export class MatterbridgeBehavior extends Behavior {
144
+ export class MatterbridgeServer extends Behavior {
145
145
  static id = 'matterbridge';
146
146
  }
147
- (function (MatterbridgeBehavior) {
147
+ (function (MatterbridgeServer) {
148
148
  class State {
149
149
  deviceCommand;
150
150
  }
151
- MatterbridgeBehavior.State = State;
152
- })(MatterbridgeBehavior || (MatterbridgeBehavior = {}));
151
+ MatterbridgeServer.State = State;
152
+ })(MatterbridgeServer || (MatterbridgeServer = {}));
153
153
  export class MatterbridgeIdentifyServer extends IdentifyServer {
154
154
  initialize() {
155
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
155
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
156
156
  device.setEndpointId(this.endpoint.maybeId);
157
157
  device.setEndpointNumber(this.endpoint.maybeNumber);
158
158
  super.initialize();
159
159
  }
160
160
  identify({ identifyTime }) {
161
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
161
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
162
162
  device.identify({ identifyTime });
163
163
  super.identify({ identifyTime });
164
164
  }
165
165
  triggerEffect({ effectIdentifier, effectVariant }) {
166
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
166
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
167
167
  device.triggerEffect({ effectIdentifier, effectVariant });
168
168
  super.triggerEffect({ effectIdentifier, effectVariant });
169
169
  }
170
170
  }
171
171
  export class MatterbridgeOnOffServer extends OnOffServer {
172
172
  async on() {
173
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
173
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
174
174
  device.on();
175
175
  super.on();
176
176
  }
177
177
  async off() {
178
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
178
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
179
179
  device.off();
180
180
  super.off();
181
181
  }
182
182
  async toggle() {
183
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
183
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
184
184
  device.toggle();
185
185
  super.toggle();
186
186
  }
187
187
  }
188
188
  export class MatterbridgeLevelControlServer extends LevelControlServer {
189
189
  async moveToLevel({ level, transitionTime, optionsMask, optionsOverride }) {
190
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
190
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
191
191
  device.moveToLevel({ level, transitionTime, optionsMask, optionsOverride });
192
192
  super.moveToLevel({ level, transitionTime, optionsMask, optionsOverride });
193
193
  }
194
194
  async moveToLevelWithOnOff({ level, transitionTime, optionsMask, optionsOverride }) {
195
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
195
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
196
196
  device.moveToLevelWithOnOff({ level, transitionTime, optionsMask, optionsOverride });
197
197
  super.moveToLevelWithOnOff({ level, transitionTime, optionsMask, optionsOverride });
198
198
  }
199
199
  }
200
200
  export class MatterbridgeColorControlServer extends ColorControlServer.with(ColorControl.Feature.HueSaturation, ColorControl.Feature.Xy, ColorControl.Feature.ColorTemperature) {
201
201
  async moveToHue({ optionsMask, optionsOverride, hue, direction, transitionTime }) {
202
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
202
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
203
203
  device.moveToHue({ optionsMask, optionsOverride, hue, direction, transitionTime });
204
204
  super.moveToHue({ optionsMask, optionsOverride, hue, direction, transitionTime });
205
205
  }
206
206
  async moveToSaturation({ optionsMask, optionsOverride, saturation, transitionTime }) {
207
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
207
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
208
208
  device.moveToSaturation({ optionsMask, optionsOverride, saturation, transitionTime });
209
209
  super.moveToSaturation({ optionsMask, optionsOverride, saturation, transitionTime });
210
210
  }
211
211
  async moveToHueAndSaturation({ optionsOverride, optionsMask, saturation, hue, transitionTime }) {
212
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
212
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
213
213
  device.moveToHueAndSaturation({ optionsOverride, optionsMask, saturation, hue, transitionTime });
214
214
  super.moveToHueAndSaturation({ optionsOverride, optionsMask, saturation, hue, transitionTime });
215
215
  }
216
216
  async moveToColor({ optionsMask, optionsOverride, colorX, colorY, transitionTime }) {
217
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
217
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
218
218
  device.moveToColor({ optionsMask, optionsOverride, colorX, colorY, transitionTime });
219
219
  super.moveToColor({ optionsMask, optionsOverride, colorX, colorY, transitionTime });
220
220
  }
221
221
  async moveToColorTemperature({ optionsOverride, optionsMask, colorTemperatureMireds, transitionTime }) {
222
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
222
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
223
223
  device.moveToColorTemperature({ optionsOverride, optionsMask, colorTemperatureMireds, transitionTime });
224
224
  super.moveToColorTemperature({ optionsOverride, optionsMask, colorTemperatureMireds, transitionTime });
225
225
  }
226
226
  }
227
227
  export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(WindowCovering.Feature.Lift, WindowCovering.Feature.PositionAwareLift) {
228
228
  async upOrOpen() {
229
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
229
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
230
230
  device.upOrOpen();
231
231
  super.upOrOpen();
232
232
  }
233
233
  async downOrClose() {
234
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
234
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
235
235
  device.downOrClose();
236
236
  super.downOrClose();
237
237
  }
238
238
  stopMotion() {
239
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
239
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
240
240
  device.stopMotion();
241
241
  super.stopMotion();
242
242
  }
243
243
  goToLiftPercentage({ liftPercent100thsValue }) {
244
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
244
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
245
245
  device.goToLiftPercentage({ liftPercent100thsValue });
246
246
  super.goToLiftPercentage({ liftPercent100thsValue });
247
247
  }
@@ -250,26 +250,26 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
250
250
  }
251
251
  export class MatterbridgeDoorLockServer extends DoorLockServer {
252
252
  async lockDoor() {
253
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
253
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
254
254
  device.lockDoor();
255
255
  super.lockDoor();
256
256
  }
257
257
  async unlockDoor() {
258
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
258
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
259
259
  device.unlockDoor();
260
260
  super.unlockDoor();
261
261
  }
262
262
  }
263
263
  export class MatterbridgeModeSelectServer extends ModeSelectServer {
264
264
  async changeToMode({ newMode }) {
265
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
265
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
266
266
  device.changeToMode({ newMode });
267
267
  super.changeToMode({ newMode });
268
268
  }
269
269
  }
270
270
  export class MatterbridgeFanControlServer extends FanControlServer.with(FanControl.Feature.MultiSpeed, FanControl.Feature.Auto, FanControl.Feature.Step) {
271
271
  async step({ direction, wrap, lowestOff }) {
272
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
272
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
273
273
  device.step({ direction, wrap, lowestOff });
274
274
  const lookupStepDirection = ['Increase', 'Decrease'];
275
275
  device.log.debug(`Command step called with direction: ${lookupStepDirection[direction]} wrap: ${wrap} lowestOff: ${lowestOff}`);
@@ -294,7 +294,7 @@ export class MatterbridgeFanControlServer extends FanControlServer.with(FanContr
294
294
  }
295
295
  export class MatterbridgeThermostatServer extends ThermostatBehavior.with(Thermostat.Feature.Cooling, Thermostat.Feature.Heating, Thermostat.Feature.AutoMode) {
296
296
  async setpointRaiseLower({ mode, amount }) {
297
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
297
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
298
298
  device.setpointRaiseLower({ mode, amount });
299
299
  const lookupSetpointAdjustMode = ['Heat', 'Cool', 'Both'];
300
300
  device.log.debug(`Command setpointRaiseLower called with mode: ${lookupSetpointAdjustMode[mode]} amount: ${amount / 10}`);
@@ -316,14 +316,14 @@ export class MatterbridgeValveConfigurationAndControlServer extends ValveConfigu
316
316
  initialize() {
317
317
  }
318
318
  open({ openDuration, targetLevel }) {
319
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
319
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
320
320
  device.log.debug(`Command open called with openDuration: ${openDuration} targetLevel: ${targetLevel}`);
321
321
  device.open({ openDuration, targetLevel });
322
322
  this.state.targetLevel = targetLevel ?? 100;
323
323
  this.state.currentLevel = targetLevel ?? 100;
324
324
  }
325
325
  close() {
326
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
326
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
327
327
  device.log.debug(`Command close called`);
328
328
  device.close();
329
329
  this.state.targetLevel = 0;
@@ -332,14 +332,14 @@ export class MatterbridgeValveConfigurationAndControlServer extends ValveConfigu
332
332
  }
333
333
  export class MatterbridgeSmokeCoAlarmServer extends SmokeCoAlarmServer.with(SmokeCoAlarm.Feature.SmokeAlarm, SmokeCoAlarm.Feature.CoAlarm) {
334
334
  async selfTestRequest() {
335
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
335
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
336
336
  device.selfTestRequest();
337
337
  super.selfTestRequest();
338
338
  }
339
339
  }
340
340
  export class MatterbridgeBooleanStateConfigurationServer extends BooleanStateConfigurationServer.with(BooleanStateConfiguration.Feature.Visual, BooleanStateConfiguration.Feature.Audible, BooleanStateConfiguration.Feature.SensitivityLevel) {
341
341
  async enableDisableAlarm({ alarmsToEnableDisable }) {
342
- const device = this.agent.get(MatterbridgeBehavior).state.deviceCommand;
342
+ const device = this.agent.get(MatterbridgeServer).state.deviceCommand;
343
343
  device.enableDisableAlarm({ alarmsToEnableDisable });
344
344
  super.enableDisableAlarm({ alarmsToEnableDisable });
345
345
  }
@@ -44,13 +44,11 @@ import { EnergyPreference } from '@matter/main/clusters/energy-preference';
44
44
  import { RvcRunMode } from '@matter/main/clusters/rvc-run-mode';
45
45
  import { RvcOperationalState } from '@matter/main/clusters/rvc-operational-state';
46
46
  import { RvcCleanMode } from '@matter/main/clusters/rvc-clean-mode';
47
- import { ScenesManagement } from '@matter/main/clusters/scenes-management';
48
47
  import { HepaFilterMonitoring } from '@matter/main/clusters/hepa-filter-monitoring';
49
48
  import { ActivatedCarbonFilterMonitoring } from '@matter/main/clusters/activated-carbon-filter-monitoring';
50
49
  import { DeviceEnergyManagementMode } from '@matter/main/clusters/device-energy-management-mode';
51
50
  import { AdministratorCommissioning } from '@matter/main/clusters/administrator-commissioning';
52
51
  import { EcosystemInformation } from '@matter/main/clusters/ecosystem-information';
53
- import { AccessControl } from '@matter/main/clusters/access-control';
54
52
  import { CommissionerControl } from '@matter/main/clusters/commissioner-control';
55
53
  import { ServiceArea } from '@matter/main/clusters';
56
54
  export var DeviceClasses;
@@ -178,7 +176,7 @@ export const pumpDevice = DeviceTypeDefinition({
178
176
  deviceClass: DeviceClasses.Simple,
179
177
  revision: 3,
180
178
  requiredServerClusters: [OnOff.Cluster.id, PumpConfigurationAndControl.Cluster.id, Identify.Cluster.id],
181
- optionalServerClusters: [LevelControl.Cluster.id, Groups.Cluster.id, ScenesManagement.Cluster.id, TemperatureMeasurement.Cluster.id, PressureMeasurement.Cluster.id, FlowMeasurement.Cluster.id],
179
+ optionalServerClusters: [LevelControl.Cluster.id, Groups.Cluster.id, TemperatureMeasurement.Cluster.id, PressureMeasurement.Cluster.id, FlowMeasurement.Cluster.id],
182
180
  });
183
181
  export const waterValve = DeviceTypeDefinition({
184
182
  name: 'MA-waterValve',
@@ -194,7 +192,7 @@ export const onOffSwitch = DeviceTypeDefinition({
194
192
  deviceClass: DeviceClasses.Simple,
195
193
  revision: 3,
196
194
  requiredServerClusters: [Identify.Cluster.id, OnOff.Cluster.id],
197
- optionalServerClusters: [Groups.Cluster.id, ScenesManagement.Cluster.id],
195
+ optionalServerClusters: [Groups.Cluster.id],
198
196
  });
199
197
  export const dimmableSwitch = DeviceTypeDefinition({
200
198
  name: 'MA-dimmableswitch',
@@ -202,7 +200,7 @@ export const dimmableSwitch = DeviceTypeDefinition({
202
200
  deviceClass: DeviceClasses.Simple,
203
201
  revision: 3,
204
202
  requiredServerClusters: [Identify.Cluster.id, OnOff.Cluster.id, LevelControl.Cluster.id],
205
- optionalServerClusters: [Groups.Cluster.id, ScenesManagement.Cluster.id],
203
+ optionalServerClusters: [Groups.Cluster.id],
206
204
  });
207
205
  export const colorTemperatureSwitch = DeviceTypeDefinition({
208
206
  name: 'MA-colortemperatureswitch',
@@ -210,7 +208,7 @@ export const colorTemperatureSwitch = DeviceTypeDefinition({
210
208
  deviceClass: DeviceClasses.Simple,
211
209
  revision: 3,
212
210
  requiredServerClusters: [Identify.Cluster.id, Groups.Cluster.id, OnOff.Cluster.id, LevelControl.Cluster.id, ColorControl.Cluster.id],
213
- optionalServerClusters: [Groups.Cluster.id, ScenesManagement.Cluster.id],
211
+ optionalServerClusters: [Groups.Cluster.id],
214
212
  });
215
213
  export const genericSwitch = DeviceTypeDefinition({
216
214
  name: 'MA-genericswitch',
@@ -329,7 +327,7 @@ export const doorLockDevice = DeviceTypeDefinition({
329
327
  code: 0xa,
330
328
  deviceClass: DeviceClasses.Simple,
331
329
  revision: 3,
332
- requiredServerClusters: [Identify.Cluster.id, DoorLock.Cluster.id, AccessControl.Cluster.id],
330
+ requiredServerClusters: [Identify.Cluster.id, DoorLock.Cluster.id],
333
331
  optionalServerClusters: [],
334
332
  });
335
333
  export const coverDevice = DeviceTypeDefinition({
@@ -371,7 +369,7 @@ export const modeSelect = DeviceTypeDefinition({
371
369
  revision: 1,
372
370
  requiredServerClusters: [ModeSelect.Cluster.id],
373
371
  });
374
- export const bridge = DeviceTypeDefinition({
372
+ export const aggregator = DeviceTypeDefinition({
375
373
  name: 'MA-aggregator',
376
374
  code: 0x000e,
377
375
  deviceClass: DeviceClasses.Dynamic,
@@ -379,7 +377,7 @@ export const bridge = DeviceTypeDefinition({
379
377
  requiredServerClusters: [],
380
378
  optionalServerClusters: [Actions.Cluster.id, Identify.Cluster.id, CommissionerControl.Cluster.id],
381
379
  });
382
- export const aggregator = bridge;
380
+ export const bridge = aggregator;
383
381
  export const roboticVacuumCleaner = DeviceTypeDefinition({
384
382
  name: 'MA-roboticvacuumcleaner',
385
383
  code: 0x74,
@@ -388,11 +386,3 @@ export const roboticVacuumCleaner = DeviceTypeDefinition({
388
386
  requiredServerClusters: [Identify.Cluster.id, RvcRunMode.Cluster.id, RvcOperationalState.Cluster.id],
389
387
  optionalServerClusters: [RvcCleanMode.Cluster.id, ServiceArea.Cluster.id],
390
388
  });
391
- export const airConditioner = DeviceTypeDefinition({
392
- name: 'MA-airConditioner',
393
- code: 0x72,
394
- deviceClass: DeviceClasses.Simple,
395
- revision: 2,
396
- requiredServerClusters: [Identify.Cluster.id, OnOff.Cluster.id, Thermostat.Cluster.id],
397
- optionalServerClusters: [Groups.Cluster.id, ScenesManagement.Cluster.id, FanControl.Cluster.id, ThermostatUserInterfaceConfiguration.Cluster.id, TemperatureMeasurement.Cluster.id, RelativeHumidityMeasurement.Cluster.id],
398
- });
@@ -1,7 +1,7 @@
1
1
  import { AnsiLogger, BLUE, CYAN, YELLOW, db, debugStringify, er, hk, or, zb } from './logger/export.js';
2
2
  import { bridgedNode } from './matterbridgeDeviceTypes.js';
3
3
  import { isValidNumber, isValidObject } from './utils/export.js';
4
- import { MatterbridgeBehavior, MatterbridgeBehaviorDevice, MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer, MatterbridgeWindowCoveringServer, MatterbridgeThermostatServer, MatterbridgeFanControlServer, MatterbridgeDoorLockServer, MatterbridgeModeSelectServer, MatterbridgeValveConfigurationAndControlServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeBooleanStateConfigurationServer, MatterbridgeSwitchServer, } from './matterbridgeBehaviors.js';
4
+ import { MatterbridgeServer, MatterbridgeServerDevice, MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer, MatterbridgeWindowCoveringServer, MatterbridgeThermostatServer, MatterbridgeFanControlServer, MatterbridgeDoorLockServer, MatterbridgeModeSelectServer, MatterbridgeValveConfigurationAndControlServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeBooleanStateConfigurationServer, MatterbridgeSwitchServer, } from './matterbridgeBehaviors.js';
5
5
  import { addClusterServers, addFixedLabel, addOptionalClusterServers, addRequiredClusterServers, addUserLabel, capitalizeFirstLetter, createUniqueId, getBehavior, getBehaviourTypesFromClusterClientIds, getBehaviourTypesFromClusterServerIds, getDefaultFlowMeasurementClusterServer, getDefaultIlluminanceMeasurementClusterServer, getDefaultPressureMeasurementClusterServer, getDefaultRelativeHumidityMeasurementClusterServer, getDefaultTemperatureMeasurementClusterServer, getDefaultOccupancySensingClusterServer, lowercaseFirstLetter, updateAttribute, getClusterId, getAttributeId, setAttribute, getAttribute, checkNotLatinCharacters, generateUniqueId, subscribeAttribute, } from './matterbridgeEndpointHelpers.js';
6
6
  import { Endpoint, Lifecycle, MutableEndpoint, NamedHandler, SupportedBehaviors, VendorId } from '@matter/main';
7
7
  import { getClusterNameById, MeasurementType } from '@matter/main/types';
@@ -55,6 +55,10 @@ import { Pm25ConcentrationMeasurementServer } from '@matter/main/behaviors/pm25-
55
55
  import { Pm10ConcentrationMeasurementServer } from '@matter/main/behaviors/pm10-concentration-measurement';
56
56
  import { RadonConcentrationMeasurementServer } from '@matter/main/behaviors/radon-concentration-measurement';
57
57
  import { TotalVolatileOrganicCompoundsConcentrationMeasurementServer } from '@matter/main/behaviors/total-volatile-organic-compounds-concentration-measurement';
58
+ import { FanControlServer } from '@matter/main/behaviors/fan-control';
59
+ import { ResourceMonitoring } from '@matter/main/clusters/resource-monitoring';
60
+ import { HepaFilterMonitoringServer } from '@matter/main/behaviors/hepa-filter-monitoring';
61
+ import { ActivatedCarbonFilterMonitoringServer } from '@matter/main/behaviors/activated-carbon-filter-monitoring';
58
62
  export class MatterbridgeEndpoint extends Endpoint {
59
63
  static bridgeMode = '';
60
64
  static logLevel = "info";
@@ -134,7 +138,7 @@ export class MatterbridgeEndpoint extends Endpoint {
134
138
  this.log = new AnsiLogger({ logName: options.uniqueStorageKey ?? 'MatterbridgeEndpoint', logTimestampFormat: 4, logLevel: debug === true ? "debug" : MatterbridgeEndpoint.logLevel });
135
139
  this.log.debug(`${YELLOW}new${db} MatterbridgeEndpoint: ${zb}${'0x' + firstDefinition.code.toString(16).padStart(4, '0')}${db}-${zb}${firstDefinition.name}${db} ` +
136
140
  `id: ${CYAN}${options.uniqueStorageKey}${db} number: ${CYAN}${options.endpointId}${db} taglist: ${CYAN}${options.tagList ? debugStringify(options.tagList) : 'undefined'}${db}`);
137
- this.behaviors.require(MatterbridgeBehavior, { deviceCommand: new MatterbridgeBehaviorDevice(this.log, this.commandHandler, undefined) });
141
+ this.behaviors.require(MatterbridgeServer, { deviceCommand: new MatterbridgeServerDevice(this.log, this.commandHandler, undefined) });
138
142
  }
139
143
  static async loadInstance(definition, options = {}, debug = false) {
140
144
  return new MatterbridgeEndpoint(definition, options, debug);
@@ -530,6 +534,12 @@ export class MatterbridgeEndpoint extends Endpoint {
530
534
  });
531
535
  return this;
532
536
  }
537
+ createOffOnlyOnOffClusterServer(onOff = false) {
538
+ this.behaviors.require(MatterbridgeOnOffServer.with(OnOff.Feature.OffOnly), {
539
+ onOff,
540
+ });
541
+ return this;
542
+ }
533
543
  createDefaultLevelControlClusterServer(currentLevel = 254, minLevel = 1, maxLevel = 254, onLevel = null, startUpCurrentLevel = null) {
534
544
  this.behaviors.require(MatterbridgeLevelControlServer.with(LevelControl.Feature.OnOff, LevelControl.Feature.Lighting), {
535
545
  currentLevel,
@@ -762,6 +772,31 @@ export class MatterbridgeEndpoint extends Endpoint {
762
772
  });
763
773
  return this;
764
774
  }
775
+ createBaseFanControlClusterServer(fanMode = FanControl.FanMode.Off) {
776
+ this.behaviors.require(FanControlServer, {
777
+ fanMode,
778
+ fanModeSequence: FanControl.FanModeSequence.OffLowMedHigh,
779
+ percentSetting: 0,
780
+ percentCurrent: 0,
781
+ });
782
+ return this;
783
+ }
784
+ createDefaultHepaFilterMonitoringClusterServer(changeIndication = ResourceMonitoring.ChangeIndication.Ok, inPlaceIndicator = undefined, lastChangedTime = undefined) {
785
+ this.behaviors.require(HepaFilterMonitoringServer, {
786
+ changeIndication,
787
+ inPlaceIndicator,
788
+ lastChangedTime,
789
+ });
790
+ return this;
791
+ }
792
+ createDefaultActivatedCarbonFilterMonitoringClusterServer(changeIndication = ResourceMonitoring.ChangeIndication.Ok, inPlaceIndicator = undefined, lastChangedTime = undefined) {
793
+ this.behaviors.require(ActivatedCarbonFilterMonitoringServer, {
794
+ changeIndication,
795
+ inPlaceIndicator,
796
+ lastChangedTime,
797
+ });
798
+ return this;
799
+ }
765
800
  createDefaultDoorLockClusterServer(lockState = DoorLock.LockState.Locked, lockType = DoorLock.LockType.DeadBolt) {
766
801
  this.behaviors.require(MatterbridgeDoorLockServer.enable({ events: { doorLockAlarm: true, lockOperation: true, lockOperationError: true } }), {
767
802
  lockState,
@@ -115,8 +115,8 @@ export class MatterbridgePlatform {
115
115
  if (device.deviceName)
116
116
  this._registeredEndpointsByName.delete(device.deviceName);
117
117
  }
118
- async unregisterAllDevices() {
119
- await this.matterbridge.removeAllBridgedEndpoints(this.name);
118
+ async unregisterAllDevices(delay = 0) {
119
+ await this.matterbridge.removeAllBridgedEndpoints(this.name, delay);
120
120
  this._registeredEndpoints.clear();
121
121
  this._registeredEndpointsByName.clear();
122
122
  }
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.0.0-edge.3",
3
+ "version": "3.0.0-edge.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge",
9
- "version": "3.0.0-edge.3",
9
+ "version": "3.0.0-edge.5",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
- "@matter/main": "^0.13.0-alpha.0-20250408-c916c7e8",
12
+ "@matter/main": "0.13.0-alpha.0-20250412-5fad64e7b",
13
13
  "archiver": "7.0.1",
14
14
  "express": "4.21.2",
15
15
  "glob": "11.0.1",
@@ -47,65 +47,65 @@
47
47
  }
48
48
  },
49
49
  "node_modules/@matter/general": {
50
- "version": "0.13.0-alpha.0-20250408-c916c7e8",
51
- "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.13.0-alpha.0-20250408-c916c7e8.tgz",
52
- "integrity": "sha512-iQ2EnGzoMieFUW56ALFXkbwWihm68wHLhvRlV0V/PJ4yVBY8JAxn+L2RZ6UzzKmLIL7Smzd4YtfwphhI2yAdyg==",
50
+ "version": "0.13.0-alpha.0-20250412-5fad64e7b",
51
+ "resolved": "https://registry.npmjs.org/@matter/general/-/general-0.13.0-alpha.0-20250412-5fad64e7b.tgz",
52
+ "integrity": "sha512-Ol+AWbTAcoiEM3Rr9SBRdm0hljFIqFJqRd/ClbPV9CSUNyQFe8NR4J7bFmI+eCgahQBkPmtIpGhj6ebDDkCyEA==",
53
53
  "license": "Apache-2.0",
54
54
  "dependencies": {
55
55
  "@noble/curves": "^1.8.1"
56
56
  }
57
57
  },
58
58
  "node_modules/@matter/main": {
59
- "version": "0.13.0-alpha.0-20250408-c916c7e8",
60
- "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.13.0-alpha.0-20250408-c916c7e8.tgz",
61
- "integrity": "sha512-LBaN3bzAcj676BzNvhLbaiFuNs+zda38MPQLmm7w2vmrK1HeYZhtCr2Xlt76oTNIR5bwh5oiYI22n2CpNYa4iQ==",
59
+ "version": "0.13.0-alpha.0-20250412-5fad64e7b",
60
+ "resolved": "https://registry.npmjs.org/@matter/main/-/main-0.13.0-alpha.0-20250412-5fad64e7b.tgz",
61
+ "integrity": "sha512-rXPMESZm4nmq/QRYhunddSbeNMLfM/flGfv45IWY++tezwI2yzJu4dVU5QDPmfsyehagVMD0sLwo5x0UwLgDiA==",
62
62
  "license": "Apache-2.0",
63
63
  "dependencies": {
64
- "@matter/general": "0.13.0-alpha.0-20250408-c916c7e8",
65
- "@matter/model": "0.13.0-alpha.0-20250408-c916c7e8",
66
- "@matter/node": "0.13.0-alpha.0-20250408-c916c7e8",
67
- "@matter/protocol": "0.13.0-alpha.0-20250408-c916c7e8",
68
- "@matter/types": "0.13.0-alpha.0-20250408-c916c7e8",
64
+ "@matter/general": "0.13.0-alpha.0-20250412-5fad64e7b",
65
+ "@matter/model": "0.13.0-alpha.0-20250412-5fad64e7b",
66
+ "@matter/node": "0.13.0-alpha.0-20250412-5fad64e7b",
67
+ "@matter/protocol": "0.13.0-alpha.0-20250412-5fad64e7b",
68
+ "@matter/types": "0.13.0-alpha.0-20250412-5fad64e7b",
69
69
  "@noble/curves": "^1.8.1"
70
70
  },
71
71
  "optionalDependencies": {
72
- "@matter/nodejs": "0.13.0-alpha.0-20250408-c916c7e8"
72
+ "@matter/nodejs": "0.13.0-alpha.0-20250412-5fad64e7b"
73
73
  }
74
74
  },
75
75
  "node_modules/@matter/model": {
76
- "version": "0.13.0-alpha.0-20250408-c916c7e8",
77
- "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.13.0-alpha.0-20250408-c916c7e8.tgz",
78
- "integrity": "sha512-1pczrCHWxGRY85V7idsFBV4O7t/yXfy29c2vWtQdTQ5IP4qILqocf6qgSK/6jqvKag8x8Ph8Dt/L2EHe/Rjc4A==",
76
+ "version": "0.13.0-alpha.0-20250412-5fad64e7b",
77
+ "resolved": "https://registry.npmjs.org/@matter/model/-/model-0.13.0-alpha.0-20250412-5fad64e7b.tgz",
78
+ "integrity": "sha512-b73rqLywpSOSV7ITiuEdvG5QPEBcsc3cuRWVt1kgmrrlxh5nWw6r37vAqrGyNCgimYURMLLFDhVs/AYcV298BA==",
79
79
  "license": "Apache-2.0",
80
80
  "dependencies": {
81
- "@matter/general": "0.13.0-alpha.0-20250408-c916c7e8",
81
+ "@matter/general": "0.13.0-alpha.0-20250412-5fad64e7b",
82
82
  "@noble/curves": "^1.8.1"
83
83
  }
84
84
  },
85
85
  "node_modules/@matter/node": {
86
- "version": "0.13.0-alpha.0-20250408-c916c7e8",
87
- "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.13.0-alpha.0-20250408-c916c7e8.tgz",
88
- "integrity": "sha512-i43KtL4ybHW4NuvSBPeyjvFCUekIL/EF054YFP9/+XioplgsSVRskaeLr0YVvCIfDfAmEwCcdmfvaFLjc/vlDw==",
86
+ "version": "0.13.0-alpha.0-20250412-5fad64e7b",
87
+ "resolved": "https://registry.npmjs.org/@matter/node/-/node-0.13.0-alpha.0-20250412-5fad64e7b.tgz",
88
+ "integrity": "sha512-KJCaAla7ZDs4HwHo6gcMPsmiT2OvMtA7EZ+SwNVqd8CUNEslnktEyn9Y8scxylkcppf4mwwOnPl10rGqHqQ27g==",
89
89
  "license": "Apache-2.0",
90
90
  "dependencies": {
91
- "@matter/general": "0.13.0-alpha.0-20250408-c916c7e8",
92
- "@matter/model": "0.13.0-alpha.0-20250408-c916c7e8",
93
- "@matter/protocol": "0.13.0-alpha.0-20250408-c916c7e8",
94
- "@matter/types": "0.13.0-alpha.0-20250408-c916c7e8",
91
+ "@matter/general": "0.13.0-alpha.0-20250412-5fad64e7b",
92
+ "@matter/model": "0.13.0-alpha.0-20250412-5fad64e7b",
93
+ "@matter/protocol": "0.13.0-alpha.0-20250412-5fad64e7b",
94
+ "@matter/types": "0.13.0-alpha.0-20250412-5fad64e7b",
95
95
  "@noble/curves": "^1.8.1"
96
96
  }
97
97
  },
98
98
  "node_modules/@matter/nodejs": {
99
- "version": "0.13.0-alpha.0-20250408-c916c7e8",
100
- "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.13.0-alpha.0-20250408-c916c7e8.tgz",
101
- "integrity": "sha512-3vA1mPacdP4SF4mdaRFyzev+Fjsznte3bMYCIhz93Qji/8DuKVTtHEcxq9gqLbcAkfisbguwe63O+axg4vzf4w==",
99
+ "version": "0.13.0-alpha.0-20250412-5fad64e7b",
100
+ "resolved": "https://registry.npmjs.org/@matter/nodejs/-/nodejs-0.13.0-alpha.0-20250412-5fad64e7b.tgz",
101
+ "integrity": "sha512-cs3H+/vtpOvZhRyza/4dNMmxOJF+kehvv+TSQIWpb4bFvh+k2wgKgs+2dNrjUjdbKC4+0ObEmjDLti7KLgN7Gw==",
102
102
  "license": "Apache-2.0",
103
103
  "optional": true,
104
104
  "dependencies": {
105
- "@matter/general": "0.13.0-alpha.0-20250408-c916c7e8",
106
- "@matter/node": "0.13.0-alpha.0-20250408-c916c7e8",
107
- "@matter/protocol": "0.13.0-alpha.0-20250408-c916c7e8",
108
- "@matter/types": "0.13.0-alpha.0-20250408-c916c7e8",
105
+ "@matter/general": "0.13.0-alpha.0-20250412-5fad64e7b",
106
+ "@matter/node": "0.13.0-alpha.0-20250412-5fad64e7b",
107
+ "@matter/protocol": "0.13.0-alpha.0-20250412-5fad64e7b",
108
+ "@matter/types": "0.13.0-alpha.0-20250412-5fad64e7b",
109
109
  "node-localstorage": "^3.0.5"
110
110
  },
111
111
  "engines": {
@@ -113,25 +113,25 @@
113
113
  }
114
114
  },
115
115
  "node_modules/@matter/protocol": {
116
- "version": "0.13.0-alpha.0-20250408-c916c7e8",
117
- "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.13.0-alpha.0-20250408-c916c7e8.tgz",
118
- "integrity": "sha512-HchrugjNPnR7ZcPoWcGX+7bRdHlBofWWJVoD6z7deZVLCycaddq/o3W5KsRol4HBFyVVmxlnaK5GE14VcdWw4g==",
116
+ "version": "0.13.0-alpha.0-20250412-5fad64e7b",
117
+ "resolved": "https://registry.npmjs.org/@matter/protocol/-/protocol-0.13.0-alpha.0-20250412-5fad64e7b.tgz",
118
+ "integrity": "sha512-VLRyFSSwShpdG5PGRxp0LGDJ2zpcQJs8MecuQtJuPAfCifXKVdtXGQhxe6ESDBLNDYn41bFQvF0IFjriJVWS2g==",
119
119
  "license": "Apache-2.0",
120
120
  "dependencies": {
121
- "@matter/general": "0.13.0-alpha.0-20250408-c916c7e8",
122
- "@matter/model": "0.13.0-alpha.0-20250408-c916c7e8",
123
- "@matter/types": "0.13.0-alpha.0-20250408-c916c7e8",
121
+ "@matter/general": "0.13.0-alpha.0-20250412-5fad64e7b",
122
+ "@matter/model": "0.13.0-alpha.0-20250412-5fad64e7b",
123
+ "@matter/types": "0.13.0-alpha.0-20250412-5fad64e7b",
124
124
  "@noble/curves": "^1.8.1"
125
125
  }
126
126
  },
127
127
  "node_modules/@matter/types": {
128
- "version": "0.13.0-alpha.0-20250408-c916c7e8",
129
- "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.13.0-alpha.0-20250408-c916c7e8.tgz",
130
- "integrity": "sha512-zd7OXUbsWEdgD6J1CxPuCyHvtLHbaPGoYXmgLtVAgT6sjnmDH/4wFWdYVavTOIhhenVzg4aQ30sdi62HGyHGrw==",
128
+ "version": "0.13.0-alpha.0-20250412-5fad64e7b",
129
+ "resolved": "https://registry.npmjs.org/@matter/types/-/types-0.13.0-alpha.0-20250412-5fad64e7b.tgz",
130
+ "integrity": "sha512-+V17rduApurHl4H7iivF3DO6Zzy+4ZYdQUtrTyeFIH1rma4B29fPIxKVRjXsBPi2oIWtbQcL522Y0LhdLwBPUA==",
131
131
  "license": "Apache-2.0",
132
132
  "dependencies": {
133
- "@matter/general": "0.13.0-alpha.0-20250408-c916c7e8",
134
- "@matter/model": "0.13.0-alpha.0-20250408-c916c7e8",
133
+ "@matter/general": "0.13.0-alpha.0-20250412-5fad64e7b",
134
+ "@matter/model": "0.13.0-alpha.0-20250412-5fad64e7b",
135
135
  "@noble/curves": "^1.8.1"
136
136
  }
137
137
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.0.0-edge.3",
3
+ "version": "3.0.0-edge.5",
4
4
  "description": "Matterbridge plugin manager for Matter",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",
@@ -94,7 +94,7 @@
94
94
  }
95
95
  },
96
96
  "dependencies": {
97
- "@matter/main": "^0.13.0-alpha.0-20250408-c916c7e8",
97
+ "@matter/main": "0.13.0-alpha.0-20250412-5fad64e7b",
98
98
  "archiver": "7.0.1",
99
99
  "express": "4.21.2",
100
100
  "glob": "11.0.1",