@matterbridge/core 3.10.8-dev-20260902-361500d → 3.10.8-dev-20260903-4ab4a0f

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.
@@ -21,4 +21,5 @@ export * from './smokeCoAlarmServer.js';
21
21
  export * from './switchServer.js';
22
22
  export * from './thermostatServer.js';
23
23
  export * from './valveConfigurationAndControlServer.js';
24
+ export * from './waterTankLevelMonitoringServer.js';
24
25
  export * from './windowCoveringServer.js';
@@ -21,4 +21,5 @@ export * from './smokeCoAlarmServer.js';
21
21
  export * from './switchServer.js';
22
22
  export * from './thermostatServer.js';
23
23
  export * from './valveConfigurationAndControlServer.js';
24
+ export * from './waterTankLevelMonitoringServer.js';
24
25
  export * from './windowCoveringServer.js';
@@ -0,0 +1,11 @@
1
+ import { WaterTankLevelMonitoringServer } from '@matter/node/behaviors/water-tank-level-monitoring';
2
+ import type { WaterTankLevelMonitoring } from '@matter/types/clusters/water-tank-level-monitoring';
3
+ declare const MatterbridgeWaterTankLevelMonitoringServer_base: import("@matter/node").ClusterBehavior.Type<typeof WaterTankLevelMonitoringServer, import("@matter/types").ClusterType.WithSupportedFeatures<WaterTankLevelMonitoring, {
4
+ condition: true;
5
+ replacementProductList: true;
6
+ warning: true;
7
+ }>, import("@matter/types").ClusterType.Concrete, new () => {}, "waterTankLevelMonitoring">;
8
+ export declare class MatterbridgeWaterTankLevelMonitoringServer extends MatterbridgeWaterTankLevelMonitoringServer_base {
9
+ resetCondition(): Promise<void>;
10
+ }
11
+ export {};
@@ -0,0 +1,21 @@
1
+ import { WaterTankLevelMonitoringServer } from '@matter/node/behaviors/water-tank-level-monitoring';
2
+ import { ResourceMonitoring } from '@matter/types/clusters/resource-monitoring';
3
+ import { MatterbridgeServer } from './matterbridgeServer.js';
4
+ export class MatterbridgeWaterTankLevelMonitoringServer extends WaterTankLevelMonitoringServer.with(ResourceMonitoring.Feature.Condition, ResourceMonitoring.Feature.Warning, ResourceMonitoring.Feature.ReplacementProductList) {
5
+ async resetCondition() {
6
+ const device = this.endpoint.stateOf(MatterbridgeServer);
7
+ device.log.info(`MatterbridgeWaterTankLevelMonitoringServer: resetting condition (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
8
+ await device.commandHandler.executeHandler('WaterTankLevelMonitoring.resetCondition', {
9
+ command: 'resetCondition',
10
+ request: {},
11
+ cluster: MatterbridgeWaterTankLevelMonitoringServer.id,
12
+ attributes: this.state,
13
+ endpoint: this.endpoint,
14
+ context: this.context,
15
+ });
16
+ this.state.condition = 100;
17
+ this.state.changeIndication = ResourceMonitoring.ChangeIndication.Ok;
18
+ this.state.lastChangedTime = Math.floor(new Date().getTime() / 1000);
19
+ device.log.debug(`MatterbridgeWaterTankLevelMonitoringServer: resetCondition called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
20
+ }
21
+ }
@@ -133,7 +133,11 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
133
133
  this.state.targetPositionLiftPercent100ths = this.state.currentPositionLiftPercent100ths;
134
134
  if (this.features.positionAwareTilt)
135
135
  this.state.targetPositionTiltPercent100ths = this.state.currentPositionTiltPercent100ths;
136
- this.state.operationalStatus = { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped };
136
+ this.state.operationalStatus = {
137
+ global: WindowCovering.MovementStatus.Stopped,
138
+ ...(this.features.lift ? { lift: WindowCovering.MovementStatus.Stopped } : {}),
139
+ ...(this.features.tilt ? { tilt: WindowCovering.MovementStatus.Stopped } : {}),
140
+ };
137
141
  }
