@matterbridge/core 3.10.5-dev-20260812-3e239dd → 3.10.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ClosureControlServer } from '@matter/node/behaviors/closure-control';
|
|
2
2
|
import { ClosureControl } from '@matter/types/clusters/closure-control';
|
|
3
|
+
import { Identify } from '@matter/types/clusters/identify';
|
|
3
4
|
import type { Semtag } from '@matter/types/globals';
|
|
4
5
|
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
5
6
|
import { type ClosureDimensionType, type ClosurePanelOptions } from './closurePanel.js';
|
|
@@ -19,6 +20,9 @@ export declare class MatterbridgeClosureControlServer extends MatterbridgeClosur
|
|
|
19
20
|
stop: () => Promise<void>;
|
|
20
21
|
}
|
|
21
22
|
export interface ClosureOptions {
|
|
23
|
+
identifyTime?: number;
|
|
24
|
+
identifyType?: Identify.IdentifyType;
|
|
25
|
+
powerSourceType?: 'Rechargeable' | 'Replaceable' | 'Battery' | 'Wired' | 'None';
|
|
22
26
|
countdownTime?: number;
|
|
23
27
|
mainState?: ClosureControl.MainState;
|
|
24
28
|
currentErrorList?: ClosureControl.ClosureError[];
|
|
@@ -30,6 +34,13 @@ export interface ClosureOptions {
|
|
|
30
34
|
export declare class Closure extends MatterbridgeEndpoint {
|
|
31
35
|
constructor(name: string, serial: string, options?: ClosureOptions);
|
|
32
36
|
getMainState(): ClosureControl.MainState | undefined;
|
|
33
|
-
|
|
37
|
+
setState(currentState: ClosureControl.OverallCurrentState, targetState: ClosureControl.OverallTargetState, mainState?: ClosureControl.MainState, countdownTime?: number, currentErrorList?: ClosureControl.ClosureError[]): Promise<void>;
|
|
38
|
+
setFullyClosed(): Promise<void>;
|
|
39
|
+
setFullOpened(): Promise<void>;
|
|
40
|
+
setPartiallyOpened(): Promise<void>;
|
|
41
|
+
triggerOperationalError(errorState?: ClosureControl.ClosureError[]): Promise<void>;
|
|
42
|
+
triggerMovementCompleted(): Promise<void>;
|
|
43
|
+
triggerSecureStateChanged(secureValue: boolean): Promise<void>;
|
|
44
|
+
addPanel(name: string, tagList: Semtag[], dimensionType: ClosureDimensionType, options?: ClosurePanelOptions): MatterbridgeEndpoint;
|
|
34
45
|
}
|
|
35
46
|
export {};
|
package/dist/devices/closure.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
+
import { ClosureTag } from '@matter/node';
|
|
1
2
|
import { ClosureControlServer } from '@matter/node/behaviors/closure-control';
|
|
3
|
+
import { StatusResponse } from '@matter/types';
|
|
2
4
|
import { ClosureControl } from '@matter/types/clusters/closure-control';
|
|
5
|
+
import { Identify } from '@matter/types/clusters/identify';
|
|
3
6
|
import { ThreeLevelAuto } from '@matter/types/globals';
|
|
4
7
|
import { MatterbridgeServer } from '../behaviors/matterbridgeServer.js';
|
|
5
|
-
import { closure, closurePanel } from '../matterbridgeDeviceTypes.js';
|
|
8
|
+
import { closure, closurePanel, powerSource } from '../matterbridgeDeviceTypes.js';
|
|
6
9
|
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
10
|
+
import { getSemtag } from '../matterbridgeEndpointHelpers.js';
|
|
7
11
|
import { createClosureDimensionClusterServer } from './closurePanel.js';
|
|
8
12
|
export class MatterbridgeClosureControlServer extends ClosureControlServer.with(ClosureControl.Feature.Positioning, ClosureControl.Feature.MotionLatching, ClosureControl.Feature.Speed) {
|
|
9
13
|
moveTo = async (request) => {
|
|
@@ -16,6 +20,16 @@ export class MatterbridgeClosureControlServer extends ClosureControlServer.with(
|
|
|
16
20
|
attributes: this.state,
|
|
17
21
|
endpoint: this.endpoint,
|
|
18
22
|
});
|
|
23
|
+
if (request.position === undefined && request.latch === undefined && request.speed === undefined) {
|
|
24
|
+
throw new StatusResponse.InvalidCommandError('ClosureControl.moveTo requires at least one of position, latch, or speed to be present');
|
|
25
|
+
}
|
|
26
|
+
if (![ClosureControl.MainState.Moving, ClosureControl.MainState.WaitingForMotion, ClosureControl.MainState.Stopped].includes(this.state.mainState)) {
|
|
27
|
+
throw new StatusResponse.InvalidInStateError('ClosureControl.moveTo is only allowed while Moving, WaitingForMotion, or Stopped');
|
|
28
|
+
}
|
|
29
|
+
let currentState = this.state.overallCurrentState;
|
|
30
|
+
if (currentState?.latch === true && request.position !== undefined && request.latch !== false) {
|
|
31
|
+
throw new StatusResponse.InvalidInStateError('ClosureControl.moveTo position changes require latch false while the closure is latched');
|
|
32
|
+
}
|
|
19
33
|
const previousTarget = this.state.overallTargetState ?? {};
|
|
20
34
|
const nextTarget = {
|
|
21
35
|
...previousTarget,
|
|
@@ -24,7 +38,10 @@ export class MatterbridgeClosureControlServer extends ClosureControlServer.with(
|
|
|
24
38
|
speed: request?.speed ?? ThreeLevelAuto.Auto,
|
|
25
39
|
};
|
|
26
40
|
this.state.overallTargetState = nextTarget;
|
|
27
|
-
|
|
41
|
+
if (currentState !== null) {
|
|
42
|
+
currentState = { ...currentState, speed: nextTarget.speed };
|
|
43
|
+
this.state.overallCurrentState = currentState;
|
|
44
|
+
}
|
|
28
45
|
const isAtTarget = currentState !== null &&
|
|
29
46
|
(nextTarget.position === undefined || nextTarget.position === currentState.position) &&
|
|
30
47
|
(nextTarget.latch === undefined || nextTarget.latch === currentState.latch) &&
|
|
@@ -41,35 +58,111 @@ export class MatterbridgeClosureControlServer extends ClosureControlServer.with(
|
|
|
41
58
|
attributes: this.state,
|
|
42
59
|
endpoint: this.endpoint,
|
|
43
60
|
});
|
|
44
|
-
|
|
61
|
+
if ([ClosureControl.MainState.Moving, ClosureControl.MainState.WaitingForMotion, ClosureControl.MainState.Calibrating].includes(this.state.mainState)) {
|
|
62
|
+
this.state.mainState = ClosureControl.MainState.Stopped;
|
|
63
|
+
}
|
|
45
64
|
};
|
|
46
65
|
}
|
|
47
66
|
export class Closure extends MatterbridgeEndpoint {
|
|
48
67
|
constructor(name, serial, options = {}) {
|
|
49
|
-
|
|
50
|
-
|
|
68
|
+
const { identifyTime = 0, identifyType = Identify.IdentifyType.None, powerSourceType = 'Wired', countdownTime = 0, mainState = ClosureControl.MainState.Stopped, currentErrorList = [], overallCurrentState = {
|
|
69
|
+
position: ClosureControl.CurrentPosition.FullyClosed,
|
|
70
|
+
latch: true,
|
|
71
|
+
speed: ThreeLevelAuto.Auto,
|
|
72
|
+
secureState: true,
|
|
73
|
+
}, overallTargetState = {
|
|
74
|
+
position: ClosureControl.TargetPosition.MoveToFullyClosed,
|
|
75
|
+
latch: true,
|
|
76
|
+
speed: ThreeLevelAuto.Auto,
|
|
77
|
+
}, latchControlModes = { remoteLatching: true, remoteUnlatching: true }, tagList = [getSemtag(ClosureTag.Covering)], } = options;
|
|
78
|
+
super(powerSourceType === 'None' ? [closure] : [closure, powerSource], {
|
|
79
|
+
id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
|
|
80
|
+
tagList,
|
|
81
|
+
});
|
|
82
|
+
this.createDefaultIdentifyClusterServer(identifyTime, identifyType);
|
|
51
83
|
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Closure');
|
|
84
|
+
switch (powerSourceType) {
|
|
85
|
+
case 'Rechargeable':
|
|
86
|
+
this.createDefaultPowerSourceRechargeableBatteryClusterServer();
|
|
87
|
+
break;
|
|
88
|
+
case 'Replaceable':
|
|
89
|
+
this.createDefaultPowerSourceReplaceableBatteryClusterServer();
|
|
90
|
+
break;
|
|
91
|
+
case 'Battery':
|
|
92
|
+
this.createDefaultPowerSourceBatteryClusterServer();
|
|
93
|
+
break;
|
|
94
|
+
case 'Wired':
|
|
95
|
+
this.createDefaultPowerSourceWiredClusterServer();
|
|
96
|
+
break;
|
|
97
|
+
case 'None':
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
52
100
|
this.behaviors.require(MatterbridgeClosureControlServer, {
|
|
53
|
-
countdownTime
|
|
54
|
-
mainState
|
|
55
|
-
currentErrorList
|
|
56
|
-
overallCurrentState
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
speed: ThreeLevelAuto.Auto,
|
|
60
|
-
secureState: true,
|
|
61
|
-
},
|
|
62
|
-
overallTargetState: options.overallTargetState ?? {
|
|
63
|
-
position: ClosureControl.TargetPosition.MoveToFullyClosed,
|
|
64
|
-
latch: true,
|
|
65
|
-
speed: ThreeLevelAuto.Auto,
|
|
66
|
-
},
|
|
67
|
-
latchControlModes: options.latchControlModes ?? { remoteLatching: true, remoteUnlatching: true },
|
|
101
|
+
countdownTime,
|
|
102
|
+
mainState,
|
|
103
|
+
currentErrorList,
|
|
104
|
+
overallCurrentState,
|
|
105
|
+
overallTargetState,
|
|
106
|
+
latchControlModes,
|
|
68
107
|
});
|
|
69
108
|
}
|
|
70
109
|
getMainState() {
|
|
71
110
|
return this.getAttribute(ClosureControlServer, 'mainState');
|
|
72
111
|
}
|
|
112
|
+
async setState(currentState, targetState, mainState = ClosureControl.MainState.Stopped, countdownTime = 0, currentErrorList = []) {
|
|
113
|
+
await this.setAttribute(ClosureControl, 'countdownTime', countdownTime);
|
|
114
|
+
await this.setAttribute(ClosureControl, 'mainState', mainState);
|
|
115
|
+
await this.setAttribute(ClosureControl, 'currentErrorList', currentErrorList);
|
|
116
|
+
await this.setAttribute(ClosureControl, 'overallCurrentState', currentState);
|
|
117
|
+
await this.setAttribute(ClosureControl, 'overallTargetState', targetState);
|
|
118
|
+
}
|
|
119
|
+
async setFullyClosed() {
|
|
120
|
+
await this.setState({
|
|
121
|
+
position: ClosureControl.CurrentPosition.FullyClosed,
|
|
122
|
+
latch: true,
|
|
123
|
+
speed: ThreeLevelAuto.Auto,
|
|
124
|
+
secureState: true,
|
|
125
|
+
}, {
|
|
126
|
+
position: ClosureControl.TargetPosition.MoveToFullyClosed,
|
|
127
|
+
latch: true,
|
|
128
|
+
speed: ThreeLevelAuto.Auto,
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
async setFullOpened() {
|
|
132
|
+
await this.setState({
|
|
133
|
+
position: ClosureControl.CurrentPosition.FullyOpened,
|
|
134
|
+
latch: false,
|
|
135
|
+
speed: ThreeLevelAuto.Auto,
|
|
136
|
+
secureState: false,
|
|
137
|
+
}, {
|
|
138
|
+
position: ClosureControl.TargetPosition.MoveToFullyOpen,
|
|
139
|
+
latch: false,
|
|
140
|
+
speed: ThreeLevelAuto.Auto,
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
async setPartiallyOpened() {
|
|
144
|
+
await this.setState({
|
|
145
|
+
position: ClosureControl.CurrentPosition.PartiallyOpened,
|
|
146
|
+
latch: false,
|
|
147
|
+
speed: ThreeLevelAuto.Auto,
|
|
148
|
+
secureState: false,
|
|
149
|
+
}, {
|
|
150
|
+
position: null,
|
|
151
|
+
latch: false,
|
|
152
|
+
speed: ThreeLevelAuto.Auto,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
async triggerOperationalError(errorState = []) {
|
|
156
|
+
await this.setAttribute(ClosureControl, 'mainState', ClosureControl.MainState.Error);
|
|
157
|
+
await this.setAttribute(ClosureControl, 'currentErrorList', errorState);
|
|
158
|
+
await this.triggerEvent(ClosureControl, 'operationalError', { errorState });
|
|
159
|
+
}
|
|
160
|
+
async triggerMovementCompleted() {
|
|
161
|
+
await this.triggerEvent(ClosureControl, 'movementCompleted', undefined);
|
|
162
|
+
}
|
|
163
|
+
async triggerSecureStateChanged(secureValue) {
|
|
164
|
+
await this.triggerEvent(ClosureControl, 'secureStateChanged', { secureValue });
|
|
165
|
+
}
|
|
73
166
|
addPanel(name, tagList, dimensionType, options = {}) {
|
|
74
167
|
const panel = this.addChildDeviceType(name, closurePanel, { tagList });
|
|
75
168
|
createClosureDimensionClusterServer(panel, dimensionType, options);
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { ClosureDimensionServer } from '@matter/node/behaviors/closure-dimension';
|
|
2
2
|
import { ClosureDimension } from '@matter/types/clusters/closure-dimension';
|
|
3
|
-
import type {
|
|
4
|
-
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
3
|
+
import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
5
4
|
export type ClosureDimensionType = 'lift' | 'tilt' | 'modulation';
|
|
6
5
|
declare const MatterbridgeClosureDimensionServer_base: import("@matter/node").ClusterBehavior.Type<typeof ClosureDimensionServer, import("@matter/types").ClusterType.WithSupportedFeatures<ClosureDimension, {
|
|
7
6
|
limitation: false;
|
|
@@ -27,10 +26,6 @@ export interface ClosurePanelOptions {
|
|
|
27
26
|
rotationAxis?: ClosureDimension.RotationAxis;
|
|
28
27
|
overflow?: ClosureDimension.Overflow;
|
|
29
28
|
modulationType?: ClosureDimension.ModulationType;
|
|
30
|
-
tagList?: Semtag[];
|
|
31
|
-
}
|
|
32
|
-
export declare class ClosurePanel extends MatterbridgeEndpoint {
|
|
33
|
-
constructor(name: string, serial: string, dimensionType: ClosureDimensionType, options?: ClosurePanelOptions);
|
|
34
29
|
}
|
|
35
30
|
export declare function createClosureDimensionClusterServer(endpoint: MatterbridgeEndpoint, dimensionType: ClosureDimensionType, options: ClosurePanelOptions): MatterbridgeEndpoint;
|
|
36
31
|
export {};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { ClosureControlServer } from '@matter/node/behaviors/closure-control';
|
|
1
2
|
import { ClosureDimensionServer } from '@matter/node/behaviors/closure-dimension';
|
|
3
|
+
import { StatusResponse } from '@matter/types';
|
|
4
|
+
import { ClosureControl } from '@matter/types/clusters/closure-control';
|
|
2
5
|
import { ClosureDimension } from '@matter/types/clusters/closure-dimension';
|
|
3
6
|
import { ThreeLevelAuto } from '@matter/types/globals';
|
|
4
7
|
import { MatterbridgeServer } from '../behaviors/matterbridgeServer.js';
|
|
5
|
-
import { closurePanel } from '../matterbridgeDeviceTypes.js';
|
|
6
|
-
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
7
8
|
export class MatterbridgeClosureDimensionServer extends ClosureDimensionServer.with(ClosureDimension.Feature.Positioning, ClosureDimension.Feature.MotionLatching, ClosureDimension.Feature.Speed) {
|
|
8
9
|
setTarget = async (request) => {
|
|
9
10
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -15,13 +16,48 @@ export class MatterbridgeClosureDimensionServer extends ClosureDimensionServer.w
|
|
|
15
16
|
attributes: this.state,
|
|
16
17
|
endpoint: this.endpoint,
|
|
17
18
|
});
|
|
19
|
+
if (request.position === undefined && request.latch === undefined && request.speed === undefined) {
|
|
20
|
+
throw new StatusResponse.InvalidCommandError('ClosureDimension.setTarget requires at least one of position, latch, or speed to be present');
|
|
21
|
+
}
|
|
22
|
+
if (request.position !== undefined && (request.position < 0 || request.position > 10000)) {
|
|
23
|
+
throw new StatusResponse.ConstraintErrorError('ClosureDimension.setTarget position must be between 0 and 10000');
|
|
24
|
+
}
|
|
25
|
+
const latchControlModes = this.state.latchControlModes;
|
|
26
|
+
if (request.latch !== undefined && ((request.latch && !latchControlModes?.remoteLatching) || (!request.latch && !latchControlModes?.remoteUnlatching))) {
|
|
27
|
+
throw new StatusResponse.InvalidInStateError('ClosureDimension.setTarget latch change requires manual intervention per LatchControlModes');
|
|
28
|
+
}
|
|
29
|
+
if (request.speed !== undefined && (request.speed < ThreeLevelAuto.Auto || request.speed > ThreeLevelAuto.High)) {
|
|
30
|
+
throw new StatusResponse.ConstraintErrorError('ClosureDimension.setTarget speed must be a valid ThreeLevelAutoEnum value');
|
|
31
|
+
}
|
|
32
|
+
const associatedMainState = this.endpoint.owner?.maybeStateOf(ClosureControlServer)?.mainState;
|
|
33
|
+
if (associatedMainState !== undefined &&
|
|
34
|
+
[
|
|
35
|
+
ClosureControl.MainState.Disengaged,
|
|
36
|
+
ClosureControl.MainState.Protected,
|
|
37
|
+
ClosureControl.MainState.Calibrating,
|
|
38
|
+
ClosureControl.MainState.SetupRequired,
|
|
39
|
+
ClosureControl.MainState.Error,
|
|
40
|
+
].includes(associatedMainState)) {
|
|
41
|
+
throw new StatusResponse.InvalidInStateError('ClosureDimension.setTarget is not allowed while the associated ClosureControl is Disengaged, Protected, Calibrating, SetupRequired, or Error');
|
|
42
|
+
}
|
|
43
|
+
const currentState = this.state.currentState;
|
|
44
|
+
if (request.position !== undefined && currentState?.latch === true && request.latch !== false) {
|
|
45
|
+
throw new StatusResponse.InvalidInStateError('ClosureDimension.setTarget position changes require latch false while the closure is latched');
|
|
46
|
+
}
|
|
18
47
|
const previousTarget = this.state.targetState ?? {};
|
|
48
|
+
const resolution = this.state.resolution;
|
|
19
49
|
const nextTarget = {
|
|
20
50
|
...previousTarget,
|
|
21
|
-
...(request?.position !== undefined ? { position: request.position } : null),
|
|
51
|
+
...(request?.position !== undefined ? { position: Math.round(request.position / resolution) * resolution } : null),
|
|
22
52
|
...(request?.latch !== undefined ? { latch: request.latch } : null),
|
|
23
53
|
speed: request?.speed ?? ThreeLevelAuto.Auto,
|
|
24
54
|
};
|
|
55
|
+
const matchesCurrentState = currentState !== null &&
|
|
56
|
+
(nextTarget.position === undefined || nextTarget.position === currentState.position) &&
|
|
57
|
+
(nextTarget.latch === undefined || nextTarget.latch === currentState.latch) &&
|
|
58
|
+
nextTarget.speed === currentState.speed;
|
|
59
|
+
if (matchesCurrentState)
|
|
60
|
+
return;
|
|
25
61
|
this.state.targetState = nextTarget;
|
|
26
62
|
};
|
|
27
63
|
step = async (request) => {
|
|
@@ -34,37 +70,51 @@ export class MatterbridgeClosureDimensionServer extends ClosureDimensionServer.w
|
|
|
34
70
|
attributes: this.state,
|
|
35
71
|
endpoint: this.endpoint,
|
|
36
72
|
});
|
|
73
|
+
if (request.direction < ClosureDimension.StepDirection.Decrease || request.direction > ClosureDimension.StepDirection.Increase) {
|
|
74
|
+
throw new StatusResponse.ConstraintErrorError('ClosureDimension.step direction must be a valid StepDirectionEnum value');
|
|
75
|
+
}
|
|
76
|
+
if (request.numberOfSteps < 1) {
|
|
77
|
+
throw new StatusResponse.ConstraintErrorError('ClosureDimension.step numberOfSteps must be at least 1');
|
|
78
|
+
}
|
|
79
|
+
if (request.speed !== undefined && (request.speed < ThreeLevelAuto.Auto || request.speed > ThreeLevelAuto.High)) {
|
|
80
|
+
throw new StatusResponse.ConstraintErrorError('ClosureDimension.step speed must be a valid ThreeLevelAutoEnum value');
|
|
81
|
+
}
|
|
82
|
+
const currentState = this.state.currentState;
|
|
83
|
+
if (currentState?.latch === true) {
|
|
84
|
+
throw new StatusResponse.InvalidInStateError('ClosureDimension.step is not allowed while the closure is latched');
|
|
85
|
+
}
|
|
86
|
+
const associatedMainState = this.endpoint.owner?.maybeStateOf(ClosureControlServer)?.mainState;
|
|
87
|
+
if (associatedMainState !== undefined &&
|
|
88
|
+
[
|
|
89
|
+
ClosureControl.MainState.Disengaged,
|
|
90
|
+
ClosureControl.MainState.Protected,
|
|
91
|
+
ClosureControl.MainState.Calibrating,
|
|
92
|
+
ClosureControl.MainState.SetupRequired,
|
|
93
|
+
ClosureControl.MainState.Error,
|
|
94
|
+
].includes(associatedMainState)) {
|
|
95
|
+
throw new StatusResponse.InvalidInStateError('ClosureDimension.step is not allowed while the associated ClosureControl is Disengaged, Protected, Calibrating, SetupRequired, or Error');
|
|
96
|
+
}
|
|
37
97
|
const stepValue = this.state.stepValue;
|
|
38
98
|
const numberOfSteps = request.numberOfSteps;
|
|
39
99
|
const delta = stepValue * numberOfSteps;
|
|
40
100
|
const isIncrease = request.direction === ClosureDimension.StepDirection.Increase;
|
|
41
|
-
const
|
|
42
|
-
const previousTarget = this.state.targetState ?? {};
|
|
43
|
-
const currentPosition = typeof previousCurrent.position === 'number' ? previousCurrent.position : typeof previousTarget.position === 'number' ? previousTarget.position : 0;
|
|
101
|
+
const currentPosition = typeof currentState?.position === 'number' ? currentState.position : 0;
|
|
44
102
|
let nextPosition = isIncrease ? currentPosition + delta : currentPosition - delta;
|
|
45
103
|
nextPosition = Math.max(0, Math.min(10000, nextPosition));
|
|
46
|
-
const
|
|
47
|
-
this.state.
|
|
48
|
-
...
|
|
104
|
+
const previousTarget = this.state.targetState ?? {};
|
|
105
|
+
this.state.targetState = {
|
|
106
|
+
...previousTarget,
|
|
49
107
|
position: nextPosition,
|
|
50
|
-
speed,
|
|
108
|
+
...(request.speed !== undefined ? { speed: request.speed } : null),
|
|
51
109
|
};
|
|
52
|
-
this.state.targetState = { ...previousTarget, position: nextPosition, speed };
|
|
53
110
|
};
|
|
54
111
|
}
|
|
55
|
-
export class ClosurePanel extends MatterbridgeEndpoint {
|
|
56
|
-
constructor(name, serial, dimensionType, options = {}) {
|
|
57
|
-
super([closurePanel], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`, tagList: options.tagList });
|
|
58
|
-
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Closure Panel');
|
|
59
|
-
createClosureDimensionClusterServer(this, dimensionType, options);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
112
|
export function createClosureDimensionClusterServer(endpoint, dimensionType, options) {
|
|
63
113
|
const commonOptions = {
|
|
64
114
|
currentState: options.currentState ?? { position: 0, latch: true, speed: ThreeLevelAuto.Auto },
|
|
65
115
|
targetState: options.targetState ?? { position: 0, latch: true, speed: ThreeLevelAuto.Auto },
|
|
66
|
-
resolution: options.resolution ?? 1,
|
|
67
|
-
stepValue: options.stepValue ?? 1,
|
|
116
|
+
resolution: Math.max(1, options.resolution ?? 1),
|
|
117
|
+
stepValue: Math.max(1, options.stepValue ?? 1),
|
|
68
118
|
latchControlModes: options.latchControlModes ?? { remoteLatching: true, remoteUnlatching: true },
|
|
69
119
|
};
|
|
70
120
|
if (dimensionType === 'lift') {
|
|
@@ -993,7 +993,7 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
993
993
|
...(occupied !== undefined ? { occupancy: { occupied } } : {}),
|
|
994
994
|
...(occupied !== undefined ? { externallyMeasuredOccupancy: true } : {}),
|
|
995
995
|
numberOfPresets: Math.max(Array.isArray(presets) ? presets.length : 0, Array.isArray(presetTypes) ? Math.max(0, ...presetTypes.map((pt) => pt.numberOfPresets ?? 0)) : 0, 1),
|
|
996
|
-
activePresetHandle: activePresetHandle ? Uint8Array.from(
|
|
996
|
+
activePresetHandle: activePresetHandle ? Uint8Array.from(activePresetHandle) : null,
|
|
997
997
|
presets: (presets ?? []).map((p) => ({
|
|
998
998
|
presetHandle: p.presetHandle ? Uint8Array.from(p.presetHandle) : null,
|
|
999
999
|
presetScenario: p.presetScenario,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matterbridge/core",
|
|
3
|
-
"version": "3.10.5
|
|
3
|
+
"version": "3.10.5",
|
|
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.5
|
|
136
|
-
"@matterbridge/thread": "3.10.5
|
|
137
|
-
"@matterbridge/types": "3.10.5
|
|
138
|
-
"@matterbridge/utils": "3.10.5
|
|
135
|
+
"@matterbridge/dgram": "3.10.5",
|
|
136
|
+
"@matterbridge/thread": "3.10.5",
|
|
137
|
+
"@matterbridge/types": "3.10.5",
|
|
138
|
+
"@matterbridge/utils": "3.10.5",
|
|
139
139
|
"escape-html": "1.0.3",
|
|
140
140
|
"express": "5.2.1",
|
|
141
141
|
"express-rate-limit": "8.6.2",
|