@matterbridge/core 3.10.8-dev-20260901-c4963a1 → 3.10.8-dev-20260902-361500d
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/windowCoveringServer.d.ts +6 -2
- package/dist/behaviors/windowCoveringServer.js +32 -26
- package/dist/demoDevices.js +27 -2
- package/dist/devices/closure.d.ts +18 -5
- package/dist/devices/closure.js +121 -37
- package/dist/devices/closurePanel.d.ts +6 -4
- package/dist/devices/closurePanel.js +24 -17
- package/dist/devices/electricalUtilityMeter.d.ts +15 -0
- package/dist/devices/electricalUtilityMeter.js +16 -16
- package/dist/matterbridgeEndpointHelpers.js +1 -1
- package/dist/matterbridgeFactory.d.ts +1 -0
- package/dist/matterbridgeFactory.js +18 -2
- package/package.json +5 -5
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Timer } from '@matter/general';
|
|
1
2
|
import { WindowCoveringBaseServer, WindowCoveringServer } from '@matter/node/behaviors/window-covering';
|
|
2
3
|
import { WindowCovering } from '@matter/types/clusters/window-covering';
|
|
3
4
|
declare const MatterbridgeWindowCoveringServer_base: import("@matter/node").ClusterBehavior.Type<typeof WindowCoveringServer, import("@matter/types").ClusterType.WithSupportedFeatures<WindowCovering, {
|
|
@@ -18,11 +19,14 @@ export declare class MatterbridgeWindowCoveringServer extends MatterbridgeWindow
|
|
|
18
19
|
stopMotion(): Promise<void>;
|
|
19
20
|
goToLiftPercentage(request: WindowCovering.GoToLiftPercentageRequest): Promise<void>;
|
|
20
21
|
goToTiltPercentage(request: WindowCovering.GoToTiltPercentageRequest): Promise<void>;
|
|
22
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
21
23
|
}
|
|
22
24
|
export declare namespace MatterbridgeWindowCoveringServer {
|
|
23
25
|
class Internal extends WindowCoveringBaseServer.Internal {
|
|
24
|
-
liftMovementTimer?:
|
|
25
|
-
|
|
26
|
+
liftMovementTimer?: Timer;
|
|
27
|
+
liftMovementTarget: number;
|
|
28
|
+
tiltMovementTimer?: Timer;
|
|
29
|
+
tiltMovementTarget: number;
|
|
26
30
|
}
|
|
27
31
|
class State extends WindowCoveringBaseServer.State {
|
|
28
32
|
movementDuration: number;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Millis, Time } from '@matter/general';
|
|
1
2
|
import { WindowCoveringBaseServer, WindowCoveringServer } from '@matter/node/behaviors/window-covering';
|
|
2
3
|
import { WindowCovering } from '@matter/types/clusters/window-covering';
|
|
3
4
|
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
@@ -35,7 +36,7 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
|
|
|
35
36
|
this.state.operationalStatus.global = lift === WindowCovering.MovementStatus.Stopped ? tilt : lift;
|
|
36
37
|
}
|
|
37
38
|
#startLiftMovement(targetPercent100ths) {
|
|
38
|
-
|
|
39
|
+
this.internal.liftMovementTimer?.stop();
|
|
39
40
|
this.internal.liftMovementTimer = undefined;
|
|
40
41
|
if (this.state.movementDuration <= 0)
|
|
41
42
|
return;
|
|
@@ -44,19 +45,17 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
|
|
|
44
45
|
this.#updateGlobalOperationalStatus();
|
|
45
46
|
if (status === WindowCovering.MovementStatus.Stopped)
|
|
46
47
|
return;
|
|
47
|
-
this.internal.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
await windowCovering.setAttribute(WindowCovering, 'operationalStatus', { global: tilt, lift: WindowCovering.MovementStatus.Stopped, tilt });
|
|
57
|
-
};
|
|
48
|
+
this.internal.liftMovementTarget = targetPercent100ths;
|
|
49
|
+
this.internal.liftMovementTimer = Time.getTimer('WindowCovering lift movement complete', Millis(this.state.movementDuration), this.callback(this.#completeLiftMovement, { lock: true })).start();
|
|
50
|
+
}
|
|
51
|
+
#completeLiftMovement() {
|
|
52
|
+
this.internal.liftMovementTimer = undefined;
|
|
53
|
+
this.state.currentPositionLiftPercent100ths = this.internal.liftMovementTarget;
|
|
54
|
+
this.state.operationalStatus.lift = WindowCovering.MovementStatus.Stopped;
|
|
55
|
+
this.#updateGlobalOperationalStatus();
|
|
56
|
+
}
|
|
58
57
|
#startTiltMovement(targetPercent100ths) {
|
|
59
|
-
|
|
58
|
+
this.internal.tiltMovementTimer?.stop();
|
|
60
59
|
this.internal.tiltMovementTimer = undefined;
|
|
61
60
|
if (this.state.movementDuration <= 0)
|
|
62
61
|
return;
|
|
@@ -65,17 +64,15 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
|
|
|
65
64
|
this.#updateGlobalOperationalStatus();
|
|
66
65
|
if (status === WindowCovering.MovementStatus.Stopped)
|
|
67
66
|
return;
|
|
68
|
-
this.internal.
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
await windowCovering.setAttribute(WindowCovering, 'operationalStatus', { global: lift, lift, tilt: WindowCovering.MovementStatus.Stopped });
|
|
78
|
-
};
|
|
67
|
+
this.internal.tiltMovementTarget = targetPercent100ths;
|
|
68
|
+
this.internal.tiltMovementTimer = Time.getTimer('WindowCovering tilt movement complete', Millis(this.state.movementDuration), this.callback(this.#completeTiltMovement, { lock: true })).start();
|
|
69
|
+
}
|
|
70
|
+
#completeTiltMovement() {
|
|
71
|
+
this.internal.tiltMovementTimer = undefined;
|
|
72
|
+
this.state.currentPositionTiltPercent100ths = this.internal.tiltMovementTarget;
|
|
73
|
+
this.state.operationalStatus.tilt = WindowCovering.MovementStatus.Stopped;
|
|
74
|
+
this.#updateGlobalOperationalStatus();
|
|
75
|
+
}
|
|
79
76
|
async upOrOpen() {
|
|
80
77
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
81
78
|
device.log.info(`MatterbridgeWindowCoveringServer: opening cover (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
@@ -127,9 +124,9 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
|
|
|
127
124
|
});
|
|
128
125
|
device.log.debug(`MatterbridgeWindowCoveringServer: stopMotion called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
129
126
|
await super.stopMotion();
|
|
130
|
-
|
|
127
|
+
this.internal.liftMovementTimer?.stop();
|
|
131
128
|
this.internal.liftMovementTimer = undefined;
|
|
132
|
-
|
|
129
|
+
this.internal.tiltMovementTimer?.stop();
|
|
133
130
|
this.internal.tiltMovementTimer = undefined;
|
|
134
131
|
if (this.state.movementDuration > 0) {
|
|
135
132
|
if (this.features.positionAwareLift)
|
|
@@ -174,11 +171,20 @@ export class MatterbridgeWindowCoveringServer extends WindowCoveringServer.with(
|
|
|
174
171
|
this.#startTiltMovement(this.state.targetPositionTiltPercent100ths);
|
|
175
172
|
device.log.debug(`MatterbridgeWindowCoveringServer: goToTiltPercentage result target ${this.state.targetPositionTiltPercent100ths} current ${this.state.currentPositionTiltPercent100ths} 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})`);
|
|
176
173
|
}
|
|
174
|
+
async [Symbol.asyncDispose]() {
|
|
175
|
+
this.internal.liftMovementTimer?.stop();
|
|
176
|
+
this.internal.liftMovementTimer = undefined;
|
|
177
|
+
this.internal.tiltMovementTimer?.stop();
|
|
178
|
+
this.internal.tiltMovementTimer = undefined;
|
|
179
|
+
await super[Symbol.asyncDispose]?.();
|
|
180
|
+
}
|
|
177
181
|
}
|
|
178
182
|
(function (MatterbridgeWindowCoveringServer) {
|
|
179
183
|
class Internal extends WindowCoveringBaseServer.Internal {
|
|
180
184
|
liftMovementTimer;
|
|
185
|
+
liftMovementTarget = 0;
|
|
181
186
|
tiltMovementTimer;
|
|
187
|
+
tiltMovementTarget = 0;
|
|
182
188
|
}
|
|
183
189
|
MatterbridgeWindowCoveringServer.Internal = Internal;
|
|
184
190
|
class State extends WindowCoveringBaseServer.State {
|
package/dist/demoDevices.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { ClosureCoveringTag, ClosurePanelTag, ClosureTag, ClosureWindowTag, CommodityTariffChronologyTag, CommodityTariffCommodityTag, CommodityTariffFlowTag, CommonNumberTag, CommonPositionTag, ElectricalMeasurementTag, PowerSourceTag, RefrigeratorTag, } from '@matter/node';
|
|
3
|
+
import { ClosureCoveringTag, ClosurePanelTag, ClosureTag, ClosureWindowTag, CommodityTariffChronologyTag, CommodityTariffCommodityTag, CommodityTariffFlowTag, CommonNumberTag, CommonPositionTag, ElectricalMeasurementTag, PowerSourceTag, RefrigeratorTag, SwitchesTag, } from '@matter/node';
|
|
4
4
|
import { AirQuality } from '@matter/types/clusters/air-quality';
|
|
5
5
|
import { ClosureDimension } from '@matter/types/clusters/closure-dimension';
|
|
6
6
|
import { DoorLock } from '@matter/types/clusters/door-lock';
|
|
@@ -267,8 +267,33 @@ export async function createDemoDevices(matterbridge) {
|
|
|
267
267
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('PumpController'), bridgedNode, powerSource], { id: 'PumpController', number: EndpointNumber(6_05) });
|
|
268
268
|
ep.createDefaultPowerSourceWiredClusterServer();
|
|
269
269
|
await registerDevice(ep, 'Pump Controller', 'SWITCH-06-05');
|
|
270
|
-
ep = new MatterbridgeEndpoint([getSupportedDeviceType('
|
|
270
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Aggregator'), bridgedNode, powerSource], { id: 'GenericSwitch', number: EndpointNumber(6_06) });
|
|
271
271
|
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
272
|
+
await ep.addFixedLabel('composed', 'GenericSwitch');
|
|
273
|
+
ep.addChildDeviceType('Button1', getSupportedDeviceType('GenericSwitch'), {
|
|
274
|
+
number: EndpointNumber(6_06_1),
|
|
275
|
+
tagList: [getSemtag(SwitchesTag.On), getSemtag(CommonNumberTag.One)],
|
|
276
|
+
})
|
|
277
|
+
.createDefaultMomentarySwitchClusterServer()
|
|
278
|
+
.addRequiredClusters();
|
|
279
|
+
ep.addChildDeviceType('Button2', getSupportedDeviceType('GenericSwitch'), {
|
|
280
|
+
number: EndpointNumber(6_06_2),
|
|
281
|
+
tagList: [getSemtag(SwitchesTag.Off), getSemtag(CommonNumberTag.Two)],
|
|
282
|
+
})
|
|
283
|
+
.createDefaultMomentarySwitchClusterServer()
|
|
284
|
+
.addRequiredClusters();
|
|
285
|
+
ep.addChildDeviceType('Button3', getSupportedDeviceType('GenericSwitch'), {
|
|
286
|
+
number: EndpointNumber(6_06_3),
|
|
287
|
+
tagList: [getSemtag(SwitchesTag.Up), getSemtag(CommonNumberTag.Three)],
|
|
288
|
+
})
|
|
289
|
+
.createDefaultMomentarySwitchClusterServer()
|
|
290
|
+
.addRequiredClusters();
|
|
291
|
+
ep.addChildDeviceType('Button4', getSupportedDeviceType('GenericSwitch'), {
|
|
292
|
+
number: EndpointNumber(6_06_4),
|
|
293
|
+
tagList: [getSemtag(SwitchesTag.Down), getSemtag(CommonNumberTag.Four)],
|
|
294
|
+
})
|
|
295
|
+
.createDefaultMomentarySwitchClusterServer()
|
|
296
|
+
.addRequiredClusters();
|
|
272
297
|
await registerDevice(ep, 'Generic Switch', 'SWITCH-06-06');
|
|
273
298
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('ContactSensor'), bridgedNode, powerSource], { id: 'ContactSensor', number: EndpointNumber(7_01) });
|
|
274
299
|
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type MaybePromise, type Timer } from '@matter/general';
|
|
2
2
|
import { ClosureControlServer } from '@matter/node/behaviors/closure-control';
|
|
3
3
|
import { type EndpointNumber } from '@matter/types';
|
|
4
4
|
import { ClosureControl } from '@matter/types/clusters/closure-control';
|
|
@@ -18,24 +18,28 @@ declare const MatterbridgeClosureControlServerBase: import("@matter/node").Clust
|
|
|
18
18
|
ventilation: false;
|
|
19
19
|
}>, import("@matter/types").ClusterType.Concrete, new () => {}, "closureControl">;
|
|
20
20
|
export declare class MatterbridgeClosureControlServer extends MatterbridgeClosureControlServerBase {
|
|
21
|
+
#private;
|
|
21
22
|
readonly state: MatterbridgeClosureControlServer.State;
|
|
22
23
|
protected internal: MatterbridgeClosureControlServer.Internal;
|
|
23
24
|
initialize(): MaybePromise;
|
|
24
25
|
moveTo: (request: ClosureControl.MoveToRequest) => Promise<void>;
|
|
25
|
-
private completeMoveTo;
|
|
26
26
|
stop: () => Promise<void>;
|
|
27
27
|
calibrate: () => Promise<void>;
|
|
28
|
-
|
|
28
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
29
29
|
}
|
|
30
30
|
export declare namespace MatterbridgeClosureControlServer {
|
|
31
31
|
class Internal extends MatterbridgeClosureControlServerBase.Internal {
|
|
32
|
-
movementTimer?:
|
|
33
|
-
|
|
32
|
+
movementTimer?: Timer;
|
|
33
|
+
movementTargetState: ClosureControl.OverallTargetState;
|
|
34
|
+
movementPreviousState: ClosureControl.OverallCurrentState;
|
|
35
|
+
calibrateTimer?: Timer;
|
|
34
36
|
}
|
|
35
37
|
class State extends MatterbridgeClosureControlServerBase.State {
|
|
36
38
|
movementDuration: number;
|
|
37
39
|
calibrationDuration: number;
|
|
38
40
|
signaturePosition: number;
|
|
41
|
+
ventilationPosition: number;
|
|
42
|
+
pedestrianPosition: number;
|
|
39
43
|
}
|
|
40
44
|
}
|
|
41
45
|
export interface ClosureOptions {
|
|
@@ -51,6 +55,8 @@ export interface ClosureOptions {
|
|
|
51
55
|
movementDuration?: number;
|
|
52
56
|
calibrationDuration?: number;
|
|
53
57
|
signaturePosition?: number;
|
|
58
|
+
ventilationPosition?: number;
|
|
59
|
+
pedestrianPosition?: number;
|
|
54
60
|
motionLatching?: boolean;
|
|
55
61
|
speed?: boolean;
|
|
56
62
|
ventilation?: boolean;
|
|
@@ -64,10 +70,17 @@ export declare class Closure extends MatterbridgeEndpoint {
|
|
|
64
70
|
constructor(name: string, serial: string, options?: ClosureOptions);
|
|
65
71
|
getMainState(): ClosureControl.MainState | undefined;
|
|
66
72
|
getSignaturePosition(): number | undefined;
|
|
73
|
+
getVentilationPosition(): number | undefined;
|
|
74
|
+
getPedestrianPosition(): number | undefined;
|
|
67
75
|
setState(currentState: ClosureControl.OverallCurrentState, targetState: ClosureControl.OverallTargetState, mainState?: ClosureControl.MainState, countdownTime?: number, currentErrorList?: ClosureControl.ClosureError[]): Promise<void>;
|
|
68
76
|
setFullyClosed(): Promise<void>;
|
|
69
77
|
setFullOpened(): Promise<void>;
|
|
70
78
|
setPartiallyOpened(): Promise<void>;
|
|
79
|
+
setOpenedAtSignature(): Promise<void>;
|
|
80
|
+
setOpenedForVentilation(): Promise<void>;
|
|
81
|
+
setOpenedForPedestrian(): Promise<void>;
|
|
82
|
+
targetPositionToCurrentPosition(position: ClosureControl.TargetPosition): ClosureControl.CurrentPosition;
|
|
83
|
+
targetPositionToTargetPercent(position: ClosureControl.TargetPosition): number;
|
|
71
84
|
triggerOperationalError(errorState?: ClosureControl.ClosureError[]): Promise<void>;
|
|
72
85
|
triggerMovementCompleted(): Promise<void>;
|
|
73
86
|
triggerSecureStateChanged(secureValue: boolean): Promise<void>;
|
package/dist/devices/closure.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Millis, Time } from '@matter/general';
|
|
1
2
|
import { ClosureTag } from '@matter/node';
|
|
2
3
|
import { ClosureControlServer } from '@matter/node/behaviors/closure-control';
|
|
3
4
|
import { StatusResponse } from '@matter/types';
|
|
@@ -73,25 +74,24 @@ export class MatterbridgeClosureControlServer extends MatterbridgeClosureControl
|
|
|
73
74
|
(!this.features.motionLatching || nextTarget.latch === undefined || nextTarget.latch === currentState.latch) &&
|
|
74
75
|
(!this.features.speed || nextTarget.speed === currentState.speed);
|
|
75
76
|
this.state.mainState = isAtTarget ? ClosureControl.MainState.Stopped : ClosureControl.MainState.Moving;
|
|
76
|
-
|
|
77
|
+
this.internal.movementTimer?.stop();
|
|
78
|
+
this.internal.movementTimer = undefined;
|
|
77
79
|
if (isAtTarget) {
|
|
78
|
-
this.internal.movementTimer = undefined;
|
|
79
80
|
this.state.countdownTime = 0;
|
|
80
81
|
}
|
|
81
82
|
else if (currentState === null || this.state.movementDuration <= 0) {
|
|
82
|
-
this.internal.movementTimer = undefined;
|
|
83
83
|
}
|
|
84
84
|
else {
|
|
85
85
|
this.state.countdownTime = this.state.movementDuration / 1000;
|
|
86
|
-
|
|
87
|
-
this.internal.
|
|
88
|
-
|
|
89
|
-
void this.completeMoveTo(nextTarget, previousState);
|
|
90
|
-
}, this.state.movementDuration);
|
|
86
|
+
this.internal.movementTargetState = nextTarget;
|
|
87
|
+
this.internal.movementPreviousState = currentState;
|
|
88
|
+
this.internal.movementTimer = Time.getTimer('ClosureControl movement complete', Millis(this.state.movementDuration), this.callback(this.#completeMoveTo, { lock: true })).start();
|
|
91
89
|
}
|
|
92
90
|
};
|
|
93
|
-
completeMoveTo
|
|
94
|
-
|
|
91
|
+
#completeMoveTo() {
|
|
92
|
+
this.internal.movementTimer = undefined;
|
|
93
|
+
const targetState = this.internal.movementTargetState;
|
|
94
|
+
const previousState = this.internal.movementPreviousState;
|
|
95
95
|
let position = previousState.position;
|
|
96
96
|
if (targetState.position !== undefined && targetState.position !== null) {
|
|
97
97
|
const mappedPosition = targetToCurrentPosition[targetState.position];
|
|
@@ -100,17 +100,25 @@ export class MatterbridgeClosureControlServer extends MatterbridgeClosureControl
|
|
|
100
100
|
}
|
|
101
101
|
const latch = targetState.latch ?? previousState.latch;
|
|
102
102
|
const secureState = this.features.motionLatching ? latch === true : position === ClosureControl.CurrentPosition.FullyClosed;
|
|
103
|
-
|
|
103
|
+
this.state.countdownTime = 0;
|
|
104
|
+
this.state.mainState = ClosureControl.MainState.Stopped;
|
|
105
|
+
this.state.currentErrorList = [];
|
|
106
|
+
this.state.overallCurrentState = {
|
|
104
107
|
position,
|
|
105
108
|
...(this.features.motionLatching ? { latch } : null),
|
|
106
109
|
...(this.features.speed ? { speed: targetState.speed } : null),
|
|
107
110
|
secureState,
|
|
108
|
-
}
|
|
111
|
+
};
|
|
112
|
+
this.state.overallTargetState = {
|
|
113
|
+
position: targetState.position,
|
|
114
|
+
...(this.features.motionLatching ? { latch: targetState.latch } : null),
|
|
115
|
+
...(this.features.speed ? { speed: targetState.speed } : null),
|
|
116
|
+
};
|
|
109
117
|
if (secureState !== previousState.secureState) {
|
|
110
|
-
|
|
118
|
+
this.events.secureStateChanged.emit({ secureValue: secureState }, this.context);
|
|
111
119
|
}
|
|
112
|
-
|
|
113
|
-
}
|
|
120
|
+
this.events.movementCompleted.emit(undefined, this.context);
|
|
121
|
+
}
|
|
114
122
|
stop = async () => {
|
|
115
123
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
116
124
|
device.log.info(`Stop (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
@@ -121,9 +129,9 @@ export class MatterbridgeClosureControlServer extends MatterbridgeClosureControl
|
|
|
121
129
|
attributes: this.state,
|
|
122
130
|
endpoint: this.endpoint,
|
|
123
131
|
});
|
|
124
|
-
|
|
132
|
+
this.internal.movementTimer?.stop();
|
|
125
133
|
this.internal.movementTimer = undefined;
|
|
126
|
-
|
|
134
|
+
this.internal.calibrateTimer?.stop();
|
|
127
135
|
this.internal.calibrateTimer = undefined;
|
|
128
136
|
if ([ClosureControl.MainState.Moving, ClosureControl.MainState.WaitingForMotion, ClosureControl.MainState.Calibrating].includes(this.state.mainState)) {
|
|
129
137
|
this.state.mainState = ClosureControl.MainState.Stopped;
|
|
@@ -147,27 +155,33 @@ export class MatterbridgeClosureControlServer extends MatterbridgeClosureControl
|
|
|
147
155
|
throw new StatusResponse.InvalidInStateError('ClosureControl.calibrate is only allowed while Stopped or SetupRequired');
|
|
148
156
|
}
|
|
149
157
|
this.state.mainState = ClosureControl.MainState.Calibrating;
|
|
150
|
-
|
|
158
|
+
this.internal.calibrateTimer?.stop();
|
|
151
159
|
if (this.state.calibrationDuration <= 0) {
|
|
152
160
|
this.internal.calibrateTimer = undefined;
|
|
153
161
|
}
|
|
154
162
|
else {
|
|
155
163
|
this.state.countdownTime = this.state.calibrationDuration / 1000;
|
|
156
|
-
this.internal.calibrateTimer =
|
|
157
|
-
this.internal.calibrateTimer = undefined;
|
|
158
|
-
void this.completeCalibrate();
|
|
159
|
-
}, this.state.calibrationDuration);
|
|
164
|
+
this.internal.calibrateTimer = Time.getTimer('ClosureControl calibrate complete', Millis(this.state.calibrationDuration), this.callback(this.#completeCalibrate, { lock: true })).start();
|
|
160
165
|
}
|
|
161
166
|
};
|
|
162
|
-
completeCalibrate
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
+
#completeCalibrate() {
|
|
168
|
+
this.internal.calibrateTimer = undefined;
|
|
169
|
+
this.state.countdownTime = 0;
|
|
170
|
+
this.state.mainState = ClosureControl.MainState.Stopped;
|
|
171
|
+
}
|
|
172
|
+
async [Symbol.asyncDispose]() {
|
|
173
|
+
this.internal.movementTimer?.stop();
|
|
174
|
+
this.internal.movementTimer = undefined;
|
|
175
|
+
this.internal.calibrateTimer?.stop();
|
|
176
|
+
this.internal.calibrateTimer = undefined;
|
|
177
|
+
await super[Symbol.asyncDispose]?.();
|
|
178
|
+
}
|
|
167
179
|
}
|
|
168
180
|
(function (MatterbridgeClosureControlServer) {
|
|
169
181
|
class Internal extends MatterbridgeClosureControlServerBase.Internal {
|
|
170
182
|
movementTimer;
|
|
183
|
+
movementTargetState = {};
|
|
184
|
+
movementPreviousState = { position: ClosureControl.CurrentPosition.FullyClosed, secureState: true };
|
|
171
185
|
calibrateTimer;
|
|
172
186
|
}
|
|
173
187
|
MatterbridgeClosureControlServer.Internal = Internal;
|
|
@@ -175,12 +189,14 @@ export class MatterbridgeClosureControlServer extends MatterbridgeClosureControl
|
|
|
175
189
|
movementDuration = 0;
|
|
176
190
|
calibrationDuration = 0;
|
|
177
191
|
signaturePosition = 50_00;
|
|
192
|
+
ventilationPosition = 50_00;
|
|
193
|
+
pedestrianPosition = 50_00;
|
|
178
194
|
}
|
|
179
195
|
MatterbridgeClosureControlServer.State = State;
|
|
180
196
|
})(MatterbridgeClosureControlServer || (MatterbridgeClosureControlServer = {}));
|
|
181
197
|
export class Closure extends MatterbridgeEndpoint {
|
|
182
198
|
constructor(name, serial, options = {}) {
|
|
183
|
-
const { identifyTime = 0, identifyType = Identify.IdentifyType.None, powerSourceType = 'Wired', countdownTime = 0, mainState = ClosureControl.MainState.Stopped, currentErrorList = [], overallCurrentState, overallTargetState, latchControlModes, movementDuration = 0, calibrationDuration = 0, signaturePosition = 50_00, motionLatching = false, speed = false, ventilation = false, pedestrian = false, calibration = false, id, number, tagList = [getSemtag(ClosureTag.Covering)], } = options;
|
|
199
|
+
const { identifyTime = 0, identifyType = Identify.IdentifyType.None, powerSourceType = 'Wired', countdownTime = 0, mainState = ClosureControl.MainState.Stopped, currentErrorList = [], overallCurrentState, overallTargetState, latchControlModes, movementDuration = 0, calibrationDuration = 0, signaturePosition = 50_00, ventilationPosition = 50_00, pedestrianPosition = 50_00, motionLatching = false, speed = false, ventilation = false, pedestrian = false, calibration = false, id, number, tagList = [getSemtag(ClosureTag.Covering)], } = options;
|
|
184
200
|
super(powerSourceType === 'None' ? [closure] : [closure, powerSource], {
|
|
185
201
|
id: id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
|
|
186
202
|
number,
|
|
@@ -223,6 +239,8 @@ export class Closure extends MatterbridgeEndpoint {
|
|
|
223
239
|
movementDuration,
|
|
224
240
|
calibrationDuration,
|
|
225
241
|
signaturePosition,
|
|
242
|
+
ventilationPosition,
|
|
243
|
+
pedestrianPosition,
|
|
226
244
|
};
|
|
227
245
|
this.behaviors.require(MatterbridgeClosureControlServer.with(ClosureControl.Feature.Positioning, ...(motionLatching ? [ClosureControl.Feature.MotionLatching] : []), ...(speed ? [ClosureControl.Feature.Speed] : []), ...(calibration ? [ClosureControl.Feature.Calibration] : []), ...(ventilation ? [ClosureControl.Feature.Ventilation] : []), ...(pedestrian ? [ClosureControl.Feature.Pedestrian] : [])), closureControlOptions);
|
|
228
246
|
}
|
|
@@ -232,23 +250,31 @@ export class Closure extends MatterbridgeEndpoint {
|
|
|
232
250
|
getSignaturePosition() {
|
|
233
251
|
return this.getAttribute(MatterbridgeClosureControlServer, 'signaturePosition');
|
|
234
252
|
}
|
|
253
|
+
getVentilationPosition() {
|
|
254
|
+
return this.getAttribute(MatterbridgeClosureControlServer, 'ventilationPosition');
|
|
255
|
+
}
|
|
256
|
+
getPedestrianPosition() {
|
|
257
|
+
return this.getAttribute(MatterbridgeClosureControlServer, 'pedestrianPosition');
|
|
258
|
+
}
|
|
235
259
|
async setState(currentState, targetState, mainState = ClosureControl.MainState.Stopped, countdownTime = 0, currentErrorList = []) {
|
|
236
|
-
const
|
|
237
|
-
const
|
|
238
|
-
|
|
260
|
+
const features = this.featuresOf(MatterbridgeClosureControlServer.id);
|
|
261
|
+
const supportsCurrentPosition = (currentState.position !== ClosureControl.CurrentPosition.OpenedForVentilation || features.ventilation) &&
|
|
262
|
+
(currentState.position !== ClosureControl.CurrentPosition.OpenedForPedestrian || features.pedestrian);
|
|
263
|
+
const supportsTargetPosition = (targetState.position !== ClosureControl.TargetPosition.MoveToVentilationPosition || features.ventilation) &&
|
|
264
|
+
(targetState.position !== ClosureControl.TargetPosition.MoveToPedestrianPosition || features.pedestrian);
|
|
239
265
|
await this.setAttribute(ClosureControl, 'countdownTime', countdownTime);
|
|
240
266
|
await this.setAttribute(ClosureControl, 'mainState', mainState);
|
|
241
267
|
await this.setAttribute(ClosureControl, 'currentErrorList', currentErrorList);
|
|
242
268
|
await this.setAttribute(ClosureControl, 'overallCurrentState', {
|
|
243
|
-
position: currentState.position,
|
|
244
|
-
...(
|
|
245
|
-
...(
|
|
269
|
+
...(supportsCurrentPosition ? { position: currentState.position } : null),
|
|
270
|
+
...(features.motionLatching ? { latch: currentState.latch } : null),
|
|
271
|
+
...(features.speed ? { speed: currentState.speed } : null),
|
|
246
272
|
secureState: currentState.secureState,
|
|
247
273
|
});
|
|
248
274
|
await this.setAttribute(ClosureControl, 'overallTargetState', {
|
|
249
|
-
position: targetState.position,
|
|
250
|
-
...(
|
|
251
|
-
...(
|
|
275
|
+
...(supportsTargetPosition ? { position: targetState.position } : null),
|
|
276
|
+
...(features.motionLatching ? { latch: targetState.latch } : null),
|
|
277
|
+
...(features.speed ? { speed: targetState.speed } : null),
|
|
252
278
|
});
|
|
253
279
|
}
|
|
254
280
|
async setFullyClosed() {
|
|
@@ -287,6 +313,64 @@ export class Closure extends MatterbridgeEndpoint {
|
|
|
287
313
|
speed: ThreeLevelAuto.Auto,
|
|
288
314
|
});
|
|
289
315
|
}
|
|
316
|
+
async setOpenedAtSignature() {
|
|
317
|
+
await this.setState({
|
|
318
|
+
position: ClosureControl.CurrentPosition.OpenedAtSignature,
|
|
319
|
+
latch: false,
|
|
320
|
+
speed: ThreeLevelAuto.Auto,
|
|
321
|
+
secureState: false,
|
|
322
|
+
}, {
|
|
323
|
+
position: ClosureControl.TargetPosition.MoveToSignaturePosition,
|
|
324
|
+
latch: false,
|
|
325
|
+
speed: ThreeLevelAuto.Auto,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
async setOpenedForVentilation() {
|
|
329
|
+
await this.setState({
|
|
330
|
+
position: ClosureControl.CurrentPosition.OpenedForVentilation,
|
|
331
|
+
latch: false,
|
|
332
|
+
speed: ThreeLevelAuto.Auto,
|
|
333
|
+
secureState: false,
|
|
334
|
+
}, {
|
|
335
|
+
position: ClosureControl.TargetPosition.MoveToVentilationPosition,
|
|
336
|
+
latch: false,
|
|
337
|
+
speed: ThreeLevelAuto.Auto,
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
async setOpenedForPedestrian() {
|
|
341
|
+
await this.setState({
|
|
342
|
+
position: ClosureControl.CurrentPosition.OpenedForPedestrian,
|
|
343
|
+
latch: false,
|
|
344
|
+
speed: ThreeLevelAuto.Auto,
|
|
345
|
+
secureState: false,
|
|
346
|
+
}, {
|
|
347
|
+
position: ClosureControl.TargetPosition.MoveToPedestrianPosition,
|
|
348
|
+
latch: false,
|
|
349
|
+
speed: ThreeLevelAuto.Auto,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
targetPositionToCurrentPosition(position) {
|
|
353
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyClosed)
|
|
354
|
+
return ClosureControl.CurrentPosition.FullyClosed;
|
|
355
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyOpen)
|
|
356
|
+
return ClosureControl.CurrentPosition.FullyOpened;
|
|
357
|
+
if (position === ClosureControl.TargetPosition.MoveToPedestrianPosition)
|
|
358
|
+
return ClosureControl.CurrentPosition.OpenedForPedestrian;
|
|
359
|
+
if (position === ClosureControl.TargetPosition.MoveToVentilationPosition)
|
|
360
|
+
return ClosureControl.CurrentPosition.OpenedForVentilation;
|
|
361
|
+
return ClosureControl.CurrentPosition.OpenedAtSignature;
|
|
362
|
+
}
|
|
363
|
+
targetPositionToTargetPercent(position) {
|
|
364
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyOpen)
|
|
365
|
+
return 0;
|
|
366
|
+
if (position === ClosureControl.TargetPosition.MoveToFullyClosed)
|
|
367
|
+
return 100_00;
|
|
368
|
+
if (position === ClosureControl.TargetPosition.MoveToPedestrianPosition)
|
|
369
|
+
return this.getPedestrianPosition() ?? 50_00;
|
|
370
|
+
if (position === ClosureControl.TargetPosition.MoveToVentilationPosition)
|
|
371
|
+
return this.getVentilationPosition() ?? 50_00;
|
|
372
|
+
return this.getSignaturePosition() ?? 50_00;
|
|
373
|
+
}
|
|
290
374
|
async triggerOperationalError(errorState = []) {
|
|
291
375
|
await this.setAttribute(ClosureControl, 'mainState', ClosureControl.MainState.Error);
|
|
292
376
|
await this.setAttribute(ClosureControl, 'currentErrorList', errorState);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type MaybePromise, type Timer } from '@matter/general';
|
|
2
2
|
import { ClosureDimensionServer } from '@matter/node/behaviors/closure-dimension';
|
|
3
3
|
import { ClosureDimension } from '@matter/types/clusters/closure-dimension';
|
|
4
4
|
import type { EndpointNumber } from '@matter/types/datatype';
|
|
@@ -15,17 +15,19 @@ declare const MatterbridgeClosureDimensionServerBase: import("@matter/node").Clu
|
|
|
15
15
|
unit: false;
|
|
16
16
|
}>, import("@matter/types").ClusterType.Concrete, new () => {}, "closureDimension">;
|
|
17
17
|
export declare class MatterbridgeClosureDimensionServer extends MatterbridgeClosureDimensionServerBase {
|
|
18
|
+
#private;
|
|
18
19
|
readonly state: MatterbridgeClosureDimensionServer.State;
|
|
19
20
|
protected internal: MatterbridgeClosureDimensionServer.Internal;
|
|
20
21
|
initialize(): MaybePromise;
|
|
21
22
|
setTarget: (request: ClosureDimension.SetTargetRequest) => Promise<void>;
|
|
22
23
|
step: (request: ClosureDimension.StepRequest) => Promise<void>;
|
|
23
|
-
|
|
24
|
-
private completeMovement;
|
|
24
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
25
25
|
}
|
|
26
26
|
export declare namespace MatterbridgeClosureDimensionServer {
|
|
27
27
|
class Internal extends MatterbridgeClosureDimensionServerBase.Internal {
|
|
28
|
-
movementTimer?:
|
|
28
|
+
movementTimer?: Timer;
|
|
29
|
+
movementTargetState: ClosureDimension.DimensionState;
|
|
30
|
+
movementPreviousState: ClosureDimension.DimensionState;
|
|
29
31
|
}
|
|
30
32
|
class State extends MatterbridgeClosureDimensionServerBase.State {
|
|
31
33
|
movementDuration: number;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Millis, Time } from '@matter/general';
|
|
1
2
|
import { ClosureControlServer } from '@matter/node/behaviors/closure-control';
|
|
2
3
|
import { ClosureDimensionServer } from '@matter/node/behaviors/closure-dimension';
|
|
3
4
|
import { StatusResponse } from '@matter/types';
|
|
@@ -71,7 +72,7 @@ export class MatterbridgeClosureDimensionServer extends MatterbridgeClosureDimen
|
|
|
71
72
|
if (matchesCurrentState)
|
|
72
73
|
return;
|
|
73
74
|
this.state.targetState = nextTarget;
|
|
74
|
-
this
|
|
75
|
+
this.#scheduleMovement(nextTarget, currentState);
|
|
75
76
|
};
|
|
76
77
|
step = async (request) => {
|
|
77
78
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -121,35 +122,41 @@ export class MatterbridgeClosureDimensionServer extends MatterbridgeClosureDimen
|
|
|
121
122
|
...(this.features.speed && request.speed !== undefined ? { speed: request.speed } : null),
|
|
122
123
|
};
|
|
123
124
|
this.state.targetState = nextTarget;
|
|
124
|
-
this
|
|
125
|
+
this.#scheduleMovement(nextTarget, currentState);
|
|
125
126
|
};
|
|
126
|
-
scheduleMovement(targetState, currentState) {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
127
|
+
#scheduleMovement(targetState, currentState) {
|
|
128
|
+
this.internal.movementTimer?.stop();
|
|
129
|
+
this.internal.movementTimer = undefined;
|
|
130
|
+
if (currentState === null || this.state.movementDuration <= 0)
|
|
130
131
|
return;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
this.internal.movementTimer =
|
|
134
|
-
this.internal.movementTimer = undefined;
|
|
135
|
-
void this.completeMovement(targetState, previousState);
|
|
136
|
-
}, this.state.movementDuration);
|
|
132
|
+
this.internal.movementTargetState = targetState;
|
|
133
|
+
this.internal.movementPreviousState = currentState;
|
|
134
|
+
this.internal.movementTimer = Time.getTimer('ClosureDimension movement complete', Millis(this.state.movementDuration), this.callback(this.#completeMovement, { lock: true })).start();
|
|
137
135
|
}
|
|
138
|
-
completeMovement
|
|
139
|
-
|
|
136
|
+
#completeMovement() {
|
|
137
|
+
this.internal.movementTimer = undefined;
|
|
138
|
+
const targetState = this.internal.movementTargetState;
|
|
139
|
+
const previousState = this.internal.movementPreviousState;
|
|
140
140
|
const position = targetState.position ?? previousState.position;
|
|
141
141
|
const latch = targetState.latch ?? previousState.latch;
|
|
142
142
|
const speed = targetState.speed ?? previousState.speed;
|
|
143
|
-
|
|
143
|
+
this.state.currentState = {
|
|
144
144
|
position,
|
|
145
145
|
...(this.features.motionLatching ? { latch } : null),
|
|
146
146
|
...(this.features.speed ? { speed } : null),
|
|
147
|
-
}
|
|
148
|
-
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async [Symbol.asyncDispose]() {
|
|
150
|
+
this.internal.movementTimer?.stop();
|
|
151
|
+
this.internal.movementTimer = undefined;
|
|
152
|
+
await super[Symbol.asyncDispose]?.();
|
|
153
|
+
}
|
|
149
154
|
}
|
|
150
155
|
(function (MatterbridgeClosureDimensionServer) {
|
|
151
156
|
class Internal extends MatterbridgeClosureDimensionServerBase.Internal {
|
|
152
157
|
movementTimer;
|
|
158
|
+
movementTargetState = {};
|
|
159
|
+
movementPreviousState = {};
|
|
153
160
|
}
|
|
154
161
|
MatterbridgeClosureDimensionServer.Internal = Internal;
|
|
155
162
|
class State extends MatterbridgeClosureDimensionServerBase.State {
|
|
@@ -62,6 +62,21 @@ export interface ElectricalEnergyTariffOptions {
|
|
|
62
62
|
currentPrice?: CommodityPrice.CommodityPriceStruct | null;
|
|
63
63
|
localGenerationAvailable?: boolean | null;
|
|
64
64
|
currentConditions?: ElectricalGridConditions.ElectricalGridConditionsStruct | null;
|
|
65
|
+
startDate?: number | null;
|
|
66
|
+
dayEntries?: CommodityTariff.DayEntry[] | null;
|
|
67
|
+
dayPatterns?: CommodityTariff.DayPattern[] | null;
|
|
68
|
+
calendarPeriods?: CommodityTariff.CalendarPeriod[] | null;
|
|
69
|
+
individualDays?: CommodityTariff.Day[] | null;
|
|
70
|
+
currentDay?: CommodityTariff.Day | null;
|
|
71
|
+
nextDay?: CommodityTariff.Day | null;
|
|
72
|
+
currentDayEntry?: CommodityTariff.DayEntry | null;
|
|
73
|
+
currentDayEntryDate?: number | null;
|
|
74
|
+
nextDayEntry?: CommodityTariff.DayEntry | null;
|
|
75
|
+
nextDayEntryDate?: number | null;
|
|
76
|
+
tariffComponents?: CommodityTariff.TariffComponent[] | null;
|
|
77
|
+
tariffPeriods?: CommodityTariff.TariffPeriod[] | null;
|
|
78
|
+
currentTariffComponents?: CommodityTariff.TariffComponent[] | null;
|
|
79
|
+
nextTariffComponents?: CommodityTariff.TariffComponent[] | null;
|
|
65
80
|
tagList?: Semtag[];
|
|
66
81
|
}
|
|
67
82
|
export declare class ElectricalUtilityMeter extends MatterbridgeEndpoint {
|
|
@@ -106,7 +106,7 @@ export class ElectricalUtilityMeter extends MatterbridgeEndpoint {
|
|
|
106
106
|
return tariff;
|
|
107
107
|
}
|
|
108
108
|
configureElectricalEnergyTariffClusters(endpoint, options) {
|
|
109
|
-
const { tariffLabel = null, providerName = null, tariffUnit = TariffUnit.KWh, currency = null, currentPrice = null, localGenerationAvailable = null, currentConditions = null, } = options;
|
|
109
|
+
const { tariffLabel = null, providerName = null, tariffUnit = TariffUnit.KWh, currency = null, currentPrice = null, localGenerationAvailable = null, currentConditions = null, startDate = null, dayEntries = null, dayPatterns = null, calendarPeriods = null, individualDays = null, currentDay = null, nextDay = null, currentDayEntry = null, currentDayEntryDate = null, nextDayEntry = null, nextDayEntryDate = null, tariffComponents = null, tariffPeriods = null, currentTariffComponents = null, nextTariffComponents = null, } = options;
|
|
110
110
|
endpoint.behaviors.require(MatterbridgeCommodityPriceServer, {
|
|
111
111
|
tariffUnit,
|
|
112
112
|
currency,
|
|
@@ -125,21 +125,21 @@ export class ElectricalUtilityMeter extends MatterbridgeEndpoint {
|
|
|
125
125
|
endpoint.behaviors.require(MatterbridgeCommodityTariffServer, {
|
|
126
126
|
tariffInfo,
|
|
127
127
|
tariffUnit: tariffInfo === null ? null : tariffUnit,
|
|
128
|
-
startDate: null,
|
|
129
|
-
dayEntries: null,
|
|
130
|
-
dayPatterns: null,
|
|
131
|
-
calendarPeriods: null,
|
|
132
|
-
individualDays: null,
|
|
133
|
-
tariffComponents: null,
|
|
134
|
-
tariffPeriods: null,
|
|
135
|
-
currentDay: null,
|
|
136
|
-
nextDay: null,
|
|
137
|
-
currentDayEntry: null,
|
|
138
|
-
currentDayEntryDate: null,
|
|
139
|
-
nextDayEntry: null,
|
|
140
|
-
nextDayEntryDate: null,
|
|
141
|
-
currentTariffComponents: null,
|
|
142
|
-
nextTariffComponents: null,
|
|
128
|
+
startDate: tariffInfo === null ? null : startDate,
|
|
129
|
+
dayEntries: tariffInfo === null ? null : dayEntries,
|
|
130
|
+
dayPatterns: tariffInfo === null ? null : dayPatterns,
|
|
131
|
+
calendarPeriods: tariffInfo === null ? null : calendarPeriods,
|
|
132
|
+
individualDays: tariffInfo === null ? null : individualDays,
|
|
133
|
+
tariffComponents: tariffInfo === null ? null : tariffComponents,
|
|
134
|
+
tariffPeriods: tariffInfo === null ? null : tariffPeriods,
|
|
135
|
+
currentDay: tariffInfo === null ? null : currentDay,
|
|
136
|
+
nextDay: tariffInfo === null ? null : nextDay,
|
|
137
|
+
currentDayEntry: tariffInfo === null ? null : currentDayEntry,
|
|
138
|
+
currentDayEntryDate: tariffInfo === null ? null : currentDayEntryDate,
|
|
139
|
+
nextDayEntry: tariffInfo === null ? null : nextDayEntry,
|
|
140
|
+
nextDayEntryDate: tariffInfo === null ? null : nextDayEntryDate,
|
|
141
|
+
currentTariffComponents: tariffInfo === null ? null : currentTariffComponents,
|
|
142
|
+
nextTariffComponents: tariffInfo === null ? null : nextTariffComponents,
|
|
143
143
|
});
|
|
144
144
|
endpoint.behaviors.require(ElectricalGridConditionsServer, { localGenerationAvailable, currentConditions });
|
|
145
145
|
}
|
|
@@ -208,7 +208,7 @@ export function featuresFor(endpoint, cluster) {
|
|
|
208
208
|
const supportedBehavior = endpoint.behaviors.supported[lowercaseFirstLetter(behaviorId)];
|
|
209
209
|
if (!supportedBehavior || !ClusterBehavior.isType(supportedBehavior))
|
|
210
210
|
return {};
|
|
211
|
-
return supportedBehavior.features
|
|
211
|
+
return supportedBehavior.features;
|
|
212
212
|
}
|
|
213
213
|
export async function internalFor(endpoint, cluster) {
|
|
214
214
|
const behaviorId = getBehavior(endpoint, cluster)?.id;
|
|
@@ -9,4 +9,5 @@ export declare function snakeCase(name: string): string;
|
|
|
9
9
|
export declare function pascalCase(name: string): string;
|
|
10
10
|
export declare function camelCase(name: string): string;
|
|
11
11
|
export declare function getServerBehaviorFromClusterId(clusterId: ClusterId, features?: Record<string, boolean> | string[]): Promise<Behavior.Type | undefined>;
|
|
12
|
+
export declare function getClientBehaviorFromClusterId(clusterId: ClusterId): Promise<Behavior.Type | undefined>;
|
|
12
13
|
export declare function createClusterServer(endpoint: MatterbridgeEndpoint, clusterId: ClusterId, options?: CreateClusterServerOptions): Promise<MatterbridgeEndpoint>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ClusterBehavior } from '@matter/node';
|
|
1
|
+
import { ClusterBehavior, isClientBehavior } from '@matter/node';
|
|
2
2
|
import { getClusterNameById } from '@matter/types/cluster';
|
|
3
3
|
import { logModuleLoaded } from '@matterbridge/utils/loader';
|
|
4
4
|
import { db, hk } from 'node-ansi-logger';
|
|
@@ -44,7 +44,7 @@ export async function getServerBehaviorFromClusterId(clusterId, features) {
|
|
|
44
44
|
return undefined;
|
|
45
45
|
}
|
|
46
46
|
const base = mod[`${name}Server`];
|
|
47
|
-
if (!base || !ClusterBehavior.isType(base))
|
|
47
|
+
if (!base || !ClusterBehavior.isType(base) || isClientBehavior(base))
|
|
48
48
|
return undefined;
|
|
49
49
|
const featureNames = (Array.isArray(features)
|
|
50
50
|
? features
|
|
@@ -53,6 +53,22 @@ export async function getServerBehaviorFromClusterId(clusterId, features) {
|
|
|
53
53
|
.map(([key]) => key)).map((key) => pascalCase(key));
|
|
54
54
|
return featureNames.length > 0 ? base.with(...featureNames) : base;
|
|
55
55
|
}
|
|
56
|
+
export async function getClientBehaviorFromClusterId(clusterId) {
|
|
57
|
+
const name = getClusterNameById(clusterId);
|
|
58
|
+
if (name.includes('Unknown cluster'))
|
|
59
|
+
return undefined;
|
|
60
|
+
let mod;
|
|
61
|
+
try {
|
|
62
|
+
mod = (await import(`@matter/node/behaviors/${snakeCase(name)}`));
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
const base = mod[`${name}Client`];
|
|
68
|
+
if (!base || !ClusterBehavior.isType(base) || !isClientBehavior(base))
|
|
69
|
+
return undefined;
|
|
70
|
+
return base;
|
|
71
|
+
}
|
|
56
72
|
export async function createClusterServer(endpoint, clusterId, options) {
|
|
57
73
|
const type = await getServerBehaviorFromClusterId(clusterId, options?.features);
|
|
58
74
|
if (!type) {
|
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-20260902-361500d",
|
|
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-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",
|
|
139
139
|
"escape-html": "1.0.3",
|
|
140
140
|
"express": "5.2.1",
|
|
141
141
|
"express-rate-limit": "8.7.0",
|