138
142
  device.log.debug(`MatterbridgeWindowCoveringServer: stopMotion result target ${this.state.targetPositionLiftPercent100ths} current ${this.state.currentPositionLiftPercent100ths} status global ${this.getMovementStatusLabel(this.state.operationalStatus.global)} lift ${this.getMovementStatusLabel(this.state.operationalStatus.lift)} tilt ${this.getMovementStatusLabel(this.state.operationalStatus.tilt)} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
139
143
  }
@@ -375,13 +375,13 @@ export async function createDemoDevices(matterbridge) {
375
375
  ep = new MatterbridgeEndpoint([getSupportedDeviceType('DoorLockController'), bridgedNode, powerSource], { id: 'DoorLockController', number: EndpointNumber(8_02) });
376
376
  await registerDevice(ep, 'Door Lock Controller', 'ENTRY-08-02');
377
377
  ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCovering'), bridgedNode, powerSource], { id: 'WindowCoveringLift', number: EndpointNumber(8_03) });
378
- ep.createDefaultWindowCoveringClusterServer();
378
+ ep.createDefaultWindowCoveringClusterServer(100_00, undefined, undefined, 10_000);
379
379
  await registerDevice(ep, 'Window Covering Lift', 'ENTRY-08-03');
380
380
  ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCovering'), bridgedNode, powerSource], { id: 'WindowCoveringTilt', number: EndpointNumber(8_03_1) });
381
- ep.createDefaultTiltWindowCoveringClusterServer();
381
+ ep.createDefaultTiltWindowCoveringClusterServer(100_00, undefined, undefined, 10_000);
382
382
  await registerDevice(ep, 'Window Covering Tilt', 'ENTRY-08-03-1');
383
383
  ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCovering'), bridgedNode, powerSource], { id: 'WindowCoveringLiftTilt', number: EndpointNumber(8_03_2) });
384
- ep.createDefaultLiftTiltWindowCoveringClusterServer();
384
+ ep.createDefaultLiftTiltWindowCoveringClusterServer(100_00, 100_00, undefined, undefined, 10_000);
385
385
  await registerDevice(ep, 'Window Covering LiftTilt', 'ENTRY-08-03-2');
386
386
  ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCoveringController'), bridgedNode, powerSource], { id: 'WindowCoveringController', number: EndpointNumber(8_04) });
387
387
  await registerDevice(ep, 'Window Covering Controller', 'ENTRY-08-04');
package/dist/export.d.ts CHANGED
@@ -19,6 +19,7 @@ export * from './behaviors/smokeCoAlarmServer.js';
19
19
  export * from './behaviors/switchServer.js';
20
20
  export * from './behaviors/thermostatServer.js';
21
21
  export * from './behaviors/valveConfigurationAndControlServer.js';
22
+ export * from './behaviors/waterTankLevelMonitoringServer.js';
22
23
  export * from './behaviors/windowCoveringServer.js';
23
24
  export { addVirtualDevice } from './helpers.js';
24
25
  export * from './matterbridgeAccessoryPlatform.js';
package/dist/export.js CHANGED
@@ -21,6 +21,7 @@ export * from './behaviors/smokeCoAlarmServer.js';
21
21
  export * from './behaviors/switchServer.js';
22
22
  export * from './behaviors/thermostatServer.js';
23
23
  export * from './behaviors/valveConfigurationAndControlServer.js';
24
+ export * from './behaviors/waterTankLevelMonitoringServer.js';
24
25
  export * from './behaviors/windowCoveringServer.js';
25
26
  export { addVirtualDevice } from './helpers.js';
26
27
  export * from './matterbridgeAccessoryPlatform.js';
package/dist/frontend.js CHANGED
@@ -1200,6 +1200,8 @@ export class Frontend extends EventEmitter {
1200
1200
  attributes += `Hepa filter: ${attributeValue}% `;
1201
1201
  if (clusterName === 'activatedCarbonFilterMonitoring' && attributeName === 'condition')
1202
1202
  attributes += `Carbon filter: ${attributeValue}% `;
1203
+ if (clusterName === 'waterTankLevelMonitoring' && attributeName === 'condition')
1204
+ attributes += `Water tank: ${attributeValue}% `;
1203
1205
  if (clusterName === 'occupancySensing' && attributeName === 'occupancy' && isValidObject(attributeValue, 1))
1204
1206
  attributes += `Occupancy: ${attributeValue.occupied} `;
1205
1207
  if (clusterName === 'illuminanceMeasurement' && attributeName === 'measuredValue') {
@@ -104,6 +104,7 @@ import { ValveConfigurationAndControl } from '@matter/types/clusters/valve-confi
104
104
  import { WakeOnLan } from '@matter/types/clusters/wake-on-lan';
105
105
  import { WaterHeaterManagement } from '@matter/types/clusters/water-heater-management';
106
106
  import { WaterHeaterMode } from '@matter/types/clusters/water-heater-mode';
107
+ import { WaterTankLevelMonitoring } from '@matter/types/clusters/water-tank-level-monitoring';
107
108
  import { WebRtcTransportProvider } from '@matter/types/clusters/web-rtc-transport-provider';
108
109
  import { WebRtcTransportRequestor } from '@matter/types/clusters/web-rtc-transport-requestor';
109
110
  import { WindowCovering } from '@matter/types/clusters/window-covering';
@@ -1276,6 +1277,7 @@ export const supportedClusters = [
1276
1277
  WakeOnLan,
1277
1278
  WaterHeaterManagement,
1278
1279
  WaterHeaterMode,
1280
+ WaterTankLevelMonitoring,
1279
1281
  WebRtcTransportProvider,
1280
1282
  WebRtcTransportRequestor,
1281
1283
  WindowCovering,
@@ -207,6 +207,7 @@ export declare class MatterbridgeEndpoint extends Endpoint {
207
207
  }, airflowDirection?: FanControl.AirflowDirection): this;
208
208
  createDefaultHepaFilterMonitoringClusterServer(condition?: number, changeIndication?: ResourceMonitoring.ChangeIndication, inPlaceIndicator?: boolean | undefined, lastChangedTime?: number | null | undefined, replacementProductList?: ResourceMonitoring.ReplacementProduct[]): this;
209
209
  createDefaultActivatedCarbonFilterMonitoringClusterServer(condition?: number, changeIndication?: ResourceMonitoring.ChangeIndication, inPlaceIndicator?: boolean | undefined, lastChangedTime?: number | null | undefined, replacementProductList?: ResourceMonitoring.ReplacementProduct[]): this;
210
+ createDefaultWaterTankLevelMonitoringClusterServer(condition?: number, changeIndication?: ResourceMonitoring.ChangeIndication, inPlaceIndicator?: boolean | undefined, lastChangedTime?: number | null | undefined, replacementProductList?: ResourceMonitoring.ReplacementProduct[]): this;
210
211
  createDefaultDoorLockClusterServer(lockState?: DoorLock.LockState, lockType?: DoorLock.LockType, autoRelockTime?: number, numberOfWeekDaySchedulesSupportedPerUser?: number, numberOfYearDaySchedulesSupportedPerUser?: number, numberOfHolidaySchedulesSupported?: number): this;
211
212
  createUserPinDoorLockClusterServer(lockState?: DoorLock.LockState, lockType?: DoorLock.LockType, autoRelockTime?: number, minPinCodeLength?: number, maxPinCodeLength?: number, numberOfWeekDaySchedulesSupportedPerUser?: number, numberOfYearDaySchedulesSupportedPerUser?: number, numberOfHolidaySchedulesSupported?: number): this;
212
213
  createDefaultModeSelectClusterServer(description: string, supportedModes: ModeSelect.ModeOption[], currentMode?: number, startUpMode?: number): this;
@@ -81,6 +81,7 @@ import { MatterbridgeSmokeCoAlarmServer } from './behaviors/smokeCoAlarmServer.j
81
81
  import { MatterbridgeSwitchServer } from './behaviors/switchServer.js';
82
82
  import { MatterbridgeThermostatServer } from './behaviors/thermostatServer.js';
83
83
  import { MatterbridgeValveConfigurationAndControlServer } from './behaviors/valveConfigurationAndControlServer.js';
84
+ import { MatterbridgeWaterTankLevelMonitoringServer } from './behaviors/waterTankLevelMonitoringServer.js';
84
85
  import { MatterbridgeWindowCoveringServer } from './behaviors/windowCoveringServer.js';
85
86
  import { CommandHandler, } from './matterbridgeEndpointCommandHandler.js';
86
87
  import { addClusterClients, addClusterServers, addFixedLabel, addOptionalClusterClients, addOptionalClusterServers, addRequiredClusterClients, addRequiredClusterServers, addUserLabel, checkNotLatinCharacters, createUniqueId, defaultFor, featuresFor, generateUniqueId, getApparentElectricalPowerMeasurementClusterServer, getAttribute, getAttributeId, getBehavior, getBehaviourTypesFromClusterClientIds, getBehaviourTypesFromClusterServerIds, getCluster, getClusterId, getDefaultDeviceEnergyManagementClusterServer, getDefaultDeviceEnergyManagementModeClusterServer, getDefaultElectricalEnergyMeasurementClusterServer, getDefaultElectricalPowerMeasurementClusterServer, getDefaultFlowMeasurementClusterServer, getDefaultIlluminanceMeasurementClusterServer, getDefaultOccupancySensingClusterServer, getDefaultOperationalStateClusterServer, getDefaultPowerSourceBatteryClusterServer, getDefaultPowerSourceRechargeableBatteryClusterServer, getDefaultPowerSourceReplaceableBatteryClusterServer, getDefaultPowerSourceWiredClusterServer, getDefaultPressureMeasurementClusterServer, getDefaultRelativeHumidityMeasurementClusterServer, getDefaultSoilMeasurementClusterServer, getDefaultTemperatureMeasurementClusterServer, getExportedElectricalEnergyMeasurementClusterServer, getImportedElectricalEnergyMeasurementClusterServer, invokeBehaviorCommand, lowercaseFirstLetter, setAttribute, setCluster, subscribeAttribute, triggerEvent, updateAttribute, } from './matterbridgeEndpointHelpers.js';
@@ -831,14 +832,13 @@ export class MatterbridgeEndpoint extends Endpoint {
831
832
  numberOfActuationsLift: 0,
832
833
  configStatus: {
833
834
  operational: true,
834
- onlineReserved: false,
835
835
  liftMovementReversed: false,
836
836
  liftPositionAware: true,
837
837
  tiltPositionAware: false,
838
838
  liftEncoderControlled: false,
839
839
  tiltEncoderControlled: false,
840
840
  },
841
- operationalStatus: { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped },
841
+ operationalStatus: { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped },
842
842
  endProductType,
843
843
  mode: { motorDirectionReversed: false, calibrationMode: false, maintenanceMode: false, ledFeedback: false },
844
844
  targetPositionLiftPercent100ths: positionPercent100ths,
@@ -855,7 +855,6 @@ export class MatterbridgeEndpoint extends Endpoint {
855
855
  numberOfActuationsTilt: 0,
856
856
  configStatus: {
857
857
  operational: true,
858
- onlineReserved: false,
859
858
  liftMovementReversed: false,
860
859
  liftPositionAware: true,
861
860
  tiltPositionAware: true,
@@ -881,14 +880,13 @@ export class MatterbridgeEndpoint extends Endpoint {
881
880
  numberOfActuationsTilt: 0,
882
881
  configStatus: {
883
882
  operational: true,
884
- onlineReserved: false,
885
883
  liftMovementReversed: false,
886
884
  liftPositionAware: false,
887
885
  tiltPositionAware: true,
888
886
  liftEncoderControlled: false,
889
887
  tiltEncoderControlled: false,
890
888
  },
891
- operationalStatus: { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped },
889
+ operationalStatus: { global: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped },
892
890
  endProductType,
893
891
  mode: { motorDirectionReversed: false, calibrationMode: false, maintenanceMode: false, ledFeedback: false },
894
892
  targetPositionTiltPercent100ths: positionTiltPercent100ths,
@@ -899,39 +897,44 @@ export class MatterbridgeEndpoint extends Endpoint {
899
897
  return this;
900
898
  }
901
899
  async setWindowCoveringTargetAsCurrentAndStopped() {
902
- const position = this.getAttribute(WindowCovering, 'currentPositionLiftPercent100ths', this.log);
903
- if (isValidNumber(position, 0, 10000)) {
904
- await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', position, this.log);
905
- await this.setAttribute(WindowCovering, 'operationalStatus', {
906
- global: WindowCovering.MovementStatus.Stopped,
907
- lift: WindowCovering.MovementStatus.Stopped,
908
- tilt: WindowCovering.MovementStatus.Stopped,
909
- }, this.log);
900
+ const { lift, tilt } = featuresFor(this, WindowCovering);
901
+ if (lift) {
902
+ const position = this.getAttribute(WindowCovering, 'currentPositionLiftPercent100ths', this.log);
903
+ if (isValidNumber(position, 0, 10000)) {
904
+ await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', position, this.log);
905
+ }
906
+ this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths and targetPositionLiftPercent100ths to ${position} and operationalStatus to Stopped.`);
910
907
  }
