@matterbridge/core 3.10.8-dev-20260902-361500d → 3.10.8-dev-20260903-014e30e
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/dist/behaviors/export.d.ts +2 -0
- package/dist/behaviors/export.js +2 -0
- package/dist/behaviors/temperatureAlarmServer.d.ts +26 -0
- package/dist/behaviors/temperatureAlarmServer.js +96 -0
- package/dist/behaviors/waterTankLevelMonitoringServer.d.ts +11 -0
- package/dist/behaviors/waterTankLevelMonitoringServer.js +21 -0
- package/dist/behaviors/windowCoveringServer.js +7 -2
- package/dist/chipTests.js +0 -8
- package/dist/demoDevices.js +7 -3
- package/dist/devices/dishwasher.d.ts +14 -2
- package/dist/devices/dishwasher.js +93 -3
- package/dist/devices/refrigerator.d.ts +2 -0
- package/dist/devices/refrigerator.js +8 -0
- package/dist/export.d.ts +2 -0
- package/dist/export.js +2 -0
- package/dist/frontend.js +4 -0
- package/dist/matterbridgeDeviceTypes.js +3 -0
- package/dist/matterbridgeEndpoint.d.ts +7 -4
- package/dist/matterbridgeEndpoint.js +60 -24
- package/dist/matterbridgeEndpointCommandHandler.d.ts +38 -0
- package/dist/matterbridgeEndpointHelpers.d.ts +1 -1
- package/dist/matterbridgeEndpointHelpers.js +21 -1
- package/dist/matterbridgeFactory.js +5 -2
- package/package.json +5 -5
|
@@ -19,6 +19,8 @@ export * from './pumpConfigurationAndControlServer.js';
|
|
|
19
19
|
export * from './serviceAreaServer.js';
|
|
20
20
|
export * from './smokeCoAlarmServer.js';
|
|
21
21
|
export * from './switchServer.js';
|
|
22
|
+
export * from './temperatureAlarmServer.js';
|
|
22
23
|
export * from './thermostatServer.js';
|
|
23
24
|
export * from './valveConfigurationAndControlServer.js';
|
|
25
|
+
export * from './waterTankLevelMonitoringServer.js';
|
|
24
26
|
export * from './windowCoveringServer.js';
|
package/dist/behaviors/export.js
CHANGED
|
@@ -19,6 +19,8 @@ export * from './pumpConfigurationAndControlServer.js';
|
|
|
19
19
|
export * from './serviceAreaServer.js';
|
|
20
20
|
export * from './smokeCoAlarmServer.js';
|
|
21
21
|
export * from './switchServer.js';
|
|
22
|
+
export * from './temperatureAlarmServer.js';
|
|
22
23
|
export * from './thermostatServer.js';
|
|
23
24
|
export * from './valveConfigurationAndControlServer.js';
|
|
25
|
+
export * from './waterTankLevelMonitoringServer.js';
|
|
24
26
|
export * from './windowCoveringServer.js';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { MaybePromise } from '@matter/general';
|
|
2
|
+
import { TemperatureAlarmServer } from '@matter/node/behaviors/temperature-alarm';
|
|
3
|
+
import { TemperatureAlarm } from '@matter/types/clusters/temperature-alarm';
|
|
4
|
+
declare class TemperatureAlarmBaseServer extends TemperatureAlarmServer {
|
|
5
|
+
static readonly schema: import("@matter/model").ClusterModel;
|
|
6
|
+
}
|
|
7
|
+
declare const MatterbridgeTemperatureAlarmServer_base: import("@matter/node").ClusterBehavior.Type<typeof TemperatureAlarmBaseServer, import("@matter/types").ClusterType.WithSupportedFeatures<TemperatureAlarm, {
|
|
8
|
+
majorThreshold: false;
|
|
9
|
+
minorThreshold: false;
|
|
10
|
+
overCriticalAdjustable: false;
|
|
11
|
+
overMajorAdjustable: false;
|
|
12
|
+
overMinorAdjustable: false;
|
|
13
|
+
overTemperature: true;
|
|
14
|
+
reset: true;
|
|
15
|
+
underCriticalAdjustable: false;
|
|
16
|
+
underMajorAdjustable: false;
|
|
17
|
+
underMinorAdjustable: false;
|
|
18
|
+
underTemperature: true;
|
|
19
|
+
}>, import("@matter/types").ClusterType.Concrete, new () => {}, "temperatureAlarm">;
|
|
20
|
+
export declare class MatterbridgeTemperatureAlarmServer extends MatterbridgeTemperatureAlarmServer_base {
|
|
21
|
+
#private;
|
|
22
|
+
initialize(): MaybePromise;
|
|
23
|
+
reset(request: TemperatureAlarm.ResetRequest): Promise<void>;
|
|
24
|
+
modifyEnabledAlarms(request: TemperatureAlarm.ModifyEnabledAlarmsRequest): Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { AttributeElement, CommandElement, EventElement, FieldElement } from '@matter/model';
|
|
2
|
+
import { TemperatureAlarmServer } from '@matter/node/behaviors/temperature-alarm';
|
|
3
|
+
import { Status, StatusResponseError } from '@matter/types';
|
|
4
|
+
import { TemperatureAlarm } from '@matter/types/clusters/temperature-alarm';
|
|
5
|
+
import { debugStringify, nf } from 'node-ansi-logger';
|
|
6
|
+
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
7
|
+
const MatterbridgeTemperatureAlarmSchema = TemperatureAlarmServer.schema.extend({}, AttributeElement({ name: 'Mask', id: 0x0000, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'Latch', id: 0x0001, type: 'AlarmBitmap', access: 'R V', conformance: 'RESET', quality: 'F' }), AttributeElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'Supported', id: 0x0003, type: 'AlarmBitmap', access: 'R V', conformance: 'M', quality: 'F' }), CommandElement({ name: 'Reset', id: 0x0000, access: 'O', conformance: 'RESET', direction: 'request', response: 'status' }, FieldElement({ name: 'Alarms', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' })), CommandElement({ name: 'ModifyEnabledAlarms', id: 0x0001, access: 'O', conformance: 'O', direction: 'request', response: 'status' }, FieldElement({ name: 'Mask', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' })), EventElement({ name: 'Notify', id: 0x0000, access: 'V', conformance: 'M', priority: 'info' }, FieldElement({ name: 'Active', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Inactive', id: 0x0001, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Mask', id: 0x0003, type: 'AlarmBitmap', conformance: 'M' })));
|
|
8
|
+
class TemperatureAlarmBaseServer extends TemperatureAlarmServer {
|
|
9
|
+
static schema = MatterbridgeTemperatureAlarmSchema;
|
|
10
|
+
}
|
|
11
|
+
export class MatterbridgeTemperatureAlarmServer extends TemperatureAlarmBaseServer.with(TemperatureAlarm.Feature.Reset, TemperatureAlarm.Feature.OverTemperature, TemperatureAlarm.Feature.UnderTemperature) {
|
|
12
|
+
initialize() {
|
|
13
|
+
this.reactTo(this.events.state$Changed, this.#emitNotify);
|
|
14
|
+
}
|
|
15
|
+
#emitNotify(state, oldState) {
|
|
16
|
+
const active = {
|
|
17
|
+
criticalOverTemperatureAlarm: Boolean(state.criticalOverTemperatureAlarm && !oldState.criticalOverTemperatureAlarm),
|
|
18
|
+
majorOverTemperatureAlarm: Boolean(state.majorOverTemperatureAlarm && !oldState.majorOverTemperatureAlarm),
|
|
19
|
+
minorOverTemperatureAlarm: Boolean(state.minorOverTemperatureAlarm && !oldState.minorOverTemperatureAlarm),
|
|
20
|
+
minorUnderTemperatureAlarm: Boolean(state.minorUnderTemperatureAlarm && !oldState.minorUnderTemperatureAlarm),
|
|
21
|
+
majorUnderTemperatureAlarm: Boolean(state.majorUnderTemperatureAlarm && !oldState.majorUnderTemperatureAlarm),
|
|
22
|
+
criticalUnderTemperatureAlarm: Boolean(state.criticalUnderTemperatureAlarm && !oldState.criticalUnderTemperatureAlarm),
|
|
23
|
+
};
|
|
24
|
+
const inactive = {
|
|
25
|
+
criticalOverTemperatureAlarm: Boolean(!state.criticalOverTemperatureAlarm && oldState.criticalOverTemperatureAlarm),
|
|
26
|
+
majorOverTemperatureAlarm: Boolean(!state.majorOverTemperatureAlarm && oldState.majorOverTemperatureAlarm),
|
|
27
|
+
minorOverTemperatureAlarm: Boolean(!state.minorOverTemperatureAlarm && oldState.minorOverTemperatureAlarm),
|
|
28
|
+
minorUnderTemperatureAlarm: Boolean(!state.minorUnderTemperatureAlarm && oldState.minorUnderTemperatureAlarm),
|
|
29
|
+
majorUnderTemperatureAlarm: Boolean(!state.majorUnderTemperatureAlarm && oldState.majorUnderTemperatureAlarm),
|
|
30
|
+
criticalUnderTemperatureAlarm: Boolean(!state.criticalUnderTemperatureAlarm && oldState.criticalUnderTemperatureAlarm),
|
|
31
|
+
};
|
|
32
|
+
this.events.notify.emit({ active, inactive, state, mask: this.state.mask }, this.context);
|
|
33
|
+
}
|
|
34
|
+
#assertAlarmsSupported(alarms, status) {
|
|
35
|
+
const unsupported = {
|
|
36
|
+
criticalOverTemperatureAlarm: Boolean(alarms.criticalOverTemperatureAlarm && !this.state.supported.criticalOverTemperatureAlarm),
|
|
37
|
+
majorOverTemperatureAlarm: Boolean(alarms.majorOverTemperatureAlarm && !this.state.supported.majorOverTemperatureAlarm),
|
|
38
|
+
minorOverTemperatureAlarm: Boolean(alarms.minorOverTemperatureAlarm && !this.state.supported.minorOverTemperatureAlarm),
|
|
39
|
+
minorUnderTemperatureAlarm: Boolean(alarms.minorUnderTemperatureAlarm && !this.state.supported.minorUnderTemperatureAlarm),
|
|
40
|
+
majorUnderTemperatureAlarm: Boolean(alarms.majorUnderTemperatureAlarm && !this.state.supported.majorUnderTemperatureAlarm),
|
|
41
|
+
criticalUnderTemperatureAlarm: Boolean(alarms.criticalUnderTemperatureAlarm && !this.state.supported.criticalUnderTemperatureAlarm),
|
|
42
|
+
};
|
|
43
|
+
if (Object.values(unsupported).some(Boolean)) {
|
|
44
|
+
throw new StatusResponseError(`MatterbridgeTemperatureAlarmServer: requested alarm is not supported (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`, status);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
#clearAlarms(alarms) {
|
|
48
|
+
return {
|
|
49
|
+
criticalOverTemperatureAlarm: Boolean(this.state.state.criticalOverTemperatureAlarm && !alarms.criticalOverTemperatureAlarm),
|
|
50
|
+
majorOverTemperatureAlarm: Boolean(this.state.state.majorOverTemperatureAlarm && !alarms.majorOverTemperatureAlarm),
|
|
51
|
+
minorOverTemperatureAlarm: Boolean(this.state.state.minorOverTemperatureAlarm && !alarms.minorOverTemperatureAlarm),
|
|
52
|
+
minorUnderTemperatureAlarm: Boolean(this.state.state.minorUnderTemperatureAlarm && !alarms.minorUnderTemperatureAlarm),
|
|
53
|
+
majorUnderTemperatureAlarm: Boolean(this.state.state.majorUnderTemperatureAlarm && !alarms.majorUnderTemperatureAlarm),
|
|
54
|
+
criticalUnderTemperatureAlarm: Boolean(this.state.state.criticalUnderTemperatureAlarm && !alarms.criticalUnderTemperatureAlarm),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
#applyMaskToState(mask) {
|
|
58
|
+
return {
|
|
59
|
+
criticalOverTemperatureAlarm: Boolean(this.state.state.criticalOverTemperatureAlarm && mask.criticalOverTemperatureAlarm),
|
|
60
|
+
majorOverTemperatureAlarm: Boolean(this.state.state.majorOverTemperatureAlarm && mask.majorOverTemperatureAlarm),
|
|
61
|
+
minorOverTemperatureAlarm: Boolean(this.state.state.minorOverTemperatureAlarm && mask.minorOverTemperatureAlarm),
|
|
62
|
+
minorUnderTemperatureAlarm: Boolean(this.state.state.minorUnderTemperatureAlarm && mask.minorUnderTemperatureAlarm),
|
|
63
|
+
majorUnderTemperatureAlarm: Boolean(this.state.state.majorUnderTemperatureAlarm && mask.majorUnderTemperatureAlarm),
|
|
64
|
+
criticalUnderTemperatureAlarm: Boolean(this.state.state.criticalUnderTemperatureAlarm && mask.criticalUnderTemperatureAlarm),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async reset(request) {
|
|
68
|
+
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
69
|
+
device.log.info(`MatterbridgeTemperatureAlarmServer: resetting alarms ${debugStringify(request.alarms)}${nf} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
70
|
+
await device.commandHandler.executeHandler('TemperatureAlarm.reset', {
|
|
71
|
+
command: 'reset',
|
|
72
|
+
request,
|
|
73
|
+
cluster: MatterbridgeTemperatureAlarmServer.id,
|
|
74
|
+
attributes: this.state,
|
|
75
|
+
endpoint: this.endpoint,
|
|
76
|
+
context: this.context,
|
|
77
|
+
});
|
|
78
|
+
this.#assertAlarmsSupported(request.alarms, Status.Failure);
|
|
79
|
+
this.state.state = this.#clearAlarms(request.alarms);
|
|
80
|
+
}
|
|
81
|
+
async modifyEnabledAlarms(request) {
|
|
82
|
+
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
83
|
+
device.log.info(`MatterbridgeTemperatureAlarmServer: modifying enabled alarms ${debugStringify(request.mask)}${nf} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
84
|
+
await device.commandHandler.executeHandler('TemperatureAlarm.modifyEnabledAlarms', {
|
|
85
|
+
command: 'modifyEnabledAlarms',
|
|
86
|
+
request,
|
|
87
|
+
cluster: MatterbridgeTemperatureAlarmServer.id,
|
|
88
|
+
attributes: this.state,
|
|
89
|
+
endpoint: this.endpoint,
|
|
90
|
+
context: this.context,
|
|
91
|
+
});
|
|
92
|
+
this.#assertAlarmsSupported(request.mask, Status.InvalidCommand);
|
|
93
|
+
this.state.mask = request.mask;
|
|
94
|
+
this.state.state = this.#applyMaskToState(request.mask);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -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
|
+
}
|
|
@@ -32,7 +32,8 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
|
|
|
32
32
|
return current < target ? WindowCovering.MovementStatus.Closing : WindowCovering.MovementStatus.Opening;
|
|
33
33
|
}
|
|
34
34
|
#updateGlobalOperationalStatus() {
|
|
35
|
-
const
|
|
35
|
+
const lift = this.state.operationalStatus.lift ?? WindowCovering.MovementStatus.Stopped;
|
|
36
|
+
const tilt = this.state.operationalStatus.tilt ?? WindowCovering.MovementStatus.Stopped;
|
|
36
37
|
this.state.operationalStatus.global = lift === WindowCovering.MovementStatus.Stopped ? tilt : lift;
|
|
37
38
|
}
|
|
38
39
|
#startLiftMovement(targetPercent100ths) {
|
|
@@ -133,7 +134,11 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
|
|
|
133
134
|
this.state.targetPositionLiftPercent100ths = this.state.currentPositionLiftPercent100ths;
|
|
134
135
|
if (this.features.positionAwareTilt)
|
|
135
136
|
this.state.targetPositionTiltPercent100ths = this.state.currentPositionTiltPercent100ths;
|
|
136
|
-
this.state.operationalStatus = {
|
|
137
|
+
this.state.operationalStatus = {
|
|
138
|
+
global: WindowCovering.MovementStatus.Stopped,
|
|
139
|
+
...(this.features.lift ? { lift: WindowCovering.MovementStatus.Stopped } : {}),
|
|
140
|
+
...(this.features.tilt ? { tilt: WindowCovering.MovementStatus.Stopped } : {}),
|
|
141
|
+
};
|
|
137
142
|
}
|
|
138
143
|
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
144
|
}
|
package/dist/chipTests.js
CHANGED
|
@@ -24,7 +24,6 @@ import { SmokeCoAlarm } from '@matter/types/clusters/smoke-co-alarm';
|
|
|
24
24
|
import { TariffPriceType, TariffUnit } from '@matter/types/globals';
|
|
25
25
|
import { MatterbridgeOccupancySensingServer } from './behaviors/occupancySensingServer.js';
|
|
26
26
|
import { cliEmitter } from './cliEmitter.js';
|
|
27
|
-
import { MatterbridgeRefrigeratorAlarmServer } from './devices/refrigerator.js';
|
|
28
27
|
import { MatterbridgeRvcOperationalStateServer, MatterbridgeRvcRunModeServer } from './devices/roboticVacuumCleaner.js';
|
|
29
28
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
30
29
|
const chipTestAppPipePath = '/tmp/matterbridge-chip-test-app-pipe';
|
|
@@ -1019,14 +1018,7 @@ async function handleChipTestAppPipeCommand(matterbridge, command) {
|
|
|
1019
1018
|
return;
|
|
1020
1019
|
case 'SetRefrigeratorDoorStatus': {
|
|
1021
1020
|
const doorOpen = Boolean(command.DoorOpen);
|
|
1022
|
-
const wasDoorOpen = Boolean(endpoint.stateOf(MatterbridgeRefrigeratorAlarmServer).state.doorOpen);
|
|
1023
1021
|
await endpoint.setCluster(RefrigeratorAlarm, { state: { doorOpen } }, matterbridge.log);
|
|
1024
|
-
await endpoint.triggerEvent('RefrigeratorAlarm', 'notify', {
|
|
1025
|
-
active: { doorOpen: doorOpen && !wasDoorOpen },
|
|
1026
|
-
inactive: { doorOpen: !doorOpen && wasDoorOpen },
|
|
1027
|
-
state: { doorOpen },
|
|
1028
|
-
mask: endpoint.stateOf(MatterbridgeRefrigeratorAlarmServer).mask,
|
|
1029
|
-
}, matterbridge.log);
|
|
1030
1022
|
matterbridge.log.info(`CHIP test app pipe set RefrigeratorAlarm.State.DoorOpen to ${doorOpen} on endpoint ${endpointId}`);
|
|
1031
1023
|
return;
|
|
1032
1024
|
}
|
package/dist/demoDevices.js
CHANGED
|
@@ -372,16 +372,20 @@ export async function createDemoDevices(matterbridge) {
|
|
|
372
372
|
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
373
373
|
ep.createUserPinDoorLockClusterServer(DoorLock.LockState.Locked, DoorLock.LockType.DeadBolt, 0, 4, 10, 2, 3, 4);
|
|
374
374
|
await registerDevice(ep, 'Door Lock User PIN Schedules', 'ENTRY-08-01-2');
|
|
375
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('DoorLock'), bridgedNode, powerSource], { id: 'DoorLockUserPinExpiring', number: EndpointNumber(8_01_3) });
|
|
376
|
+
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
377
|
+
ep.createUserPinDoorLockClusterServer(DoorLock.LockState.Locked, DoorLock.LockType.DeadBolt, 0, 4, 10, undefined, undefined, undefined, 10);
|
|
378
|
+
await registerDevice(ep, 'Door Lock User PIN Expiring', 'ENTRY-08-01-3');
|
|
375
379
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('DoorLockController'), bridgedNode, powerSource], { id: 'DoorLockController', number: EndpointNumber(8_02) });
|
|
376
380
|
await registerDevice(ep, 'Door Lock Controller', 'ENTRY-08-02');
|
|
377
381
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCovering'), bridgedNode, powerSource], { id: 'WindowCoveringLift', number: EndpointNumber(8_03) });
|
|
378
|
-
ep.createDefaultWindowCoveringClusterServer();
|
|
382
|
+
ep.createDefaultWindowCoveringClusterServer(100_00, undefined, undefined, 10_000);
|
|
379
383
|
await registerDevice(ep, 'Window Covering Lift', 'ENTRY-08-03');
|
|
380
384
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCovering'), bridgedNode, powerSource], { id: 'WindowCoveringTilt', number: EndpointNumber(8_03_1) });
|
|
381
|
-
ep.createDefaultTiltWindowCoveringClusterServer();
|
|
385
|
+
ep.createDefaultTiltWindowCoveringClusterServer(100_00, undefined, undefined, 10_000);
|
|
382
386
|
await registerDevice(ep, 'Window Covering Tilt', 'ENTRY-08-03-1');
|
|
383
387
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCovering'), bridgedNode, powerSource], { id: 'WindowCoveringLiftTilt', number: EndpointNumber(8_03_2) });
|
|
384
|
-
ep.createDefaultLiftTiltWindowCoveringClusterServer();
|
|
388
|
+
ep.createDefaultLiftTiltWindowCoveringClusterServer(100_00, 100_00, undefined, undefined, 10_000);
|
|
385
389
|
await registerDevice(ep, 'Window Covering LiftTilt', 'ENTRY-08-03-2');
|
|
386
390
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCoveringController'), bridgedNode, powerSource], { id: 'WindowCoveringController', number: EndpointNumber(8_04) });
|
|
387
391
|
await registerDevice(ep, 'Window Covering Controller', 'ENTRY-08-04');
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import type { MaybePromise } from '@matter/general';
|
|
1
2
|
import { DishwasherAlarmServer } from '@matter/node/behaviors/dishwasher-alarm';
|
|
2
3
|
import { DishwasherModeServer } from '@matter/node/behaviors/dishwasher-mode';
|
|
3
|
-
import type
|
|
4
|
+
import { type EndpointNumber } from '@matter/types';
|
|
5
|
+
import { DishwasherAlarm } from '@matter/types/clusters/dishwasher-alarm';
|
|
4
6
|
import { DishwasherMode } from '@matter/types/clusters/dishwasher-mode';
|
|
5
7
|
import { ModeBase } from '@matter/types/clusters/mode-base';
|
|
6
8
|
import type { OperationalState } from '@matter/types/clusters/operational-state';
|
|
@@ -32,6 +34,16 @@ export declare class MatterbridgeDishwasherModeServer extends DishwasherModeServ
|
|
|
32
34
|
protected handleOnOffChange(onOff: boolean): void;
|
|
33
35
|
changeToMode(request: ModeBase.ChangeToModeRequest): Promise<ModeBase.ChangeToModeResponse>;
|
|
34
36
|
}
|
|
35
|
-
|
|
37
|
+
declare class DishwasherAlarmBaseServer extends DishwasherAlarmServer {
|
|
36
38
|
static readonly schema: import("@matter/model").ClusterModel;
|
|
37
39
|
}
|
|
40
|
+
declare const MatterbridgeDishwasherAlarmServer_base: import("@matter/node").ClusterBehavior.Type<typeof DishwasherAlarmBaseServer, import("@matter/types").ClusterType.WithSupportedFeatures<DishwasherAlarm, {
|
|
41
|
+
reset: true;
|
|
42
|
+
}>, import("@matter/types").ClusterType.Concrete, new () => {}, "dishwasherAlarm">;
|
|
43
|
+
export declare class MatterbridgeDishwasherAlarmServer extends MatterbridgeDishwasherAlarmServer_base {
|
|
44
|
+
#private;
|
|
45
|
+
initialize(): MaybePromise;
|
|
46
|
+
reset(request: DishwasherAlarm.ResetRequest): Promise<void>;
|
|
47
|
+
modifyEnabledAlarms(request: DishwasherAlarm.ModifyEnabledAlarmsRequest): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
export {};
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
import { AttributeElement, EventElement, FieldElement } from '@matter/model';
|
|
1
|
+
import { AttributeElement, CommandElement, EventElement, FieldElement } from '@matter/model';
|
|
2
2
|
import { DishwasherAlarmServer } from '@matter/node/behaviors/dishwasher-alarm';
|
|
3
3
|
import { DishwasherModeServer } from '@matter/node/behaviors/dishwasher-mode';
|
|
4
|
+
import { Status, StatusResponseError } from '@matter/types';
|
|
5
|
+
import { DishwasherAlarm } from '@matter/types/clusters/dishwasher-alarm';
|
|
4
6
|
import { DishwasherMode } from '@matter/types/clusters/dishwasher-mode';
|
|
5
7
|
import { ModeBase } from '@matter/types/clusters/mode-base';
|
|
6
8
|
import { OnOff } from '@matter/types/clusters/on-off';
|
|
9
|
+
import { debugStringify, nf } from 'node-ansi-logger';
|
|
7
10
|
import { MatterbridgeServer } from '../behaviors/matterbridgeServer.js';
|
|
8
11
|
import { MatterbridgeOnOffServer } from '../behaviors/onOffServer.js';
|
|
9
12
|
import { dishwasher, powerSource } from '../matterbridgeDeviceTypes.js';
|
|
@@ -56,6 +59,7 @@ export class Dishwasher extends MatterbridgeEndpoint {
|
|
|
56
59
|
createDefaultDishwasherAlarmClusterServer() {
|
|
57
60
|
this.behaviors.require(MatterbridgeDishwasherAlarmServer, {
|
|
58
61
|
mask: { inflowError: false, drainError: false, doorError: true, tempTooLow: false, tempTooHigh: false, waterLevelError: false },
|
|
62
|
+
latch: { inflowError: false, drainError: false, doorError: false, tempTooLow: false, tempTooHigh: false, waterLevelError: false },
|
|
59
63
|
state: { inflowError: false, drainError: false, doorError: false, tempTooLow: false, tempTooHigh: false, waterLevelError: false },
|
|
60
64
|
supported: { inflowError: false, drainError: false, doorError: true, tempTooLow: false, tempTooHigh: false, waterLevelError: false },
|
|
61
65
|
});
|
|
@@ -98,7 +102,93 @@ export class MatterbridgeDishwasherModeServer extends DishwasherModeServer {
|
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
}
|
|
101
|
-
const MatterbridgeDishwasherAlarmSchema = DishwasherAlarmServer.schema.extend({}, AttributeElement({ name: 'Mask', id: 0x0000, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'Supported', id: 0x0003, type: 'AlarmBitmap', access: 'R V', conformance: 'M', quality: 'F' }), EventElement({ name: 'Notify', id: 0x0000, access: 'V', conformance: 'M', priority: 'info' }, FieldElement({ name: 'Active', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Inactive', id: 0x0001, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Mask', id: 0x0003, type: 'AlarmBitmap', conformance: 'M' })));
|
|
102
|
-
|
|
105
|
+
const MatterbridgeDishwasherAlarmSchema = DishwasherAlarmServer.schema.extend({}, AttributeElement({ name: 'Mask', id: 0x0000, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'Latch', id: 0x0001, type: 'AlarmBitmap', access: 'R V', conformance: 'RESET', quality: 'F' }), AttributeElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'Supported', id: 0x0003, type: 'AlarmBitmap', access: 'R V', conformance: 'M', quality: 'F' }), CommandElement({ name: 'Reset', id: 0x0000, access: 'O', conformance: 'RESET', direction: 'request', response: 'status' }, FieldElement({ name: 'Alarms', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' })), CommandElement({ name: 'ModifyEnabledAlarms', id: 0x0001, access: 'O', conformance: 'O', direction: 'request', response: 'status' }, FieldElement({ name: 'Mask', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' })), EventElement({ name: 'Notify', id: 0x0000, access: 'V', conformance: 'M', priority: 'info' }, FieldElement({ name: 'Active', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Inactive', id: 0x0001, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Mask', id: 0x0003, type: 'AlarmBitmap', conformance: 'M' })));
|
|
106
|
+
class DishwasherAlarmBaseServer extends DishwasherAlarmServer {
|
|
103
107
|
static schema = MatterbridgeDishwasherAlarmSchema;
|
|
104
108
|
}
|
|
109
|
+
export class MatterbridgeDishwasherAlarmServer extends DishwasherAlarmBaseServer.with(DishwasherAlarm.Feature.Reset) {
|
|
110
|
+
initialize() {
|
|
111
|
+
this.reactTo(this.events.state$Changed, this.#emitNotify);
|
|
112
|
+
}
|
|
113
|
+
#emitNotify(state, oldState) {
|
|
114
|
+
const active = {
|
|
115
|
+
inflowError: Boolean(state.inflowError && !oldState.inflowError),
|
|
116
|
+
drainError: Boolean(state.drainError && !oldState.drainError),
|
|
117
|
+
doorError: Boolean(state.doorError && !oldState.doorError),
|
|
118
|
+
tempTooLow: Boolean(state.tempTooLow && !oldState.tempTooLow),
|
|
119
|
+
tempTooHigh: Boolean(state.tempTooHigh && !oldState.tempTooHigh),
|
|
120
|
+
waterLevelError: Boolean(state.waterLevelError && !oldState.waterLevelError),
|
|
121
|
+
};
|
|
122
|
+
const inactive = {
|
|
123
|
+
inflowError: Boolean(!state.inflowError && oldState.inflowError),
|
|
124
|
+
drainError: Boolean(!state.drainError && oldState.drainError),
|
|
125
|
+
doorError: Boolean(!state.doorError && oldState.doorError),
|
|
126
|
+
tempTooLow: Boolean(!state.tempTooLow && oldState.tempTooLow),
|
|
127
|
+
tempTooHigh: Boolean(!state.tempTooHigh && oldState.tempTooHigh),
|
|
128
|
+
waterLevelError: Boolean(!state.waterLevelError && oldState.waterLevelError),
|
|
129
|
+
};
|
|
130
|
+
this.events.notify.emit({ active, inactive, state, mask: this.state.mask }, this.context);
|
|
131
|
+
}
|
|
132
|
+
#assertAlarmsSupported(alarms, status) {
|
|
133
|
+
const unsupported = {
|
|
134
|
+
inflowError: Boolean(alarms.inflowError && !this.state.supported.inflowError),
|
|
135
|
+
drainError: Boolean(alarms.drainError && !this.state.supported.drainError),
|
|
136
|
+
doorError: Boolean(alarms.doorError && !this.state.supported.doorError),
|
|
137
|
+
tempTooLow: Boolean(alarms.tempTooLow && !this.state.supported.tempTooLow),
|
|
138
|
+
tempTooHigh: Boolean(alarms.tempTooHigh && !this.state.supported.tempTooHigh),
|
|
139
|
+
waterLevelError: Boolean(alarms.waterLevelError && !this.state.supported.waterLevelError),
|
|
140
|
+
};
|
|
141
|
+
if (Object.values(unsupported).some(Boolean)) {
|
|
142
|
+
throw new StatusResponseError(`MatterbridgeDishwasherAlarmServer: requested alarm is not supported (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`, status);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
#clearAlarms(alarms) {
|
|
146
|
+
return {
|
|
147
|
+
inflowError: Boolean(this.state.state.inflowError && !alarms.inflowError),
|
|
148
|
+
drainError: Boolean(this.state.state.drainError && !alarms.drainError),
|
|
149
|
+
doorError: Boolean(this.state.state.doorError && !alarms.doorError),
|
|
150
|
+
tempTooLow: Boolean(this.state.state.tempTooLow && !alarms.tempTooLow),
|
|
151
|
+
tempTooHigh: Boolean(this.state.state.tempTooHigh && !alarms.tempTooHigh),
|
|
152
|
+
waterLevelError: Boolean(this.state.state.waterLevelError && !alarms.waterLevelError),
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
#applyMaskToState(mask) {
|
|
156
|
+
return {
|
|
157
|
+
inflowError: Boolean(this.state.state.inflowError && mask.inflowError),
|
|
158
|
+
drainError: Boolean(this.state.state.drainError && mask.drainError),
|
|
159
|
+
doorError: Boolean(this.state.state.doorError && mask.doorError),
|
|
160
|
+
tempTooLow: Boolean(this.state.state.tempTooLow && mask.tempTooLow),
|
|
161
|
+
tempTooHigh: Boolean(this.state.state.tempTooHigh && mask.tempTooHigh),
|
|
162
|
+
waterLevelError: Boolean(this.state.state.waterLevelError && mask.waterLevelError),
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
async reset(request) {
|
|
166
|
+
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
167
|
+
device.log.info(`MatterbridgeDishwasherAlarmServer: resetting alarms ${debugStringify(request.alarms)}${nf} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
168
|
+
await device.commandHandler.executeHandler('DishwasherAlarm.reset', {
|
|
169
|
+
command: 'reset',
|
|
170
|
+
request,
|
|
171
|
+
cluster: MatterbridgeDishwasherAlarmServer.id,
|
|
172
|
+
attributes: this.state,
|
|
173
|
+
endpoint: this.endpoint,
|
|
174
|
+
context: this.context,
|
|
175
|
+
});
|
|
176
|
+
this.#assertAlarmsSupported(request.alarms, Status.Failure);
|
|
177
|
+
this.state.state = this.#clearAlarms(request.alarms);
|
|
178
|
+
}
|
|
179
|
+
async modifyEnabledAlarms(request) {
|
|
180
|
+
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
181
|
+
device.log.info(`MatterbridgeDishwasherAlarmServer: modifying enabled alarms ${debugStringify(request.mask)}${nf} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
182
|
+
await device.commandHandler.executeHandler('DishwasherAlarm.modifyEnabledAlarms', {
|
|
183
|
+
command: 'modifyEnabledAlarms',
|
|
184
|
+
request,
|
|
185
|
+
cluster: MatterbridgeDishwasherAlarmServer.id,
|
|
186
|
+
attributes: this.state,
|
|
187
|
+
endpoint: this.endpoint,
|
|
188
|
+
context: this.context,
|
|
189
|
+
});
|
|
190
|
+
this.#assertAlarmsSupported(request.mask, Status.InvalidCommand);
|
|
191
|
+
this.state.mask = request.mask;
|
|
192
|
+
this.state.state = this.#applyMaskToState(request.mask);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
@@ -38,5 +38,7 @@ export declare class MatterbridgeRefrigeratorAndTemperatureControlledCabinetMode
|
|
|
38
38
|
changeToMode(request: ModeBase.ChangeToModeRequest): MaybePromise<ModeBase.ChangeToModeResponse>;
|
|
39
39
|
}
|
|
40
40
|
export declare class MatterbridgeRefrigeratorAlarmServer extends RefrigeratorAlarmServer {
|
|
41
|
+
#private;
|
|
41
42
|
static readonly schema: import("@matter/model").ClusterModel;
|
|
43
|
+
initialize(): MaybePromise;
|
|
42
44
|
}
|
|
@@ -100,4 +100,12 @@ export class MatterbridgeRefrigeratorAndTemperatureControlledCabinetModeServer e
|
|
|
100
100
|
const MatterbridgeRefrigeratorAlarmSchema = RefrigeratorAlarmServer.schema.extend({}, AttributeElement({ name: 'Mask', id: 0x0000, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', access: 'R V', conformance: 'M' }), AttributeElement({ name: 'Supported', id: 0x0003, type: 'AlarmBitmap', access: 'R V', conformance: 'M', quality: 'F' }), EventElement({ name: 'Notify', id: 0x0000, access: 'V', conformance: 'M', priority: 'info' }, FieldElement({ name: 'Active', id: 0x0000, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Inactive', id: 0x0001, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'State', id: 0x0002, type: 'AlarmBitmap', conformance: 'M' }), FieldElement({ name: 'Mask', id: 0x0003, type: 'AlarmBitmap', conformance: 'M' })));
|
|
101
101
|
export class MatterbridgeRefrigeratorAlarmServer extends RefrigeratorAlarmServer {
|
|
102
102
|
static schema = MatterbridgeRefrigeratorAlarmSchema;
|
|
103
|
+
initialize() {
|
|
104
|
+
this.reactTo(this.events.state$Changed, this.#emitNotify);
|
|
105
|
+
}
|
|
106
|
+
#emitNotify(state, oldState) {
|
|
107
|
+
const active = { doorOpen: Boolean(state.doorOpen && !oldState.doorOpen) };
|
|
108
|
+
const inactive = { doorOpen: Boolean(!state.doorOpen && oldState.doorOpen) };
|
|
109
|
+
this.events.notify.emit({ active, inactive, state, mask: this.state.mask }, this.context);
|
|
110
|
+
}
|
|
103
111
|
}
|
package/dist/export.d.ts
CHANGED
|
@@ -19,6 +19,8 @@ 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/temperatureAlarmServer.js';
|
|
23
|
+
export * from './behaviors/waterTankLevelMonitoringServer.js';
|
|
22
24
|
export * from './behaviors/windowCoveringServer.js';
|
|
23
25
|
export { addVirtualDevice } from './helpers.js';
|
|
24
26
|
export * from './matterbridgeAccessoryPlatform.js';
|
package/dist/export.js
CHANGED
|
@@ -21,6 +21,8 @@ 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/temperatureAlarmServer.js';
|
|
25
|
+
export * from './behaviors/waterTankLevelMonitoringServer.js';
|
|
24
26
|
export * from './behaviors/windowCoveringServer.js';
|
|
25
27
|
export { addVirtualDevice } from './helpers.js';
|
|
26
28
|
export * from './matterbridgeAccessoryPlatform.js';
|
package/dist/frontend.js
CHANGED
|
@@ -1200,6 +1200,10 @@ 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}% `;
|
|
1205
|
+
if (clusterName === 'temperatureAlarm' && attributeName === 'state' && isValidObject(attributeValue))
|
|
1206
|
+
attributes += `Temp alarm: ${stringify(attributeValue)} `;
|
|
1203
1207
|
if (clusterName === 'occupancySensing' && attributeName === 'occupancy' && isValidObject(attributeValue, 1))
|
|
1204
1208
|
attributes += `Occupancy: ${attributeValue.occupied} `;
|
|
1205
1209
|
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';
|
|
@@ -1264,6 +1265,7 @@ export const supportedClusters = [
|
|
|
1264
1265
|
SoilMeasurement,
|
|
1265
1266
|
Switch,
|
|
1266
1267
|
TargetNavigator,
|
|
1268
|
+
TemperatureAlarm,
|
|
1267
1269
|
TemperatureControl,
|
|
1268
1270
|
TemperatureMeasurement,
|
|
1269
1271
|
Thermostat,
|
|
@@ -1276,6 +1278,7 @@ export const supportedClusters = [
|
|
|
1276
1278
|
WakeOnLan,
|
|
1277
1279
|
WaterHeaterManagement,
|
|
1278
1280
|
WaterHeaterMode,
|
|
1281
|
+
WaterTankLevelMonitoring,
|
|
1279
1282
|
WebRtcTransportProvider,
|
|
1280
1283
|
WebRtcTransportRequestor,
|
|
1281
1284
|
WindowCovering,
|
|
@@ -18,6 +18,7 @@ import { PowerTopology } from '@matter/types/clusters/power-topology';
|
|
|
18
18
|
import { PumpConfigurationAndControl } from '@matter/types/clusters/pump-configuration-and-control';
|
|
19
19
|
import { ResourceMonitoring } from '@matter/types/clusters/resource-monitoring';
|
|
20
20
|
import { SmokeCoAlarm } from '@matter/types/clusters/smoke-co-alarm';
|
|
21
|
+
import type { TemperatureAlarm } from '@matter/types/clusters/temperature-alarm';
|
|
21
22
|
import { Thermostat } from '@matter/types/clusters/thermostat';
|
|
22
23
|
import { ThermostatUserInterfaceConfiguration } from '@matter/types/clusters/thermostat-user-interface-configuration';
|
|
23
24
|
import { ValveConfigurationAndControl } from '@matter/types/clusters/valve-configuration-and-control';
|
|
@@ -119,9 +120,9 @@ export declare class MatterbridgeEndpoint extends Endpoint {
|
|
|
119
120
|
addCommandHandler<C extends CommandHandlers>(command: C, handler: CommandHandlerFunction<C>): this;
|
|
120
121
|
removeCommandHandler<C extends CommandHandlers>(command: C, handler: CommandHandlerFunction<C>): this;
|
|
121
122
|
executeCommandHandler<C extends CommandHandlers>(command: C, request: CommandHandlerData<C>['request'], cluster: CommandHandlerData<C>['cluster'], attributes: CommandHandlerData<C>['attributes'], endpoint: CommandHandlerData<C>['endpoint']): Promise<CommandHandlerExecutionResult<C>>;
|
|
122
|
-
invokeBehaviorCommand<T extends Behavior.Type, C extends BehaviorCommandName<T>>(cluster: T, command: C, params?: BehaviorCommandParams<T, C
|
|
123
|
-
invokeBehaviorCommand<T extends ClusterType, C extends ClusterCommandName<T>>(cluster: T, command: C, params?: ClusterCommandParams<T, C
|
|
124
|
-
invokeBehaviorCommand(cluster: ClusterId | string, command: CommandHandlers, params?: Record<string, boolean | number | bigint | string | object | null
|
|
123
|
+
invokeBehaviorCommand<T extends Behavior.Type, C extends BehaviorCommandName<T>>(cluster: T, command: C, params?: BehaviorCommandParams<T, C>, waiterCondition?: () => boolean): Promise<void>;
|
|
124
|
+
invokeBehaviorCommand<T extends ClusterType, C extends ClusterCommandName<T>>(cluster: T, command: C, params?: ClusterCommandParams<T, C>, waiterCondition?: () => boolean): Promise<void>;
|
|
125
|
+
invokeBehaviorCommand(cluster: ClusterId | string, command: CommandHandlers, params?: Record<string, boolean | number | bigint | string | object | null>, waiterCondition?: () => boolean): Promise<void>;
|
|
125
126
|
addRequiredClusters(): MatterbridgeEndpoint;
|
|
126
127
|
addRequiredClusterServers(): MatterbridgeEndpoint;
|
|
127
128
|
addOptionalClusterServers(): MatterbridgeEndpoint;
|
|
@@ -207,8 +208,10 @@ export declare class MatterbridgeEndpoint extends Endpoint {
|
|
|
207
208
|
}, airflowDirection?: FanControl.AirflowDirection): this;
|
|
208
209
|
createDefaultHepaFilterMonitoringClusterServer(condition?: number, changeIndication?: ResourceMonitoring.ChangeIndication, inPlaceIndicator?: boolean | undefined, lastChangedTime?: number | null | undefined, replacementProductList?: ResourceMonitoring.ReplacementProduct[]): this;
|
|
209
210
|
createDefaultActivatedCarbonFilterMonitoringClusterServer(condition?: number, changeIndication?: ResourceMonitoring.ChangeIndication, inPlaceIndicator?: boolean | undefined, lastChangedTime?: number | null | undefined, replacementProductList?: ResourceMonitoring.ReplacementProduct[]): this;
|
|
211
|
+
createDefaultTemperatureAlarmClusterServer(criticalOverTemperatureThreshold?: number, criticalUnderTemperatureThreshold?: number, supported?: TemperatureAlarm.Alarm, mask?: TemperatureAlarm.Alarm, latch?: TemperatureAlarm.Alarm, state?: TemperatureAlarm.Alarm): this;
|
|
212
|
+
createDefaultWaterTankLevelMonitoringClusterServer(condition?: number, changeIndication?: ResourceMonitoring.ChangeIndication, inPlaceIndicator?: boolean | undefined, lastChangedTime?: number | null | undefined, replacementProductList?: ResourceMonitoring.ReplacementProduct[]): this;
|
|
210
213
|
createDefaultDoorLockClusterServer(lockState?: DoorLock.LockState, lockType?: DoorLock.LockType, autoRelockTime?: number, numberOfWeekDaySchedulesSupportedPerUser?: number, numberOfYearDaySchedulesSupportedPerUser?: number, numberOfHolidaySchedulesSupported?: number): this;
|
|
211
|
-
createUserPinDoorLockClusterServer(lockState?: DoorLock.LockState, lockType?: DoorLock.LockType, autoRelockTime?: number, minPinCodeLength?: number, maxPinCodeLength?: number, numberOfWeekDaySchedulesSupportedPerUser?: number, numberOfYearDaySchedulesSupportedPerUser?: number, numberOfHolidaySchedulesSupported?: number): this;
|
|
214
|
+
createUserPinDoorLockClusterServer(lockState?: DoorLock.LockState, lockType?: DoorLock.LockType, autoRelockTime?: number, minPinCodeLength?: number, maxPinCodeLength?: number, numberOfWeekDaySchedulesSupportedPerUser?: number, numberOfYearDaySchedulesSupportedPerUser?: number, numberOfHolidaySchedulesSupported?: number, expiringUserTimeout?: number, numberOfRfidUsersSupported?: number, minRfidCodeLength?: number, maxRfidCodeLength?: number): this;
|
|
212
215
|
createDefaultModeSelectClusterServer(description: string, supportedModes: ModeSelect.ModeOption[], currentMode?: number, startUpMode?: number): this;
|
|
213
216
|
createDefaultValveConfigurationAndControlClusterServer(valveState?: ValveConfigurationAndControl.ValveState, valveLevel?: number, movementDuration?: number, autoClose?: boolean): this;
|
|
214
217
|
createDefaultPumpConfigurationAndControlClusterServer(pumpMode?: PumpConfigurationAndControl.OperationMode, maxPressure?: number | null, maxSpeed?: number | null, maxFlow?: number | null, minConstSpeed?: number | null, maxConstSpeed?: number | null, speed?: number | null): this;
|
|
@@ -79,8 +79,10 @@ import { MatterbridgePowerSourceServer } from './behaviors/powerSourceServer.js'
|
|
|
79
79
|
import { MatterbridgePumpConfigurationAndControlServer } from './behaviors/pumpConfigurationAndControlServer.js';
|
|
80
80
|
import { MatterbridgeSmokeCoAlarmServer } from './behaviors/smokeCoAlarmServer.js';
|
|
81
81
|
import { MatterbridgeSwitchServer } from './behaviors/switchServer.js';
|
|
82
|
+
import { MatterbridgeTemperatureAlarmServer } from './behaviors/temperatureAlarmServer.js';
|
|
82
83
|
import { MatterbridgeThermostatServer } from './behaviors/thermostatServer.js';
|
|
83
84
|
import { MatterbridgeValveConfigurationAndControlServer } from './behaviors/valveConfigurationAndControlServer.js';
|
|
85
|
+
import { MatterbridgeWaterTankLevelMonitoringServer } from './behaviors/waterTankLevelMonitoringServer.js';
|
|
84
86
|
import { MatterbridgeWindowCoveringServer } from './behaviors/windowCoveringServer.js';
|
|
85
87
|
import { CommandHandler, } from './matterbridgeEndpointCommandHandler.js';
|
|
86
88
|
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';
|
|
@@ -277,8 +279,8 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
277
279
|
async executeCommandHandler(command, request, cluster, attributes, endpoint) {
|
|
278
280
|
return this.commandHandler.executeHandler(command, { command, request, cluster, attributes, endpoint });
|
|
279
281
|
}
|
|
280
|
-
async invokeBehaviorCommand(cluster, command, params) {
|
|
281
|
-
await invokeBehaviorCommand(this, cluster, command, params);
|
|
282
|
+
async invokeBehaviorCommand(cluster, command, params, waiterCondition) {
|
|
283
|
+
await invokeBehaviorCommand(this, cluster, command, params, waiterCondition);
|
|
282
284
|
}
|
|
283
285
|
addRequiredClusters() {
|
|
284
286
|
addRequiredClusterServers(this);
|
|
@@ -831,14 +833,13 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
831
833
|
numberOfActuationsLift: 0,
|
|
832
834
|
configStatus: {
|
|
833
835
|
operational: true,
|
|
834
|
-
onlineReserved: false,
|
|
835
836
|
liftMovementReversed: false,
|
|
836
837
|
liftPositionAware: true,
|
|
837
838
|
tiltPositionAware: false,
|
|
838
839
|
liftEncoderControlled: false,
|
|
839
840
|
tiltEncoderControlled: false,
|
|
840
841
|
},
|
|
841
|
-
operationalStatus: { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped
|
|
842
|
+
operationalStatus: { global: WindowCovering.MovementStatus.Stopped, lift: WindowCovering.MovementStatus.Stopped },
|
|
842
843
|
endProductType,
|
|
843
844
|
mode: { motorDirectionReversed: false, calibrationMode: false, maintenanceMode: false, ledFeedback: false },
|
|
844
845
|
targetPositionLiftPercent100ths: positionPercent100ths,
|
|
@@ -855,7 +856,6 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
855
856
|
numberOfActuationsTilt: 0,
|
|
856
857
|
configStatus: {
|
|
857
858
|
operational: true,
|
|
858
|
-
onlineReserved: false,
|
|
859
859
|
liftMovementReversed: false,
|
|
860
860
|
liftPositionAware: true,
|
|
861
861
|
tiltPositionAware: true,
|
|
@@ -881,14 +881,13 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
881
881
|
numberOfActuationsTilt: 0,
|
|
882
882
|
configStatus: {
|
|
883
883
|
operational: true,
|
|
884
|
-
onlineReserved: false,
|
|
885
884
|
liftMovementReversed: false,
|
|
886
885
|
liftPositionAware: false,
|
|
887
886
|
tiltPositionAware: true,
|
|
888
887
|
liftEncoderControlled: false,
|
|
889
888
|
tiltEncoderControlled: false,
|
|
890
889
|
},
|
|
891
|
-
operationalStatus: { global: WindowCovering.MovementStatus.Stopped,
|
|
890
|
+
operationalStatus: { global: WindowCovering.MovementStatus.Stopped, tilt: WindowCovering.MovementStatus.Stopped },
|
|
892
891
|
endProductType,
|
|
893
892
|
mode: { motorDirectionReversed: false, calibrationMode: false, maintenanceMode: false, ledFeedback: false },
|
|
894
893
|
targetPositionTiltPercent100ths: positionTiltPercent100ths,
|
|
@@ -899,39 +898,44 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
899
898
|
return this;
|
|
900
899
|
}
|
|
901
900
|
async setWindowCoveringTargetAsCurrentAndStopped() {
|
|
902
|
-
const
|
|
903
|
-
if (
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
}, this.log);
|
|
901
|
+
const { lift, tilt } = featuresFor(this, WindowCovering);
|
|
902
|
+
if (lift) {
|
|
903
|
+
const position = this.getAttribute(WindowCovering, 'currentPositionLiftPercent100ths', this.log);
|
|
904
|
+
if (isValidNumber(position, 0, 10000)) {
|
|
905
|
+
await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', position, this.log);
|
|
906
|
+
}
|
|
907
|
+
this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths and targetPositionLiftPercent100ths to ${position} and operationalStatus to Stopped.`);
|
|
910
908
|
}
|
|
911
|
-
|
|
912
|
-
if (this.hasAttributeServer(WindowCovering, 'currentPositionTiltPercent100ths')) {
|
|
909
|
+
if (tilt) {
|
|
913
910
|
const position = this.getAttribute(WindowCovering, 'currentPositionTiltPercent100ths', this.log);
|
|
914
911
|
if (isValidNumber(position, 0, 10000)) {
|
|
915
912
|
await this.setAttribute(WindowCovering, 'targetPositionTiltPercent100ths', position, this.log);
|
|
916
913
|
}
|
|
917
914
|
this.log.debug(`Set WindowCovering currentPositionTiltPercent100ths and targetPositionTiltPercent100ths to ${position} and operationalStatus to Stopped.`);
|
|
918
915
|
}
|
|
916
|
+
await this.setAttribute(WindowCovering, 'operationalStatus', {
|
|
917
|
+
global: WindowCovering.MovementStatus.Stopped,
|
|
918
|
+
...(lift ? { lift: WindowCovering.MovementStatus.Stopped } : {}),
|
|
919
|
+
...(tilt ? { tilt: WindowCovering.MovementStatus.Stopped } : {}),
|
|
920
|
+
}, this.log);
|
|
919
921
|
}
|
|
920
922
|
async setWindowCoveringCurrentTargetStatus(current, target, status) {
|
|
921
923
|
await this.setAttribute(WindowCovering, 'currentPositionLiftPercent100ths', current, this.log);
|
|
922
924
|
await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', target, this.log);
|
|
925
|
+
const { lift, tilt } = featuresFor(this, WindowCovering);
|
|
923
926
|
await this.setAttribute(WindowCovering, 'operationalStatus', {
|
|
924
927
|
global: status,
|
|
925
|
-
lift: status,
|
|
926
|
-
tilt: status,
|
|
928
|
+
...(lift ? { lift: status } : {}),
|
|
929
|
+
...(tilt ? { tilt: status } : {}),
|
|
927
930
|
}, this.log);
|
|
928
931
|
this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths: ${current}, targetPositionLiftPercent100ths: ${target} and operationalStatus: ${status}.`);
|
|
929
932
|
}
|
|
930
933
|
async setWindowCoveringStatus(status) {
|
|
934
|
+
const { lift, tilt } = featuresFor(this, WindowCovering);
|
|
931
935
|
await this.setAttribute(WindowCovering, 'operationalStatus', {
|
|
932
936
|
global: status,
|
|
933
|
-
lift: status,
|
|
934
|
-
tilt: status,
|
|
937
|
+
...(lift ? { lift: status } : {}),
|
|
938
|
+
...(tilt ? { tilt: status } : {}),
|
|
935
939
|
}, this.log);
|
|
936
940
|
this.log.debug(`Set WindowCovering operationalStatus: ${status}`);
|
|
937
941
|
}
|
|
@@ -947,7 +951,7 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
947
951
|
await this.setAttribute(WindowCovering, 'currentPositionLiftPercent100ths', liftPosition, this.log);
|
|
948
952
|
await this.setAttribute(WindowCovering, 'targetPositionLiftPercent100ths', liftPosition, this.log);
|
|
949
953
|
this.log.debug(`Set WindowCovering currentPositionLiftPercent100ths: ${liftPosition} and targetPositionLiftPercent100ths: ${liftPosition}.`);
|
|
950
|
-
if (tiltPosition && this
|
|
954
|
+
if (tiltPosition && featuresFor(this, WindowCovering).tilt) {
|
|
951
955
|
await this.setAttribute(WindowCovering, 'currentPositionTiltPercent100ths', tiltPosition, this.log);
|
|
952
956
|
await this.setAttribute(WindowCovering, 'targetPositionTiltPercent100ths', tiltPosition, this.log);
|
|
953
957
|
this.log.debug(`Set WindowCovering currentPositionTiltPercent100ths: ${tiltPosition} and targetPositionTiltPercent100ths: ${tiltPosition}.`);
|
|
@@ -1282,6 +1286,36 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
1282
1286
|
});
|
|
1283
1287
|
return this;
|
|
1284
1288
|
}
|
|
1289
|
+
createDefaultTemperatureAlarmClusterServer(criticalOverTemperatureThreshold = 60 * 100, criticalUnderTemperatureThreshold = -10 * 100, supported = { criticalOverTemperatureAlarm: true, criticalUnderTemperatureAlarm: true }, mask = supported, latch = {}, state = {}) {
|
|
1290
|
+
const bitmap = (alarm) => ({
|
|
1291
|
+
criticalOverTemperatureAlarm: Boolean(alarm.criticalOverTemperatureAlarm),
|
|
1292
|
+
majorOverTemperatureAlarm: false,
|
|
1293
|
+
minorOverTemperatureAlarm: false,
|
|
1294
|
+
minorUnderTemperatureAlarm: false,
|
|
1295
|
+
majorUnderTemperatureAlarm: false,
|
|
1296
|
+
criticalUnderTemperatureAlarm: Boolean(alarm.criticalUnderTemperatureAlarm),
|
|
1297
|
+
});
|
|
1298
|
+
this.behaviors.require(MatterbridgeTemperatureAlarmServer, {
|
|
1299
|
+
criticalOverTemperatureThreshold,
|
|
1300
|
+
criticalUnderTemperatureThreshold,
|
|
1301
|
+
latch: bitmap(latch),
|
|
1302
|
+
supported: bitmap(supported),
|
|
1303
|
+
mask: bitmap(mask),
|
|
1304
|
+
state: bitmap(state),
|
|
1305
|
+
});
|
|
1306
|
+
return this;
|
|
1307
|
+
}
|
|
1308
|
+
createDefaultWaterTankLevelMonitoringClusterServer(condition = 100, changeIndication = ResourceMonitoring.ChangeIndication.Ok, inPlaceIndicator = true, lastChangedTime = null, replacementProductList = []) {
|
|
1309
|
+
this.behaviors.require(MatterbridgeWaterTankLevelMonitoringServer.with(ResourceMonitoring.Feature.Condition, ResourceMonitoring.Feature.Warning, ResourceMonitoring.Feature.ReplacementProductList), {
|
|
1310
|
+
condition,
|
|
1311
|
+
degradationDirection: ResourceMonitoring.DegradationDirection.Down,
|
|
1312
|
+
replacementProductList,
|
|
1313
|
+
changeIndication,
|
|
1314
|
+
inPlaceIndicator,
|
|
1315
|
+
lastChangedTime,
|
|
1316
|
+
});
|
|
1317
|
+
return this;
|
|
1318
|
+
}
|
|
1285
1319
|
createDefaultDoorLockClusterServer(lockState = DoorLock.LockState.Locked, lockType = DoorLock.LockType.DeadBolt, autoRelockTime = 0, numberOfWeekDaySchedulesSupportedPerUser, numberOfYearDaySchedulesSupportedPerUser, numberOfHolidaySchedulesSupported) {
|
|
1286
1320
|
this.behaviors.require(MatterbridgeDoorLockServer.with(...(numberOfWeekDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.WeekDayAccessSchedules] : []), ...(numberOfYearDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.YearDayAccessSchedules] : []), ...(numberOfHolidaySchedulesSupported !== undefined ? [DoorLock.Feature.HolidaySchedules] : [])).enable({
|
|
1287
1321
|
events: { doorLockAlarm: true, lockOperation: true, lockOperationError: true },
|
|
@@ -1299,8 +1333,8 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
1299
1333
|
});
|
|
1300
1334
|
return this;
|
|
1301
1335
|
}
|
|
1302
|
-
createUserPinDoorLockClusterServer(lockState = DoorLock.LockState.Locked, lockType = DoorLock.LockType.DeadBolt, autoRelockTime = 0, minPinCodeLength = 4, maxPinCodeLength = 10, numberOfWeekDaySchedulesSupportedPerUser, numberOfYearDaySchedulesSupportedPerUser, numberOfHolidaySchedulesSupported) {
|
|
1303
|
-
this.behaviors.require(MatterbridgeDoorLockServer.with(DoorLock.Feature.User, DoorLock.Feature.PinCredential, ...(numberOfWeekDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.WeekDayAccessSchedules] : []), ...(numberOfYearDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.YearDayAccessSchedules] : []), ...(numberOfHolidaySchedulesSupported !== undefined ? [DoorLock.Feature.HolidaySchedules] : [])).enable({
|
|
1336
|
+
createUserPinDoorLockClusterServer(lockState = DoorLock.LockState.Locked, lockType = DoorLock.LockType.DeadBolt, autoRelockTime = 0, minPinCodeLength = 4, maxPinCodeLength = 10, numberOfWeekDaySchedulesSupportedPerUser, numberOfYearDaySchedulesSupportedPerUser, numberOfHolidaySchedulesSupported, expiringUserTimeout, numberOfRfidUsersSupported, minRfidCodeLength = 8, maxRfidCodeLength = 20) {
|
|
1337
|
+
this.behaviors.require(MatterbridgeDoorLockServer.with(DoorLock.Feature.User, DoorLock.Feature.PinCredential, ...(numberOfWeekDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.WeekDayAccessSchedules] : []), ...(numberOfYearDaySchedulesSupportedPerUser !== undefined ? [DoorLock.Feature.YearDayAccessSchedules] : []), ...(numberOfHolidaySchedulesSupported !== undefined ? [DoorLock.Feature.HolidaySchedules] : []), ...(numberOfRfidUsersSupported !== undefined ? [DoorLock.Feature.RfidCredential] : [])).enable({
|
|
1304
1338
|
events: { doorLockAlarm: true, lockOperation: true, lockOperationError: true },
|
|
1305
1339
|
commands: { lockDoor: true, unlockDoor: true, unlockWithTimeout: true },
|
|
1306
1340
|
}), {
|
|
@@ -1318,9 +1352,11 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
1318
1352
|
numberOfTotalUsersSupported: 10,
|
|
1319
1353
|
credentialRulesSupport: { single: true },
|
|
1320
1354
|
numberOfCredentialsSupportedPerUser: 10,
|
|
1355
|
+
...(expiringUserTimeout !== undefined ? { expiringUserTimeout } : {}),
|
|
1321
1356
|
...(numberOfWeekDaySchedulesSupportedPerUser !== undefined ? { numberOfWeekDaySchedulesSupportedPerUser } : {}),
|
|
1322
1357
|
...(numberOfYearDaySchedulesSupportedPerUser !== undefined ? { numberOfYearDaySchedulesSupportedPerUser } : {}),
|
|
1323
1358
|
...(numberOfHolidaySchedulesSupported !== undefined ? { numberOfHolidaySchedulesSupported } : {}),
|
|
1359
|
+
...(numberOfRfidUsersSupported !== undefined ? { numberOfRfidUsersSupported, minRfidCodeLength, maxRfidCodeLength } : {}),
|
|
1324
1360
|
});
|
|
1325
1361
|
return this;
|
|
1326
1362
|
}
|
|
@@ -8,6 +8,7 @@ import type { CommodityPrice } from '@matter/types/clusters/commodity-price';
|
|
|
8
8
|
import type { CommodityTariff } from '@matter/types/clusters/commodity-tariff';
|
|
9
9
|
import type { DeviceEnergyManagement } from '@matter/types/clusters/device-energy-management';
|
|
10
10
|
import type { DeviceEnergyManagementMode } from '@matter/types/clusters/device-energy-management-mode';
|
|
11
|
+
import type { DishwasherAlarm } from '@matter/types/clusters/dishwasher-alarm';
|
|
11
12
|
import type { DishwasherMode } from '@matter/types/clusters/dishwasher-mode';
|
|
12
13
|
import type { DoorLock } from '@matter/types/clusters/door-lock';
|
|
13
14
|
import type { EnergyEvse } from '@matter/types/clusters/energy-evse';
|
|
@@ -30,6 +31,7 @@ import type { RvcOperationalState } from '@matter/types/clusters/rvc-operational
|
|
|
30
31
|
import type { RvcRunMode } from '@matter/types/clusters/rvc-run-mode';
|
|
31
32
|
import type { ServiceArea } from '@matter/types/clusters/service-area';
|
|
32
33
|
import type { SmokeCoAlarm } from '@matter/types/clusters/smoke-co-alarm';
|
|
34
|
+
import type { TemperatureAlarm } from '@matter/types/clusters/temperature-alarm';
|
|
33
35
|
import type { TemperatureControl } from '@matter/types/clusters/temperature-control';
|
|
34
36
|
import type { Thermostat } from '@matter/types/clusters/thermostat';
|
|
35
37
|
import type { ThreadNetworkDiagnostics } from '@matter/types/clusters/thread-network-diagnostics';
|
|
@@ -37,6 +39,7 @@ import type { TimeSynchronization } from '@matter/types/clusters/time-synchroniz
|
|
|
37
39
|
import type { ValveConfigurationAndControl } from '@matter/types/clusters/valve-configuration-and-control';
|
|
38
40
|
import type { WaterHeaterManagement } from '@matter/types/clusters/water-heater-management';
|
|
39
41
|
import type { WaterHeaterMode } from '@matter/types/clusters/water-heater-mode';
|
|
42
|
+
import type { WaterTankLevelMonitoring } from '@matter/types/clusters/water-tank-level-monitoring';
|
|
40
43
|
import type { WindowCovering } from '@matter/types/clusters/window-covering';
|
|
41
44
|
import type { ClosureControl } from './clusters/closure-control.js';
|
|
42
45
|
import type { ClosureDimension } from './clusters/closure-dimension.js';
|
|
@@ -673,6 +676,34 @@ export type CommandHandlerDataMap = {
|
|
|
673
676
|
attributes: ClusterAttributeValues<(typeof SmokeCoAlarm)['attributes']>;
|
|
674
677
|
endpoint: MatterbridgeEndpoint;
|
|
675
678
|
};
|
|
679
|
+
'DishwasherAlarm.reset': {
|
|
680
|
+
command: 'reset';
|
|
681
|
+
request: DishwasherAlarm.ResetRequest;
|
|
682
|
+
cluster: 'dishwasherAlarm';
|
|
683
|
+
attributes: ClusterAttributeValues<(typeof DishwasherAlarm)['attributes']>;
|
|
684
|
+
endpoint: MatterbridgeEndpoint;
|
|
685
|
+
};
|
|
686
|
+
'DishwasherAlarm.modifyEnabledAlarms': {
|
|
687
|
+
command: 'modifyEnabledAlarms';
|
|
688
|
+
request: DishwasherAlarm.ModifyEnabledAlarmsRequest;
|
|
689
|
+
cluster: 'dishwasherAlarm';
|
|
690
|
+
attributes: ClusterAttributeValues<(typeof DishwasherAlarm)['attributes']>;
|
|
691
|
+
endpoint: MatterbridgeEndpoint;
|
|
692
|
+
};
|
|
693
|
+
'TemperatureAlarm.reset': {
|
|
694
|
+
command: 'reset';
|
|
695
|
+
request: TemperatureAlarm.ResetRequest;
|
|
696
|
+
cluster: 'temperatureAlarm';
|
|
697
|
+
attributes: ClusterAttributeValues<(typeof TemperatureAlarm)['attributes']>;
|
|
698
|
+
endpoint: MatterbridgeEndpoint;
|
|
699
|
+
};
|
|
700
|
+
'TemperatureAlarm.modifyEnabledAlarms': {
|
|
701
|
+
command: 'modifyEnabledAlarms';
|
|
702
|
+
request: TemperatureAlarm.ModifyEnabledAlarmsRequest;
|
|
703
|
+
cluster: 'temperatureAlarm';
|
|
704
|
+
attributes: ClusterAttributeValues<(typeof TemperatureAlarm)['attributes']>;
|
|
705
|
+
endpoint: MatterbridgeEndpoint;
|
|
706
|
+
};
|
|
676
707
|
'resetCounts': CommandHandlerData<'ThreadNetworkDiagnostics.resetCounts'>;
|
|
677
708
|
'ThreadNetworkDiagnostics.resetCounts': {
|
|
678
709
|
command: 'resetCounts';
|
|
@@ -991,6 +1022,13 @@ export type CommandHandlerDataMap = {
|
|
|
991
1022
|
attributes: ClusterAttributeValues<(typeof ActivatedCarbonFilterMonitoring)['attributes']>;
|
|
992
1023
|
endpoint: MatterbridgeEndpoint;
|
|
993
1024
|
};
|
|
1025
|
+
'WaterTankLevelMonitoring.resetCondition': {
|
|
1026
|
+
command: 'resetCondition';
|
|
1027
|
+
request: {};
|
|
1028
|
+
cluster: 'waterTankLevelMonitoring';
|
|
1029
|
+
attributes: ClusterAttributeValues<(typeof WaterTankLevelMonitoring)['attributes']>;
|
|
1030
|
+
endpoint: MatterbridgeEndpoint;
|
|
1031
|
+
};
|
|
994
1032
|
'CommodityPrice.getDetailedPriceRequest': {
|
|
995
1033
|
command: 'getDetailedPriceRequest';
|
|
996
1034
|
request: CommodityPrice.GetDetailedPriceRequest;
|
|
@@ -41,7 +41,7 @@ export declare function getBehaviourTypesFromClusterClientIds(clusterClientList:
|
|
|
41
41
|
export declare function getBehaviourTypeFromClusterServerId(clusterId: ClusterId): Behavior.Type | undefined;
|
|
42
42
|
export declare function getBehaviourTypeFromClusterClientId(clusterId: ClusterId): ClusterBehavior.Type | undefined;
|
|
43
43
|
export declare function getBehavior(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string): Behavior.Type | undefined;
|
|
44
|
-
export declare function invokeBehaviorCommand(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, command: CommandHandlers, params?: Record<string, boolean | number | bigint | string | object | null
|
|
44
|
+
export declare function invokeBehaviorCommand(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, command: CommandHandlers, params?: Record<string, boolean | number | bigint | string | object | null>, waiterCondition?: () => boolean): Promise<boolean>;
|
|
45
45
|
export declare function invokeSubscribeHandler(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, attribute: string, newValue: unknown, oldValue: unknown): Promise<boolean>;
|
|
46
46
|
export declare function addRequiredClusterServers(endpoint: MatterbridgeEndpoint): void;
|
|
47
47
|
export declare function addOptionalClusterServers(endpoint: MatterbridgeEndpoint): void;
|
|
@@ -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';
|
|
@@ -98,18 +99,21 @@ import { ScenesManagement } from '@matter/types/clusters/scenes-management';
|
|
|
98
99
|
import { SmokeCoAlarm } from '@matter/types/clusters/smoke-co-alarm';
|
|
99
100
|
import { SoilMeasurement } from '@matter/types/clusters/soil-measurement';
|
|
100
101
|
import { Switch } from '@matter/types/clusters/switch';
|
|
102
|
+
import { TemperatureAlarm } from '@matter/types/clusters/temperature-alarm';
|
|
101
103
|
import { TemperatureMeasurement } from '@matter/types/clusters/temperature-measurement';
|
|
102
104
|
import { Thermostat } from '@matter/types/clusters/thermostat';
|
|
103
105
|
import { ThermostatUserInterfaceConfiguration } from '@matter/types/clusters/thermostat-user-interface-configuration';
|
|
104
106
|
import { TotalVolatileOrganicCompoundsConcentrationMeasurement } from '@matter/types/clusters/total-volatile-organic-compounds-concentration-measurement';
|
|
105
107
|
import { UserLabel } from '@matter/types/clusters/user-label';
|
|
106
108
|
import { ValveConfigurationAndControl } from '@matter/types/clusters/valve-configuration-and-control';
|
|
109
|
+
import { WaterTankLevelMonitoring } from '@matter/types/clusters/water-tank-level-monitoring';
|
|
107
110
|
import { WindowCovering } from '@matter/types/clusters/window-covering';
|
|
108
111
|
import { NodeId } from '@matter/types/datatype';
|
|
109
112
|
import { MeasurementType } from '@matter/types/globals';
|
|
110
113
|
import { deepEqual } from '@matterbridge/utils/deep-equal';
|
|
111
114
|
import { logModuleLoaded } from '@matterbridge/utils/loader';
|
|
112
115
|
import { isValidArray } from '@matterbridge/utils/validate';
|
|
116
|
+
import { waiter } from '@matterbridge/utils/wait';
|
|
113
117
|
import { BLUE, CYAN, db, debugStringify, er, hk, nf, or, wr, YELLOW, zb } from 'node-ansi-logger';
|
|
114
118
|
import { MatterbridgeBindingServer } from './behaviors/bindingServer.js';
|
|
115
119
|
import { MatterbridgeBooleanStateConfigurationServer } from './behaviors/booleanStateConfigurationServer.js';
|
|
@@ -127,6 +131,7 @@ import { MatterbridgeOperationalStateServer } from './behaviors/operationalState
|
|
|
127
131
|
import { MatterbridgePowerSourceServer } from './behaviors/powerSourceServer.js';
|
|
128
132
|
import { MatterbridgePumpConfigurationAndControlServer } from './behaviors/pumpConfigurationAndControlServer.js';
|
|
129
133
|
import { MatterbridgeSmokeCoAlarmServer } from './behaviors/smokeCoAlarmServer.js';
|
|
134
|
+
import { MatterbridgeTemperatureAlarmServer } from './behaviors/temperatureAlarmServer.js';
|
|
130
135
|
import { MatterbridgeThermostatServer } from './behaviors/thermostatServer.js';
|
|
131
136
|
import { MatterbridgeValveConfigurationAndControlServer } from './behaviors/valveConfigurationAndControlServer.js';
|
|
132
137
|
import { MatterbridgeWindowCoveringServer } from './behaviors/windowCoveringServer.js';
|
|
@@ -305,6 +310,8 @@ export function getBehaviourTypeFromClusterServerId(clusterId) {
|
|
|
305
310
|
return BooleanStateServer.enable({ events: { stateChange: true } });
|
|
306
311
|
if (clusterId === BooleanStateConfiguration.id)
|
|
307
312
|
return MatterbridgeBooleanStateConfigurationServer;
|
|
313
|
+
if (clusterId === TemperatureAlarm.id)
|
|
314
|
+
return MatterbridgeTemperatureAlarmServer;
|
|
308
315
|
if (clusterId === PowerTopology.id)
|
|
309
316
|
return PowerTopologyServer.with('TreeTopology');
|
|
310
317
|
if (clusterId === ElectricalPowerMeasurement.id)
|
|
@@ -331,6 +338,8 @@ export function getBehaviourTypeFromClusterServerId(clusterId) {
|
|
|
331
338
|
return HepaFilterMonitoringServer.with('Condition', 'Warning', 'ReplacementProductList');
|
|
332
339
|
if (clusterId === ActivatedCarbonFilterMonitoring.id)
|
|
333
340
|
return ActivatedCarbonFilterMonitoringServer.with('Condition', 'Warning', 'ReplacementProductList');
|
|
341
|
+
if (clusterId === WaterTankLevelMonitoring.id)
|
|
342
|
+
return WaterTankLevelMonitoringServer.with('Condition', 'Warning', 'ReplacementProductList');
|
|
334
343
|
if (clusterId === CarbonMonoxideConcentrationMeasurement.id)
|
|
335
344
|
return CarbonMonoxideConcentrationMeasurementServer.with('NumericMeasurement');
|
|
336
345
|
if (clusterId === CarbonDioxideConcentrationMeasurement.id)
|
|
@@ -422,7 +431,7 @@ export function getBehavior(endpoint, cluster) {
|
|
|
422
431
|
}
|
|
423
432
|
return behavior;
|
|
424
433
|
}
|
|
425
|
-
export async function invokeBehaviorCommand(endpoint, cluster, command, params) {
|
|
434
|
+
export async function invokeBehaviorCommand(endpoint, cluster, command, params, waiterCondition) {
|
|
426
435
|
const behaviorId = getBehavior(endpoint, cluster)?.id;
|
|
427
436
|
if (!behaviorId) {
|
|
428
437
|
endpoint.log?.error(`invokeBehaviorCommand error: command ${hk}${command}${er} not found on endpoint ${or}${endpoint.maybeId}${er}:${or}${endpoint.maybeNumber}${er}`);
|
|
@@ -439,6 +448,11 @@ export async function invokeBehaviorCommand(endpoint, cluster, command, params)
|
|
|
439
448
|
return;
|
|
440
449
|
}
|
|
441
450
|
void behavior?.['state'];
|
|
451
|
+
if (endpoint.behaviors.supported[behaviorId]?.lockOnInvoke) {
|
|
452
|
+
const transaction = agent.context.transaction;
|
|
453
|
+
await transaction.addResources(behavior);
|
|
454
|
+
await transaction.begin();
|
|
455
|
+
}
|
|
442
456
|
const injectedSubject = { kind: 'node', id: NodeId(100) };
|
|
443
457
|
const patchedContext = new Proxy(agent.context, { get: (t, k) => (k === 'fabric' ? 1 : k === 'subject' ? injectedSubject : Reflect.get(t, k, t)) });
|
|
444
458
|
Object.defineProperty(behavior, 'context', { configurable: true, value: patchedContext });
|
|
@@ -450,6 +464,8 @@ export async function invokeBehaviorCommand(endpoint, cluster, command, params)
|
|
|
450
464
|
delete behavior.context;
|
|
451
465
|
}
|
|
452
466
|
});
|
|
467
|
+
if (invoked && waiterCondition)
|
|
468
|
+
return await waiter(`invokeBehaviorCommand ${command}`, waiterCondition, false, 1000, 50);
|
|
453
469
|
return invoked;
|
|
454
470
|
}
|
|
455
471
|
export async function invokeSubscribeHandler(endpoint, cluster, attribute, newValue, oldValue) {
|
|
@@ -538,6 +554,8 @@ export function addClusterServers(endpoint, serverList) {
|
|
|
538
554
|
endpoint.createDefaultBooleanStateClusterServer();
|
|
539
555
|
if (serverList.includes(BooleanStateConfiguration.id))
|
|
540
556
|
endpoint.createDefaultBooleanStateConfigurationClusterServer();
|
|
557
|
+
if (serverList.includes(TemperatureAlarm.id))
|
|
558
|
+
endpoint.createDefaultTemperatureAlarmClusterServer();
|
|
541
559
|
if (serverList.includes(PowerTopology.id))
|
|
542
560
|
endpoint.createDefaultPowerTopologyClusterServer();
|
|
543
561
|
if (serverList.includes(ElectricalPowerMeasurement.id))
|
|
@@ -564,6 +582,8 @@ export function addClusterServers(endpoint, serverList) {
|
|
|
564
582
|
endpoint.createDefaultHepaFilterMonitoringClusterServer();
|
|
565
583
|
if (serverList.includes(ActivatedCarbonFilterMonitoring.id))
|
|
566
584
|
endpoint.createDefaultActivatedCarbonFilterMonitoringClusterServer();
|
|
585
|
+
if (serverList.includes(WaterTankLevelMonitoring.id))
|
|
586
|
+
endpoint.createDefaultWaterTankLevelMonitoringClusterServer();
|
|
567
587
|
if (serverList.includes(CarbonMonoxideConcentrationMeasurement.id))
|
|
568
588
|
endpoint.createDefaultCarbonMonoxideConcentrationMeasurementClusterServer();
|
|
569
589
|
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))
|
|
54
|
-
|
|
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-
|
|
3
|
+
"version": "3.10.8-dev-20260903-014e30e",
|
|
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-
|
|
136
|
-
"@matterbridge/thread": "3.10.8-dev-
|
|
137
|
-
"@matterbridge/types": "3.10.8-dev-
|
|
138
|
-
"@matterbridge/utils": "3.10.8-dev-
|
|
135
|
+
"@matterbridge/dgram": "3.10.8-dev-20260903-014e30e",
|
|
136
|
+
"@matterbridge/thread": "3.10.8-dev-20260903-014e30e",
|
|
137
|
+
"@matterbridge/types": "3.10.8-dev-20260903-014e30e",
|
|
138
|
+
"@matterbridge/utils": "3.10.8-dev-20260903-014e30e",
|
|
139
139
|
"escape-html": "1.0.3",
|
|
140
140
|
"express": "5.2.1",
|
|
141
141
|
"express-rate-limit": "8.7.0",
|