911
- this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths and targetPositionLiftPercent100ths to ${position} and operationalStatus to Stopped.`);
912
- if (this.hasAttributeServer(WindowCovering, 'currentPositionTiltPercent100ths')) {
908
+ if (tilt) {
913
909
  const position = this.getAttribute(WindowCovering, 'currentPositionTiltPercent100ths', this.log);
914
910
  if (isValidNumber(position, 0, 10000)) {
915
911
  await this.setAttribute(WindowCovering, 'targetPositionTiltPercent100ths', position, this.log);
916
912
  }
917
913
  this.log.debug(`Set WindowCovering currentPositionTiltPercent100ths and targetPositionTiltPercent100ths to ${position} and operationalStatus to Stopped.`);
918
914
  }
915
+ await this.setAttribute(WindowCovering, 'operationalStatus', {
916
+ global: WindowCovering.MovementStatus.Stopped,
917
+ ...(lift ? { lift: WindowCovering.MovementStatus.Stopped } : {}),
918
+ ...(tilt ? { tilt: WindowCovering.MovementStatus.Stopped } : {}),
919
+ }, this.log);
919
920
  }
920
921
  async setWindowCoveringCurrentTargetStatus(current, target, status) {
921
922
  await this.setAttribute(WindowCovering, 'currentPositionLiftPercent100ths', current, this.log);
922
923
  await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', target, this.log);
924
+ const { lift, tilt } = featuresFor(this, WindowCovering);
923
925
  await this.setAttribute(WindowCovering, 'operationalStatus', {
924
926
  global: status,
925
- lift: status,
926
- tilt: status,
927
+ ...(lift ? { lift: status } : {}),
928
+ ...(tilt ? { tilt: status } : {}),
927
929
  }, this.log);
928
930
  this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths: ${current}, targetPositionLiftPercent100ths: ${target} and operationalStatus: ${status}.`);
929
931
  }
930
932
  async setWindowCoveringStatus(status) {
933
+ const { lift, tilt } = featuresFor(this, WindowCovering);
931
934
  await this.setAttribute(WindowCovering, 'operationalStatus', {
932
935
  global: status,
933
- lift: status,
934
- tilt: status,
936
+ ...(lift ? { lift: status } : {}),
937
+ ...(tilt ? { tilt: status } : {}),
935
938
  }, this.log);
936
939
  this.log.debug(`Set WindowCovering operationalStatus: ${status}`);
937
940
  }
@@ -947,7 +950,7 @@ export class MatterbridgeEndpoint extends Endpoint {
947
950
  await this.setAttribute(WindowCovering, 'currentPositionLiftPercent100ths', liftPosition, this.log);
948
951
  await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', liftPosition, this.log);
949
952
  this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths: ${liftPosition} and targetPositionLiftPercent100ths: ${liftPosition}.`);
950
- if (tiltPosition && this.hasAttributeServer(WindowCovering, 'currentPositionTiltPercent100ths')) {
953
+ if (tiltPosition && featuresFor(this, WindowCovering).tilt) {
951
954
  await this.setAttribute(WindowCovering, 'currentPositionTiltPercent100ths', tiltPosition, this.log);
952
955
  await this.setAttribute(WindowCovering, 'targetPositionTiltPercent100ths', tiltPosition, this.log);
953
956
  this.log.debug(`Set WindowCovering currentPositionTiltPercent100ths: ${tiltPosition} and targetPositionTiltPercent100ths: ${tiltPosition}.`);
@@ -1282,6 +1285,17 @@ export class MatterbridgeEndpoint extends Endpoint {
1282
1285
  });
1283
1286
  return this;
1284
1287
  }
1288
+ createDefaultWaterTankLevelMonitoringClusterServer(condition = 100, changeIndication = ResourceMonitoring.ChangeIndication.Ok, inPlaceIndicator = true, lastChangedTime = null, replacementProductList = []) {
1289
+ this.behaviors.require(MatterbridgeWaterTankLevelMonitoringServer.with(ResourceMonitoring.Feature.Condition, ResourceMonitoring.Feature.Warning, ResourceMonitoring.Feature.ReplacementProductList), {
1290
+ condition,
1291
+ degradationDirection: ResourceMonitoring.DegradationDirection.Down,
1292
+ replacementProductList,
1293
+ changeIndication,
1294
+ inPlaceIndicator,
1295
+ lastChangedTime,
1296
+ });
1297
+ return this;
1298
+ }
1285
1299
  createDefaultDoorLockClusterServer(lockState = DoorLock.LockState.Locked, lockType = DoorLock.LockType.DeadBolt, autoRelockTime = 0, numberOfWeekDaySchedulesSupportedPerUser, numberOfYearDaySchedulesSupportedPerUser, numberOfHolidaySchedulesSupported) {
1286
1300
  this.behaviors.require(MatterbridgeDoorLockServer.with(...(numberOfWeekDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.WeekDayAccessSchedules] : []), ...(numberOfYearDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.YearDayAccessSchedules] : []), ...(numberOfHolidaySchedulesSupported !== undefined ? [DoorLock.Feature.HolidaySchedules] : [])).enable({
1287
1301
  events: { doorLockAlarm: true, lockOperation: true, lockOperationError: true },
@@ -37,6 +37,7 @@ import type { TimeSynchronization } from '@matter/types/clusters/time-synchroniz
37
37
  import type { ValveConfigurationAndControl } from '@matter/types/clusters/valve-configuration-and-control';
38
38
  import type { WaterHeaterManagement } from '@matter/types/clusters/water-heater-management';
39
39
  import type { WaterHeaterMode } from '@matter/types/clusters/water-heater-mode';
40
+ import type { WaterTankLevelMonitoring } from '@matter/types/clusters/water-tank-level-monitoring';
40
41
  import type { WindowCovering } from '@matter/types/clusters/window-covering';
41
42
  import type { ClosureControl } from './clusters/closure-control.js';
42
43
  import type { ClosureDimension } from './clusters/closure-dimension.js';
@@ -991,6 +992,13 @@ export type CommandHandlerDataMap = {
991
992
  attributes: ClusterAttributeValues<(typeof ActivatedCarbonFilterMonitoring)['attributes']>;
992
993
  endpoint: MatterbridgeEndpoint;
993
994
  };
995
+ 'WaterTankLevelMonitoring.resetCondition': {
996
+ command: 'resetCondition';
997
+ request: {};
998
+ cluster: 'waterTankLevelMonitoring';
999
+ attributes: ClusterAttributeValues<(typeof WaterTankLevelMonitoring)['attributes']>;
1000
+ endpoint: MatterbridgeEndpoint;
1001
+ };
994
1002
  'CommodityPrice.getDetailedPriceRequest': {
995
1003
  command: 'getDetailedPriceRequest';
996
1004
  request: CommodityPrice.GetDetailedPriceRequest;
@@ -48,6 +48,7 @@ import { ThermostatClient } from '@matter/node/behaviors/thermostat';
48
48
  import { ThermostatUserInterfaceConfigurationServer } from '@matter/node/behaviors/thermostat-user-interface-configuration';
49
49
  import { TotalVolatileOrganicCompoundsConcentrationMeasurementServer } from '@matter/node/behaviors/total-volatile-organic-compounds-concentration-measurement';
50
50
  import { UserLabelServer } from '@matter/node/behaviors/user-label';
51
+ import { WaterTankLevelMonitoringServer } from '@matter/node/behaviors/water-tank-level-monitoring';
51
52
  import { WindowCoveringClient } from '@matter/node/behaviors/window-covering';
52
53
  import { getClusterNameById } from '@matter/types/cluster';
53
54
  import { ActivatedCarbonFilterMonitoring } from '@matter/types/clusters/activated-carbon-filter-monitoring';
@@ -104,6 +105,7 @@ import { ThermostatUserInterfaceConfiguration } from '@matter/types/clusters/the
104
105
  import { TotalVolatileOrganicCompoundsConcentrationMeasurement } from '@matter/types/clusters/total-volatile-organic-compounds-concentration-measurement';
105
106
  import { UserLabel } from '@matter/types/clusters/user-label';
106
107
  import { ValveConfigurationAndControl } from '@matter/types/clusters/valve-configuration-and-control';
108
+ import { WaterTankLevelMonitoring } from '@matter/types/clusters/water-tank-level-monitoring';
107
109
  import { WindowCovering } from '@matter/types/clusters/window-covering';
108
110
  import { NodeId } from '@matter/types/datatype';
109
111
  import { MeasurementType } from '@matter/types/globals';
@@ -331,6 +333,8 @@ export function getBehaviourTypeFromClusterServerId(clusterId) {
331
333
  return HepaFilterMonitoringServer.with('Condition', 'Warning', 'ReplacementProductList');
332
334
  if (clusterId === ActivatedCarbonFilterMonitoring.id)
333
335
  return ActivatedCarbonFilterMonitoringServer.with('Condition', 'Warning', 'ReplacementProductList');
336
+ if (clusterId === WaterTankLevelMonitoring.id)
337
+ return WaterTankLevelMonitoringServer.with('Condition', 'Warning', 'ReplacementProductList');
334
338
  if (clusterId === CarbonMonoxideConcentrationMeasurement.id)
335
339
  return CarbonMonoxideConcentrationMeasurementServer.with('NumericMeasurement');
336
340
  if (clusterId === CarbonDioxideConcentrationMeasurement.id)
@@ -439,6 +443,11 @@ export async function invokeBehaviorCommand(endpoint, cluster, command, params)
439
443
  return;
440
444
  }
441
445
  void behavior?.['state'];
446
+ if (endpoint.behaviors.supported[behaviorId]?.lockOnInvoke) {
447
+ const transaction = agent.context.transaction;
448
+ await transaction.addResources(behavior);
449
+ await transaction.begin();
450
+ }
442
451
  const injectedSubject = { kind: 'node', id: NodeId(100) };
443
452
  const patchedContext = new Proxy(agent.context, { get: (t, k) => (k === 'fabric' ? 1 : k === 'subject' ? injectedSubject : Reflect.get(t, k, t)) });
444
453
  Object.defineProperty(behavior, 'context', { configurable: true, value: patchedContext });
@@ -564,6 +573,8 @@ export function addClusterServers(endpoint, serverList) {
564
573
  endpoint.createDefaultHepaFilterMonitoringClusterServer();
565
574
  if (serverList.includes(ActivatedCarbonFilterMonitoring.id))
566
575
  endpoint.createDefaultActivatedCarbonFilterMonitoringClusterServer();
576
+ if (serverList.includes(WaterTankLevelMonitoring.id))
577
+ endpoint.createDefaultWaterTankLevelMonitoringClusterServer();
567
578
  if (serverList.includes(CarbonMonoxideConcentrationMeasurement.id))
568
579
  endpoint.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer();
569
580
  if (serverList.includes(CarbonDioxideConcentrationMeasurement.id))
@@ -46,12 +46,15 @@ export async function getServerBehaviorFromClusterId(clusterId, features) {
46
46
  const base = mod[`${name}Server`];
47
47
  if (!base || !ClusterBehavior.isType(base) || isClientBehavior(base))
48
48
  return undefined;
49
+ const knownFeatureNames = new Set(Object.keys(base.cluster.features ?? {}).map((key) => pascalCase(key)));
49
50
  const featureNames = (Array.isArray(features)
50
51
  ? features
51
52
  : Object.entries(features ?? {})
52
53
  .filter(([, enabled]) => enabled)
53
- .map(([key]) => key)).map((key) => pascalCase(key));
54
- return featureNames.length > 0 ? base.with(...featureNames) : base;
54
+ .map(([key]) => key))
55
+ .map((key) => pascalCase(key))
56
+ .filter((key) => knownFeatureNames.has(key));
57
+ return features === undefined ? base : base.with(...featureNames);
55
58
  }
56
59
  export async function getClientBehaviorFromClusterId(clusterId) {
57
60
  const name = getClusterNameById(clusterId);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/core",
3
- "version": "3.10.8-dev-20260902-361500d",
3
+ "version": "3.10.8-dev-20260903-4ab4a0f",
4
4
  "description": "Matterbridge core library",
5
5
  "author": "https://github.com/Luligu",
6
6
  "homepage": "https://matterbridge.io/",
@@ -132,10 +132,10 @@
132
132
  },
133
133
  "dependencies": {
134
134
  "@matter/main": "0.17.9",
135
- "@matterbridge/dgram": "3.10.8-dev-20260902-361500d",
136
- "@matterbridge/thread": "3.10.8-dev-20260902-361500d",
137
- "@matterbridge/types": "3.10.8-dev-20260902-361500d",
138
- "@matterbridge/utils": "3.10.8-dev-20260902-361500d",
135
+ "@matterbridge/dgram": "3.10.8-dev-20260903-4ab4a0f",
136
+ "@matterbridge/thread": "3.10.8-dev-20260903-4ab4a0f",
137
+ "@matterbridge/types": "3.10.8-dev-20260903-4ab4a0f",
138
+ "@matterbridge/utils": "3.10.8-dev-20260903-4ab4a0f",
139
139
  "escape-html": "1.0.3",
140
140
  "express": "5.2.1",
141
141
  "express-rate-limit": "8.7.0",