@matterbridge/core 3.10.6-dev-20260818-c2c6349 → 3.10.6-dev-20260820-36b52be
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/fanControlServer.d.ts +3 -0
- package/dist/behaviors/fanControlServer.js +179 -15
- package/dist/behaviors/onOffServer.js +60 -48
- package/dist/cli.js +1 -0
- package/dist/demoDevices.d.ts +2 -0
- package/dist/{chipTestDevices.js → demoDevices.js} +80 -13
- package/dist/devices/closure.d.ts +3 -0
- package/dist/devices/closure.js +3 -2
- package/dist/frontend.js +51 -44
- package/dist/matterNode.js +1 -0
- package/dist/matterbridge.js +16 -6
- package/dist/matterbridgeEndpoint.d.ts +6 -5
- package/dist/matterbridgeEndpoint.js +13 -13
- package/dist/matterbridgeEndpointHelpers.d.ts +5 -5
- package/dist/matterbridgeEndpointHelpers.js +11 -10
- package/dist/pluginManager.js +4 -2
- package/package.json +5 -5
- package/dist/chipTestDevices.d.ts +0 -2
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { MaybePromise } from '@matter/general';
|
|
1
2
|
import { FanControlServer } from '@matter/node/behaviors/fan-control';
|
|
2
3
|
import { FanControl } from '@matter/types/clusters/fan-control';
|
|
3
4
|
declare const MatterbridgeFanControlServer_base: import("@matter/node").ClusterBehavior.Type<typeof FanControlServer, import("@matter/types").ClusterType.WithSupportedFeatures<FanControl, {
|
|
@@ -9,6 +10,8 @@ declare const MatterbridgeFanControlServer_base: import("@matter/node").ClusterB
|
|
|
9
10
|
wind: false;
|
|
10
11
|
}>, import("@matter/types").ClusterType.Concrete, new () => {}, "fanControl">;
|
|
11
12
|
export declare class MatterbridgeFanControlServer extends MatterbridgeFanControlServer_base {
|
|
13
|
+
#private;
|
|
14
|
+
initialize(): MaybePromise;
|
|
12
15
|
step(request: FanControl.StepRequest): Promise<void>;
|
|
13
16
|
}
|
|
14
17
|
export {};
|
|
@@ -1,10 +1,161 @@
|
|
|
1
1
|
import { FanControlServer } from '@matter/node/behaviors/fan-control';
|
|
2
|
+
import { Status, StatusResponseError } from '@matter/types';
|
|
2
3
|
import { FanControl } from '@matter/types/clusters/fan-control';
|
|
4
|
+
import { getEnumDescription } from '@matterbridge/utils/enum';
|
|
3
5
|
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
6
|
+
const lookupStepDirection = ['Increase', 'Decrease'];
|
|
7
|
+
const lookupFanMode = ['Off', 'Low', 'Medium', 'High', 'On', 'Auto', 'Auto', 'Smart'];
|
|
8
|
+
const supportedFanModesBySequence = {
|
|
9
|
+
[FanControl.FanModeSequence.OffLowMedHigh]: new Set([FanControl.FanMode.Off, FanControl.FanMode.Low, FanControl.FanMode.Medium, FanControl.FanMode.High]),
|
|
10
|
+
[FanControl.FanModeSequence.OffLowHigh]: new Set([FanControl.FanMode.Off, FanControl.FanMode.Low, FanControl.FanMode.High]),
|
|
11
|
+
[FanControl.FanModeSequence.OffLowMedHighAuto]: new Set([
|
|
12
|
+
FanControl.FanMode.Off,
|
|
13
|
+
FanControl.FanMode.Low,
|
|
14
|
+
FanControl.FanMode.Medium,
|
|
15
|
+
FanControl.FanMode.High,
|
|
16
|
+
FanControl.FanMode.Auto,
|
|
17
|
+
]),
|
|
18
|
+
[FanControl.FanModeSequence.OffLowHighAuto]: new Set([FanControl.FanMode.Off, FanControl.FanMode.Low, FanControl.FanMode.High, FanControl.FanMode.Auto]),
|
|
19
|
+
[FanControl.FanModeSequence.OffHighAuto]: new Set([FanControl.FanMode.Off, FanControl.FanMode.High, FanControl.FanMode.Auto]),
|
|
20
|
+
[FanControl.FanModeSequence.OffHigh]: new Set([FanControl.FanMode.Off, FanControl.FanMode.High]),
|
|
21
|
+
};
|
|
22
|
+
const steppedFanModes = [FanControl.FanMode.Low, FanControl.FanMode.Medium, FanControl.FanMode.High];
|
|
23
|
+
function computePercentRanges(sequence) {
|
|
24
|
+
const supported = supportedFanModesBySequence[sequence];
|
|
25
|
+
const modes = steppedFanModes.filter((fanMode) => supported.has(fanMode));
|
|
26
|
+
const ranges = [];
|
|
27
|
+
let start = 1;
|
|
28
|
+
modes.forEach((fanMode, index) => {
|
|
29
|
+
const end = Math.floor((100 * (index + 1)) / modes.length);
|
|
30
|
+
ranges.push({ fanMode, start, end });
|
|
31
|
+
start = end + 1;
|
|
32
|
+
});
|
|
33
|
+
return ranges;
|
|
34
|
+
}
|
|
35
|
+
function percentToFanMode(percent, sequence) {
|
|
36
|
+
const ranges = computePercentRanges(sequence);
|
|
37
|
+
const range = ranges.find((candidate) => percent >= candidate.start && percent <= candidate.end);
|
|
38
|
+
return range?.fanMode ?? FanControl.FanMode.High;
|
|
39
|
+
}
|
|
40
|
+
function resolvePercentSettingForFanMode(fanMode, currentPercentSetting, sequence) {
|
|
41
|
+
if (fanMode === FanControl.FanMode.Off)
|
|
42
|
+
return 0;
|
|
43
|
+
const alreadyInRange = currentPercentSetting !== null && currentPercentSetting !== 0 && percentToFanMode(currentPercentSetting, sequence) === fanMode;
|
|
44
|
+
if (alreadyInRange)
|
|
45
|
+
return currentPercentSetting;
|
|
46
|
+
const range = computePercentRanges(sequence).find((candidate) => candidate.fanMode === fanMode);
|
|
47
|
+
return range ? Math.round((range.start + range.end) / 2) : (currentPercentSetting ?? 0);
|
|
48
|
+
}
|
|
49
|
+
function resolveStepPercentSettingForFanMode(fanMode, direction, currentPercentSetting, sequence) {
|
|
50
|
+
if (fanMode === FanControl.FanMode.Off)
|
|
51
|
+
return 0;
|
|
52
|
+
const alreadyInRange = currentPercentSetting !== null && currentPercentSetting !== 0 && percentToFanMode(currentPercentSetting, sequence) === fanMode;
|
|
53
|
+
if (alreadyInRange)
|
|
54
|
+
return currentPercentSetting;
|
|
55
|
+
const range = computePercentRanges(sequence).find((candidate) => candidate.fanMode === fanMode);
|
|
56
|
+
if (!range)
|
|
57
|
+
return currentPercentSetting ?? 0;
|
|
58
|
+
return direction === FanControl.StepDirection.Increase ? range.start : range.end;
|
|
59
|
+
}
|
|
60
|
+
function speedSettingForPercent(speedMax, percent) {
|
|
61
|
+
return Math.ceil((speedMax * percent) / 100);
|
|
62
|
+
}
|
|
4
63
|
export class MatterbridgeFanControlServer extends FanControlServer.with(FanControl.Feature.Auto, FanControl.Feature.Step) {
|
|
64
|
+
initialize() {
|
|
65
|
+
const result = super.initialize();
|
|
66
|
+
this.reactTo(this.events.fanMode$Changing, this.#handleFanModeChanging);
|
|
67
|
+
this.reactTo(this.events.percentSetting$Changing, this.#handlePercentSettingChanging);
|
|
68
|
+
this.maybeReactTo(this.events.speedSetting$Changing, this.#handleSpeedSettingChanging);
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
#handleFanModeChanging(fanMode) {
|
|
72
|
+
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
73
|
+
if (fanMode === FanControl.FanMode.On) {
|
|
74
|
+
this.state.fanMode = FanControl.FanMode.High;
|
|
75
|
+
device.log.debug(`handleFanModeChanging fanMode changed to ${lookupFanMode[fanMode]} >>> fanMode ${lookupFanMode[this.state.fanMode]} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
if (fanMode === FanControl.FanMode.Smart) {
|
|
79
|
+
this.state.fanMode = this.features.auto ? FanControl.FanMode.Auto : FanControl.FanMode.High;
|
|
80
|
+
device.log.debug(`handleFanModeChanging fanMode changed to ${lookupFanMode[fanMode]} >>> fanMode ${lookupFanMode[this.state.fanMode]} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (!supportedFanModesBySequence[this.state.fanModeSequence].has(fanMode)) {
|
|
84
|
+
throw new StatusResponseError(`FanMode ${getEnumDescription(FanControl.FanMode, fanMode)} is not supported by FanModeSequence ${getEnumDescription(FanControl.FanModeSequence, this.state.fanModeSequence)}`, Status.ConstraintError);
|
|
85
|
+
}
|
|
86
|
+
if (fanMode === FanControl.FanMode.Off) {
|
|
87
|
+
this.state.percentSetting = 0;
|
|
88
|
+
if (this.features.multiSpeed) {
|
|
89
|
+
this.state.speedSetting = 0;
|
|
90
|
+
}
|
|
91
|
+
this.agent.asLocalActor(() => {
|
|
92
|
+
this.state.percentCurrent = 0;
|
|
93
|
+
if (this.features.multiSpeed) {
|
|
94
|
+
this.state.speedCurrent = 0;
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
device.log.debug(`handleFanModeChanging fanMode changed to ${lookupFanMode[fanMode]} >>> percentSetting ${this.state.percentSetting} percentCurrent ${this.state.percentCurrent} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
98
|
+
if (this.features.multiSpeed) {
|
|
99
|
+
device.log.debug(`handleFanModeChanging fanMode changed to ${lookupFanMode[fanMode]} >>> speedSetting ${this.state.speedSetting} speedCurrent ${this.state.speedCurrent} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (fanMode === FanControl.FanMode.Auto) {
|
|
103
|
+
this.state.percentSetting = null;
|
|
104
|
+
if (this.features.multiSpeed) {
|
|
105
|
+
this.state.speedSetting = null;
|
|
106
|
+
device.log.debug(`handleFanModeChanging fanMode changed to ${lookupFanMode[fanMode]} >>> speedSetting ${this.state.speedSetting} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
107
|
+
}
|
|
108
|
+
device.log.debug(`handleFanModeChanging fanMode changed to ${lookupFanMode[fanMode]} >>> percentSetting ${this.state.percentSetting} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
const resolved = resolvePercentSettingForFanMode(fanMode, this.state.percentSetting, this.state.fanModeSequence);
|
|
112
|
+
if (resolved !== this.state.percentSetting)
|
|
113
|
+
this.state.percentSetting = resolved;
|
|
114
|
+
device.log.debug(`handleFanModeChanging fanMode changed to ${lookupFanMode[fanMode]} >>> percentSetting ${this.state.percentSetting} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
#handlePercentSettingChanging(percentSetting, oldPercentSetting) {
|
|
118
|
+
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
119
|
+
if (percentSetting === null) {
|
|
120
|
+
if (this.state.fanMode === FanControl.FanMode.Auto)
|
|
121
|
+
return;
|
|
122
|
+
this.state.percentSetting = oldPercentSetting;
|
|
123
|
+
device.log.debug(`handlePercentSettingChanging percentSetting changed to ${percentSetting} >>> fanMode ${lookupFanMode[this.state.fanMode]} percentSetting ${this.state.percentSetting} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const fanMode = percentSetting === 0 ? FanControl.FanMode.Off : percentToFanMode(percentSetting, this.state.fanModeSequence);
|
|
127
|
+
if (fanMode !== this.state.fanMode)
|
|
128
|
+
this.state.fanMode = fanMode;
|
|
129
|
+
if (this.features.multiSpeed) {
|
|
130
|
+
const state = this.state;
|
|
131
|
+
state.speedSetting = speedSettingForPercent(state.speedMax, percentSetting);
|
|
132
|
+
}
|
|
133
|
+
device.log.debug(`handlePercentSettingChanging percentSetting changed to ${percentSetting} >>> fanMode ${lookupFanMode[this.state.fanMode]} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
134
|
+
}
|
|
135
|
+
#handleSpeedSettingChanging(speedSetting, oldSpeedSetting) {
|
|
136
|
+
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
137
|
+
const state = this.state;
|
|
138
|
+
if (speedSetting === null) {
|
|
139
|
+
if (this.state.fanMode === FanControl.FanMode.Auto)
|
|
140
|
+
return;
|
|
141
|
+
state.speedSetting = oldSpeedSetting;
|
|
142
|
+
device.log.debug(`handleSpeedSettingChanging speedSetting changed to ${speedSetting} >>> fanMode ${lookupFanMode[this.state.fanMode]} speedSetting ${state.speedSetting} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const { percentSetting } = this.state;
|
|
146
|
+
if (percentSetting !== null && speedSettingForPercent(state.speedMax, percentSetting) === speedSetting)
|
|
147
|
+
return;
|
|
148
|
+
const percent = speedSetting === 0 ? 0 : Math.min(100, Math.round((speedSetting / state.speedMax) * 100));
|
|
149
|
+
const fanMode = percent === 0 ? FanControl.FanMode.Off : percentToFanMode(percent, this.state.fanModeSequence);
|
|
150
|
+
if (fanMode !== this.state.fanMode)
|
|
151
|
+
this.state.fanMode = fanMode;
|
|
152
|
+
if (percent !== this.state.percentSetting)
|
|
153
|
+
this.state.percentSetting = percent;
|
|
154
|
+
device.log.debug(`handleSpeedSettingChanging speedSetting changed to ${speedSetting} >>> fanMode ${lookupFanMode[this.state.fanMode]} percentSetting ${this.state.percentSetting} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
155
|
+
}
|
|
5
156
|
async step(request) {
|
|
6
157
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
7
|
-
device.log.info(`Stepping fan with direction ${request.direction} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
158
|
+
device.log.info(`Stepping fan with direction ${lookupStepDirection[request.direction]} wrap: ${request.wrap} lowestOff: ${request.lowestOff} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
8
159
|
await device.commandHandler.executeHandler('FanControl.step', {
|
|
9
160
|
command: 'step',
|
|
10
161
|
request,
|
|
@@ -13,23 +164,36 @@ export class MatterbridgeFanControlServer extends FanControlServer.with(FanContr
|
|
|
13
164
|
endpoint: this.endpoint,
|
|
14
165
|
context: this.context,
|
|
15
166
|
});
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
167
|
+
const wrap = request.wrap ?? false;
|
|
168
|
+
const lowestOff = request.lowestOff ?? true;
|
|
169
|
+
const currentFanMode = this.state.fanMode;
|
|
170
|
+
const currentPercentSetting = this.state.percentSetting;
|
|
171
|
+
const fanModeSequence = this.state.fanModeSequence;
|
|
172
|
+
const supported = supportedFanModesBySequence[fanModeSequence];
|
|
173
|
+
const stepFanModes = [...(lowestOff ? [FanControl.FanMode.Off] : []), ...steppedFanModes.filter((fanMode) => supported.has(fanMode))];
|
|
174
|
+
let targetFanMode;
|
|
19
175
|
if (request.direction === FanControl.StepDirection.Increase) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
else
|
|
24
|
-
this.state.percentCurrent = Math.min(this.state.percentCurrent + 10, 100);
|
|
176
|
+
const higher = stepFanModes.filter((fanMode) => fanMode > currentFanMode);
|
|
177
|
+
targetFanMode = higher.length > 0 ? Math.min(...higher) : wrap ? Math.min(...stepFanModes) : Math.max(...stepFanModes);
|
|
25
178
|
}
|
|
26
179
|
else if (request.direction === FanControl.StepDirection.Decrease) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
180
|
+
const lower = stepFanModes.filter((fanMode) => fanMode < currentFanMode);
|
|
181
|
+
targetFanMode = lower.length > 0 ? Math.max(...lower) : wrap ? Math.max(...stepFanModes) : Math.min(...stepFanModes);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (targetFanMode !== currentFanMode)
|
|
187
|
+
this.state.fanMode = targetFanMode;
|
|
188
|
+
const resolvedPercentSetting = resolveStepPercentSettingForFanMode(targetFanMode, request.direction, currentPercentSetting, fanModeSequence);
|
|
189
|
+
if (resolvedPercentSetting !== this.state.percentSetting)
|
|
190
|
+
this.state.percentSetting = resolvedPercentSetting;
|
|
191
|
+
this.state.percentCurrent = resolvedPercentSetting;
|
|
192
|
+
if (this.features.multiSpeed) {
|
|
193
|
+
const state = this.state;
|
|
194
|
+
state.speedCurrent = speedSettingForPercent(state.speedMax, resolvedPercentSetting);
|
|
32
195
|
}
|
|
33
|
-
device.log.debug(
|
|
196
|
+
device.log.debug(`MatterbridgeFanControlServer: step applied fanMode ${lookupFanMode[this.state.fanMode]}, percentCurrent ${this.state.percentCurrent}` +
|
|
197
|
+
(this.features.multiSpeed ? `, speedCurrent ${this.state.speedCurrent}` : ''));
|
|
34
198
|
}
|
|
35
199
|
}
|
|
@@ -5,84 +5,96 @@ export class MatterbridgeOnOffServer extends OnOffServer.with(OnOff.Feature.Ligh
|
|
|
5
5
|
async on() {
|
|
6
6
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
7
7
|
device.log.info(`Switching device on (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
if (!process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
9
|
+
await device.commandHandler.executeHandler('OnOff.on', {
|
|
10
|
+
command: 'on',
|
|
11
|
+
request: {},
|
|
12
|
+
cluster: OnOffServer.id,
|
|
13
|
+
attributes: this.state,
|
|
14
|
+
endpoint: this.endpoint,
|
|
15
|
+
context: this.context,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
16
18
|
device.log.debug(`MatterbridgeOnOffServer: on called`);
|
|
17
19
|
await super.on();
|
|
18
20
|
}
|
|
19
21
|
async off() {
|
|
20
22
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
21
23
|
device.log.info(`Switching device off (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
if (!process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
25
|
+
await device.commandHandler.executeHandler('OnOff.off', {
|
|
26
|
+
command: 'off',
|
|
27
|
+
request: {},
|
|
28
|
+
cluster: OnOffServer.id,
|
|
29
|
+
attributes: this.state,
|
|
30
|
+
endpoint: this.endpoint,
|
|
31
|
+
context: this.context,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
30
34
|
device.log.debug(`MatterbridgeOnOffServer: off called`);
|
|
31
35
|
await super.off();
|
|
32
36
|
}
|
|
33
37
|
async toggle() {
|
|
34
38
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
35
39
|
device.log.info(`Toggle device on/off (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
if (!process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
41
|
+
await device.commandHandler.executeHandler('OnOff.toggle', {
|
|
42
|
+
command: 'toggle',
|
|
43
|
+
request: {},
|
|
44
|
+
cluster: OnOffServer.id,
|
|
45
|
+
attributes: this.state,
|
|
46
|
+
endpoint: this.endpoint,
|
|
47
|
+
context: this.context,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
44
50
|
device.log.debug(`MatterbridgeOnOffServer: toggle called`);
|
|
45
51
|
await super.toggle();
|
|
46
52
|
}
|
|
47
53
|
async offWithEffect(request) {
|
|
48
54
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
49
55
|
device.log.info(`Switching device off with effect ${request.effectIdentifier} and variant ${request.effectVariant} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
if (!process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
57
|
+
await device.commandHandler.executeHandler('OnOff.offWithEffect', {
|
|
58
|
+
command: 'offWithEffect',
|
|
59
|
+
request,
|
|
60
|
+
cluster: OnOffServer.id,
|
|
61
|
+
attributes: this.state,
|
|
62
|
+
endpoint: this.endpoint,
|
|
63
|
+
context: this.context,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
58
66
|
device.log.debug(`MatterbridgeOnOffServer: offWithEffect called`);
|
|
59
67
|
await super.offWithEffect(request);
|
|
60
68
|
}
|
|
61
69
|
async onWithRecallGlobalScene() {
|
|
62
70
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
63
71
|
device.log.info(`Switching device on with recall global scene (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
+
if (!process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
73
|
+
await device.commandHandler.executeHandler('OnOff.onWithRecallGlobalScene', {
|
|
74
|
+
command: 'onWithRecallGlobalScene',
|
|
75
|
+
request: {},
|
|
76
|
+
cluster: OnOffServer.id,
|
|
77
|
+
attributes: this.state,
|
|
78
|
+
endpoint: this.endpoint,
|
|
79
|
+
context: this.context,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
72
82
|
device.log.debug(`MatterbridgeOnOffServer: onWithRecallGlobalScene called`);
|
|
73
83
|
await super.onWithRecallGlobalScene();
|
|
74
84
|
}
|
|
75
85
|
async onWithTimedOff(request) {
|
|
76
86
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
77
87
|
device.log.info(`Switching device on with timed off control ${JSON.stringify(request.onOffControl)}, offWaitTime ${request.offWaitTime} and onTime ${request.onTime} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
88
|
+
if (!process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
89
|
+
await device.commandHandler.executeHandler('OnOff.onWithTimedOff', {
|
|
90
|
+
command: 'onWithTimedOff',
|
|
91
|
+
request,
|
|
92
|
+
cluster: OnOffServer.id,
|
|
93
|
+
attributes: this.state,
|
|
94
|
+
endpoint: this.endpoint,
|
|
95
|
+
context: this.context,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
86
98
|
device.log.debug(`MatterbridgeOnOffServer: onWithTimedOff called`);
|
|
87
99
|
await super.onWithTimedOff(request);
|
|
88
100
|
}
|
package/dist/cli.js
CHANGED
|
@@ -141,6 +141,7 @@ function help() {
|
|
|
141
141
|
--loginterfaces: log the network interfaces (usefull for finding the name of the interface to use with -mdnsinterface option)
|
|
142
142
|
--logstorage: log the node storage
|
|
143
143
|
--systemcheck: perform a system check (check Node.js version and network interfaces)
|
|
144
|
+
--demo-devices: create demo devices (only in bridge mode)
|
|
144
145
|
|
|
145
146
|
Reset Commands:
|
|
146
147
|
--reset: remove the commissioning for Matterbridge (bridge mode and childbridge mode). Shutdown Matterbridge before using it!
|
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
import { CommonNumberTag } from '@matter/node';
|
|
2
|
+
import { AirQuality } from '@matter/types/clusters/air-quality';
|
|
3
|
+
import { FanControl } from '@matter/types/clusters/fan-control';
|
|
4
|
+
import { PowerSource } from '@matter/types/clusters/power-source';
|
|
2
5
|
import { EndpointNumber } from '@matter/types/datatype';
|
|
6
|
+
import { Closure } from './devices/closure.js';
|
|
3
7
|
import { IrrigationSystem } from './devices/irrigationSystem.js';
|
|
4
8
|
import { getSupportedDeviceType } from './matterbridgeDeviceTypes.js';
|
|
5
9
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
6
10
|
import { getSemtag } from './matterbridgeEndpointHelpers.js';
|
|
7
|
-
export async function
|
|
8
|
-
if (
|
|
11
|
+
export async function createDemoDevices(matterbridge) {
|
|
12
|
+
if (matterbridge.bridgeMode !== 'bridge' || !matterbridge.serverNode || !matterbridge.aggregatorNode)
|
|
9
13
|
return;
|
|
10
14
|
const serverNode = matterbridge.serverNode;
|
|
11
15
|
const aggregator = matterbridge.aggregatorNode;
|
|
12
16
|
if (!serverNode || !aggregator) {
|
|
13
|
-
matterbridge.log.error('
|
|
17
|
+
matterbridge.log.error('Demo devices can only be created when the server node and aggregator node are available');
|
|
14
18
|
return;
|
|
15
19
|
}
|
|
16
20
|
let ep;
|
|
17
21
|
matterbridge.plugins.set({
|
|
18
|
-
name: 'matterbridge-
|
|
22
|
+
name: 'matterbridge-demo-devices',
|
|
19
23
|
path: '',
|
|
20
24
|
type: 'DynamicPlatform',
|
|
21
25
|
version: '1.0.0',
|
|
22
|
-
description: '
|
|
26
|
+
description: 'Matterbridge demo devices',
|
|
23
27
|
author: 'Matterbridge',
|
|
24
28
|
enabled: false,
|
|
25
29
|
private: false,
|
|
@@ -28,8 +32,8 @@ export async function createChipTestDevices(matterbridge) {
|
|
|
28
32
|
const registerDevice = async (device, deviceName, serialNumber) => {
|
|
29
33
|
device.createDefaultBridgedDeviceBasicInformationClusterServer(deviceName, serialNumber);
|
|
30
34
|
device.addRequiredClusters();
|
|
31
|
-
device.plugin = 'matterbridge-
|
|
32
|
-
await matterbridge.addBridgedEndpoint('matterbridge-
|
|
35
|
+
device.plugin = 'matterbridge-demo-devices';
|
|
36
|
+
await matterbridge.addBridgedEndpoint('matterbridge-demo-devices', device);
|
|
33
37
|
};
|
|
34
38
|
const bridgedNode = getSupportedDeviceType('BridgedNode');
|
|
35
39
|
const powerSource = getSupportedDeviceType('PowerSource');
|
|
@@ -157,31 +161,94 @@ export async function createChipTestDevices(matterbridge) {
|
|
|
157
161
|
ep.createSmokeOnlySmokeCOAlarmClusterServer();
|
|
158
162
|
await registerDevice(ep, 'Smoke Alarm', 'SENSOR-07-09-1');
|
|
159
163
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('SmokeCOAlarm'), bridgedNode, powerSource], { id: 'COAlarm', number: EndpointNumber(7_09_2) });
|
|
160
|
-
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
164
|
+
ep.createDefaultPowerSourceBatteryClusterServer(90, PowerSource.BatChargeLevel.Ok);
|
|
161
165
|
ep.createCoOnlySmokeCOAlarmClusterServer();
|
|
162
166
|
await registerDevice(ep, 'CO Alarm', 'SENSOR-07-09-2');
|
|
163
167
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('AirQualitySensor'), bridgedNode, powerSource], { id: 'AirQualitySensor', number: EndpointNumber(7_10) });
|
|
164
|
-
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
168
|
+
ep.createDefaultPowerSourceBatteryClusterServer(70, PowerSource.BatChargeLevel.Ok);
|
|
165
169
|
ep.createDefaultTvocMeasurementClusterServer(50, undefined, undefined, undefined, 0, 1000);
|
|
166
170
|
ep.addOptionalClusterServers();
|
|
167
171
|
await registerDevice(ep, 'Air Quality Sensor', 'SENSOR-07-10');
|
|
168
172
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WaterFreezeDetector'), bridgedNode, powerSource], { id: 'WaterFreezeDetector', number: EndpointNumber(7_11) });
|
|
169
|
-
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
173
|
+
ep.createDefaultPowerSourceBatteryClusterServer(50, PowerSource.BatChargeLevel.Ok);
|
|
170
174
|
ep.createDefaultBooleanStateClusterServer(false);
|
|
171
175
|
ep.createDefaultBooleanStateConfigurationClusterServer();
|
|
172
176
|
await registerDevice(ep, 'Water Freeze Detector', 'SENSOR-07-11');
|
|
173
177
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WaterLeakDetector'), bridgedNode, powerSource], { id: 'WaterLeakDetector', number: EndpointNumber(7_12) });
|
|
174
|
-
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
178
|
+
ep.createDefaultPowerSourceBatteryClusterServer(20, PowerSource.BatChargeLevel.Warning);
|
|
175
179
|
ep.createDefaultBooleanStateClusterServer(false);
|
|
176
180
|
ep.createDefaultBooleanStateConfigurationClusterServer();
|
|
177
181
|
await registerDevice(ep, 'Water Leak Detector', 'SENSOR-07-12');
|
|
178
182
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('RainSensor'), bridgedNode, powerSource], { id: 'RainSensor', number: EndpointNumber(7_13) });
|
|
179
|
-
ep.createDefaultPowerSourceRechargeableBatteryClusterServer();
|
|
183
|
+
ep.createDefaultPowerSourceRechargeableBatteryClusterServer(10, PowerSource.BatChargeLevel.Critical);
|
|
180
184
|
ep.createDefaultBooleanStateClusterServer(false);
|
|
181
185
|
ep.createDefaultBooleanStateConfigurationClusterServer();
|
|
182
186
|
await registerDevice(ep, 'Rain Sensor', 'SENSOR-07-13');
|
|
183
187
|
ep = new MatterbridgeEndpoint([getSupportedDeviceType('SoilSensor'), bridgedNode, powerSource], { id: 'SoilSensor', number: EndpointNumber(7_14) });
|
|
184
|
-
ep.createDefaultPowerSourceWiredClusterServer();
|
|
188
|
+
ep.createDefaultPowerSourceWiredClusterServer(PowerSource.WiredCurrentType.Dc);
|
|
185
189
|
ep.createDefaultSoilMeasurementClusterServer(50);
|
|
186
190
|
await registerDevice(ep, 'Soil Sensor', 'SENSOR-07-14');
|
|
191
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('DoorLock'), bridgedNode, powerSource], { id: 'DoorLock', number: EndpointNumber(8_01) });
|
|
192
|
+
ep.createDefaultPowerSourceBatteryClusterServer();
|
|
193
|
+
await registerDevice(ep, 'Door Lock', 'ENTRY-08-01');
|
|
194
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('DoorLockController'), bridgedNode, powerSource], { id: 'DoorLockController', number: EndpointNumber(8_02) });
|
|
195
|
+
await registerDevice(ep, 'Door Lock Controller', 'ENTRY-08-02');
|
|
196
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCovering'), bridgedNode, powerSource], { id: 'WindowCovering', number: EndpointNumber(8_03) });
|
|
197
|
+
await registerDevice(ep, 'Window Covering', 'ENTRY-08-03');
|
|
198
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('WindowCoveringController'), bridgedNode, powerSource], { id: 'WindowCoveringController', number: EndpointNumber(8_04) });
|
|
199
|
+
await registerDevice(ep, 'Window Covering Controller', 'ENTRY-08-04');
|
|
200
|
+
ep = new Closure('Closure', 'ENTRY-08-05', { id: 'Closure', number: EndpointNumber(8_05) });
|
|
201
|
+
await registerDevice(ep, 'Closure', 'ENTRY-08-05');
|
|
202
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('ClosureController'), bridgedNode, powerSource], { id: 'ClosureController', number: EndpointNumber(8_07) });
|
|
203
|
+
await registerDevice(ep, 'Closure Controller', 'ENTRY-08-07');
|
|
204
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Thermostat'), bridgedNode, powerSource], { id: 'Thermostat', number: EndpointNumber(9_01) });
|
|
205
|
+
await registerDevice(ep, 'Thermostat', 'HVAC-09-01');
|
|
206
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Thermostat'), bridgedNode, powerSource], { id: 'ThermostatHeating', number: EndpointNumber(9_01_1) });
|
|
207
|
+
ep.createDefaultHeatingThermostatClusterServer();
|
|
208
|
+
await registerDevice(ep, 'Thermostat Heating', 'HVAC-09-01-1');
|
|
209
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Thermostat'), bridgedNode, powerSource], { id: 'ThermostatCooling', number: EndpointNumber(9_01_2) });
|
|
210
|
+
ep.createDefaultCoolingThermostatClusterServer();
|
|
211
|
+
await registerDevice(ep, 'Thermostat Cooling', 'HVAC-09-01-2');
|
|
212
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Thermostat'), bridgedNode, powerSource], { id: 'ThermostatPresets', number: EndpointNumber(9_01_3) });
|
|
213
|
+
ep.createDefaultPresetsThermostatClusterServer();
|
|
214
|
+
await registerDevice(ep, 'Thermostat Presets', 'HVAC-09-01-3');
|
|
215
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Thermostat'), bridgedNode, powerSource], { id: 'ThermostatSchedules', number: EndpointNumber(9_01_4) });
|
|
216
|
+
ep.createDefaultSchedulesThermostatClusterServer();
|
|
217
|
+
await registerDevice(ep, 'Thermostat Schedules', 'HVAC-09-01-4');
|
|
218
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Thermostat'), bridgedNode, powerSource], { id: 'ThermostatSuggestions', number: EndpointNumber(9_01_5) });
|
|
219
|
+
ep.createDefaultThermostatSuggestionsClusterServer();
|
|
220
|
+
await registerDevice(ep, 'Thermostat Suggestions', 'HVAC-09-01-5');
|
|
221
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Fan'), bridgedNode, powerSource], { id: 'Fan', number: EndpointNumber(9_02) });
|
|
222
|
+
await registerDevice(ep, 'Fan OffLowMedHighAuto', 'HVAC-09-02');
|
|
223
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Fan'), bridgedNode, powerSource], { id: 'FanOnOff', number: EndpointNumber(9_02_1) });
|
|
224
|
+
ep.createOnOffFanControlClusterServer(FanControl.FanMode.High);
|
|
225
|
+
await registerDevice(ep, 'Fan OffHigh', 'HVAC-09-02-1');
|
|
226
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Fan'), bridgedNode, powerSource], { id: 'FanBase', number: EndpointNumber(9_02_2) });
|
|
227
|
+
ep.createBaseFanControlClusterServer(FanControl.FanMode.Low, undefined, 30, 30);
|
|
228
|
+
await registerDevice(ep, 'Fan OffLowMedHigh', 'HVAC-09-02-2');
|
|
229
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Fan'), bridgedNode, powerSource], { id: 'FanMultiSpeed', number: EndpointNumber(9_02_3) });
|
|
230
|
+
ep.createMultiSpeedFanControlClusterServer(FanControl.FanMode.Medium, undefined, 50, 50, 10, 5, 5);
|
|
231
|
+
await registerDevice(ep, 'Fan MultiSpeed', 'HVAC-09-02-3');
|
|
232
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('Fan'), bridgedNode, powerSource], { id: 'FanComplete', number: EndpointNumber(9_02_4) });
|
|
233
|
+
ep.createCompleteFanControlClusterServer(FanControl.FanMode.Auto, undefined, 60, 60, 10, 5, 5);
|
|
234
|
+
await registerDevice(ep, 'Fan Complete', 'HVAC-09-02-4');
|
|
235
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('AirPurifier'), bridgedNode, powerSource], {
|
|
236
|
+
id: 'AirPurifier',
|
|
237
|
+
number: EndpointNumber(9_03),
|
|
238
|
+
});
|
|
239
|
+
ep.createDefaultHepaFilterMonitoringClusterServer(85);
|
|
240
|
+
ep.createDefaultActivatedCarbonFilterMonitoringClusterServer(75);
|
|
241
|
+
ep.addChildDeviceType('AirQualitySensor', getSupportedDeviceType('AirQualitySensor'), { number: EndpointNumber(9_03_1) })
|
|
242
|
+
.createDefaultAirQualityClusterServer(AirQuality.AirQualityEnum.Good)
|
|
243
|
+
.addRequiredClusters();
|
|
244
|
+
ep.addChildDeviceType('Thermostat', getSupportedDeviceType('Thermostat'), { number: EndpointNumber(9_03_2) }).addRequiredClusters();
|
|
245
|
+
ep.addChildDeviceType('TemperatureSensor', getSupportedDeviceType('TemperatureSensor'), { number: EndpointNumber(9_03_3) })
|
|
246
|
+
.createDefaultTemperatureMeasurementClusterServer(2000, -4000, 8500)
|
|
247
|
+
.addRequiredClusters();
|
|
248
|
+
ep.addChildDeviceType('HumiditySensor', getSupportedDeviceType('HumiditySensor'), { number: EndpointNumber(9_03_4) })
|
|
249
|
+
.createDefaultRelativeHumidityMeasurementClusterServer(5000, 0, 10000)
|
|
250
|
+
.addRequiredClusters();
|
|
251
|
+
await registerDevice(ep, 'Air Purifier', 'HVAC-09-03');
|
|
252
|
+
ep = new MatterbridgeEndpoint([getSupportedDeviceType('ThermostatController'), bridgedNode, powerSource], { id: 'ThermostatController', number: EndpointNumber(9_04) });
|
|
253
|
+
await registerDevice(ep, 'Thermostat Controller', 'HVAC-09-04');
|
|
187
254
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ClosureControlServer } from '@matter/node/behaviors/closure-control';
|
|
2
|
+
import { type EndpointNumber } from '@matter/types';
|
|
2
3
|
import { ClosureControl } from '@matter/types/clusters/closure-control';
|
|
3
4
|
import { Identify } from '@matter/types/clusters/identify';
|
|
4
5
|
import type { Semtag } from '@matter/types/globals';
|
|
@@ -29,6 +30,8 @@ export interface ClosureOptions {
|
|
|
29
30
|
overallCurrentState?: ClosureControl.OverallCurrentState;
|
|
30
31
|
overallTargetState?: ClosureControl.OverallTargetState;
|
|
31
32
|
latchControlModes?: ClosureControl.LatchControlModes;
|
|
33
|
+
id?: string;
|
|
34
|
+
number?: EndpointNumber;
|
|
32
35
|
tagList?: Semtag[];
|
|
33
36
|
}
|
|
34
37
|
export declare class Closure extends MatterbridgeEndpoint {
|
package/dist/devices/closure.js
CHANGED
|
@@ -74,9 +74,10 @@ export class Closure extends MatterbridgeEndpoint {
|
|
|
74
74
|
position: ClosureControl.TargetPosition.MoveToFullyClosed,
|
|
75
75
|
latch: true,
|
|
76
76
|
speed: ThreeLevelAuto.Auto,
|
|
77
|
-
}, latchControlModes = { remoteLatching: true, remoteUnlatching: true }, tagList = [getSemtag(ClosureTag.Covering)], } = options;
|
|
77
|
+
}, latchControlModes = { remoteLatching: true, remoteUnlatching: true }, id, number, tagList = [getSemtag(ClosureTag.Covering)], } = options;
|
|
78
78
|
super(powerSourceType === 'None' ? [closure] : [closure, powerSource], {
|
|
79
|
-
id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
|
|
79
|
+
id: id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
|
|
80
|
+
number,
|
|
80
81
|
tagList,
|
|
81
82
|
});
|
|
82
83
|
this.createDefaultIdentifyClusterServer(identifyTime, identifyType);
|
package/dist/frontend.js
CHANGED
|
@@ -4,16 +4,24 @@ import path from 'node:path';
|
|
|
4
4
|
import { Diagnostic, Lifecycle, LogDestination, LogFormat as MatterLogFormat, Logger, LogLevel as MatterLogLevel } from '@matter/general';
|
|
5
5
|
import { DeviceAdvertiser, DeviceCommissioner, FabricManager } from '@matter/protocol';
|
|
6
6
|
import { getClusterNameById } from '@matter/types/cluster';
|
|
7
|
+
import { AirQuality } from '@matter/types/clusters/air-quality';
|
|
7
8
|
import { BridgedDeviceBasicInformation } from '@matter/types/clusters/bridged-device-basic-information';
|
|
9
|
+
import { ClosureControl } from '@matter/types/clusters/closure-control';
|
|
8
10
|
import { DeviceEnergyManagement } from '@matter/types/clusters/device-energy-management';
|
|
11
|
+
import { FanControl } from '@matter/types/clusters/fan-control';
|
|
12
|
+
import { OperationalState } from '@matter/types/clusters/operational-state';
|
|
9
13
|
import { PowerSource } from '@matter/types/clusters/power-source';
|
|
14
|
+
import { RvcOperationalState } from '@matter/types/clusters/rvc-operational-state';
|
|
15
|
+
import { SmokeCoAlarm } from '@matter/types/clusters/smoke-co-alarm';
|
|
10
16
|
import { SoilMeasurement } from '@matter/types/clusters/soil-measurement';
|
|
17
|
+
import { ValveConfigurationAndControl } from '@matter/types/clusters/valve-configuration-and-control';
|
|
11
18
|
import { CommissioningOptions } from '@matter/types/commissioning';
|
|
12
19
|
import { FabricIndex } from '@matter/types/datatype';
|
|
13
20
|
import { BroadcastServer } from '@matterbridge/thread/server';
|
|
14
21
|
import { MATTER_LOGGER_FILE, MATTER_STORAGE_DIR, MATTERBRIDGE_DIAGNOSTIC_FILE, MATTERBRIDGE_HISTORY_FILE, MATTERBRIDGE_LOGGER_FILE, NODE_STORAGE_DIR, plg, } from '@matterbridge/types';
|
|
15
22
|
import { isBun } from '@matterbridge/utils/bun';
|
|
16
23
|
import { getParameter, hasParameter } from '@matterbridge/utils/cli';
|
|
24
|
+
import { getEnumDescription } from '@matterbridge/utils/enum';
|
|
17
25
|
import { getErrorMessage, inspectError, logError } from '@matterbridge/utils/error';
|
|
18
26
|
import { formatBytes, formatPercent, formatUptime } from '@matterbridge/utils/format';
|
|
19
27
|
import { logModuleLoaded } from '@matterbridge/utils/loader';
|
|
@@ -1117,6 +1125,14 @@ export class Frontend extends EventEmitter {
|
|
|
1117
1125
|
attributes += `Cover position: ${attributeValue / 100}% `;
|
|
1118
1126
|
if (clusterName === 'doorLock' && attributeName === 'lockState')
|
|
1119
1127
|
attributes += `State: ${attributeValue === 1 ? 'Locked' : 'Not locked'} `;
|
|
1128
|
+
if (clusterName === 'closureControl' && attributeName === 'overallCurrentState' && attributeValue === null)
|
|
1129
|
+
attributes += `Position: unknown Latch: unknown SecureState: unknown `;
|
|
1130
|
+
if (clusterName === 'closureControl' && attributeName === 'overallCurrentState' && isValidObject(attributeValue)) {
|
|
1131
|
+
const overallCurrentState = attributeValue;
|
|
1132
|
+
attributes += `Position: ${getEnumDescription(ClosureControl.CurrentPosition, overallCurrentState.position, { fallback: 'unknown' })} `;
|
|
1133
|
+
attributes += `Latch: ${overallCurrentState.latch ?? 'unknown'} `;
|
|
1134
|
+
attributes += `SecureState: ${overallCurrentState.secureState ?? 'unknown'} `;
|
|
1135
|
+
}
|
|
1120
1136
|
if (clusterName === 'thermostat' && attributeName === 'localTemperature' && isValidNumber(attributeValue))
|
|
1121
1137
|
attributes += `Temperature: ${attributeValue / 100}°C `;
|
|
1122
1138
|
if (clusterName === 'thermostat' && attributeName === 'occupiedHeatingSetpoint' && isValidNumber(attributeValue))
|
|
@@ -1132,13 +1148,14 @@ export class Frontend extends EventEmitter {
|
|
|
1132
1148
|
if (supportedMode)
|
|
1133
1149
|
attributes += `Mode: ${supportedMode.label} `;
|
|
1134
1150
|
}
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1151
|
+
if (clusterName === 'operationalState' && attributeName === 'operationalState')
|
|
1152
|
+
attributes += `OpState: ${getEnumDescription(OperationalState.OperationalStateEnum, attributeValue)} `;
|
|
1153
|
+
if (clusterName === 'rvcOperationalState' && attributeName === 'operationalState')
|
|
1154
|
+
attributes += `OpState: ${getEnumDescription(RvcOperationalState.OperationalState, attributeValue)} `;
|
|
1138
1155
|
if (clusterName === 'pumpConfigurationAndControl' && attributeName === 'operationMode')
|
|
1139
1156
|
attributes += `Mode: ${attributeValue} `;
|
|
1140
1157
|
if (clusterName === 'valveConfigurationAndControl' && attributeName === 'currentState')
|
|
1141
|
-
attributes += `State: ${attributeValue} `;
|
|
1158
|
+
attributes += `State: ${getEnumDescription(ValveConfigurationAndControl.ValveState, attributeValue, { fallback: 'unknown' })} `;
|
|
1142
1159
|
if (clusterName === 'levelControl' && attributeName === 'currentLevel')
|
|
1143
1160
|
attributes += `Level: ${attributeValue} `;
|
|
1144
1161
|
if (clusterName === 'colorControl' && attributeName === 'colorMode' && isValidNumber(attributeValue, 0, 2))
|
|
@@ -1158,15 +1175,25 @@ export class Frontend extends EventEmitter {
|
|
|
1158
1175
|
if (clusterName === 'booleanStateConfiguration' && attributeName === 'alarmsActive' && isValidObject(attributeValue))
|
|
1159
1176
|
attributes += `Active alarms: ${stringify(attributeValue)} `;
|
|
1160
1177
|
if (clusterName === 'smokeCoAlarm' && attributeName === 'smokeState')
|
|
1161
|
-
attributes += `Smoke: ${attributeValue} `;
|
|
1178
|
+
attributes += `Smoke: ${getEnumDescription(SmokeCoAlarm.AlarmState, attributeValue)} `;
|
|
1162
1179
|
if (clusterName === 'smokeCoAlarm' && attributeName === 'coState')
|
|
1163
|
-
attributes += `Co: ${attributeValue} `;
|
|
1180
|
+
attributes += `Co: ${getEnumDescription(SmokeCoAlarm.AlarmState, attributeValue)} `;
|
|
1164
1181
|
if (clusterName === 'fanControl' && attributeName === 'fanMode')
|
|
1165
|
-
attributes += `Mode: ${attributeValue} `;
|
|
1182
|
+
attributes += `Mode: ${getEnumDescription(FanControl.FanMode, attributeValue)} `;
|
|
1166
1183
|
if (clusterName === 'fanControl' && attributeName === 'percentCurrent')
|
|
1167
|
-
attributes += `Percent: ${attributeValue} `;
|
|
1184
|
+
attributes += `Percent: ${attributeValue}% `;
|
|
1168
1185
|
if (clusterName === 'fanControl' && attributeName === 'speedCurrent')
|
|
1169
1186
|
attributes += `Speed: ${attributeValue} `;
|
|
1187
|
+
if (clusterName === 'fanControl' && attributeName === 'rockSetting' && isValidObject(attributeValue))
|
|
1188
|
+
attributes += `Rock: ${stringify(attributeValue)} `;
|
|
1189
|
+
if (clusterName === 'fanControl' && attributeName === 'windSetting' && isValidObject(attributeValue))
|
|
1190
|
+
attributes += `Wind: ${stringify(attributeValue)} `;
|
|
1191
|
+
if (clusterName === 'fanControl' && attributeName === 'airflowDirection')
|
|
1192
|
+
attributes += `Direction: ${getEnumDescription(FanControl.AirflowDirection, attributeValue)} `;
|
|
1193
|
+
if (clusterName === 'hepaFilterMonitoring' && attributeName === 'condition')
|
|
1194
|
+
attributes += `Hepa filter: ${attributeValue}% `;
|
|
1195
|
+
if (clusterName === 'activatedCarbonFilterMonitoring' && attributeName === 'condition')
|
|
1196
|
+
attributes += `Carbon filter: ${attributeValue}% `;
|
|
1170
1197
|
if (clusterName === 'occupancySensing' && attributeName === 'occupancy' && isValidObject(attributeValue, 1))
|
|
1171
1198
|
attributes += `Occupancy: ${attributeValue.occupied} `;
|
|
1172
1199
|
if (clusterName === 'illuminanceMeasurement' && attributeName === 'measuredValue') {
|
|
@@ -1176,47 +1203,27 @@ export class Frontend extends EventEmitter {
|
|
|
1176
1203
|
attributes += `Illuminance: ${Math.round(Math.max(Math.pow(10, attributeValue / 10000), 0))} lx`;
|
|
1177
1204
|
}
|
|
1178
1205
|
if (clusterName === 'airQuality' && attributeName === 'airQuality')
|
|
1179
|
-
attributes += `Air quality: ${attributeValue} `;
|
|
1206
|
+
attributes += `Air quality: ${getEnumDescription(AirQuality.AirQualityEnum, attributeValue)} `;
|
|
1180
1207
|
if (clusterName === 'totalVolatileOrganicCompoundsConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
1181
|
-
|
|
1208
|
+
appendMeasurement('Voc', getMeasurementText(attributeValue, 1, ''));
|
|
1182
1209
|
if (clusterName === 'pm1ConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
1183
|
-
|
|
1210
|
+
appendMeasurement('Pm1', getMeasurementText(attributeValue, 1, ''));
|
|
1184
1211
|
if (clusterName === 'pm25ConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
1185
|
-
|
|
1212
|
+
appendMeasurement('Pm2.5', getMeasurementText(attributeValue, 1, ''));
|
|
1186
1213
|
if (clusterName === 'pm10ConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
1187
|
-
|
|
1214
|
+
appendMeasurement('Pm10', getMeasurementText(attributeValue, 1, ''));
|
|
1188
1215
|
if (clusterName === 'formaldehydeConcentrationMeasurement' && attributeName === 'measuredValue')
|
|
1189
|
-
|
|
1190
|
-
if (clusterName === 'temperatureMeasurement' && attributeName === 'measuredValue')
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
if (clusterName === '
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
attributes += `Humidity: ${attributeValue / 100}% `;
|
|
1201
|
-
}
|
|
1202
|
-
if (clusterName === 'pressureMeasurement' && attributeName === 'measuredValue') {
|
|
1203
|
-
if (attributeValue === null)
|
|
1204
|
-
attributes += `Pressure: unknown `;
|
|
1205
|
-
else if (isValidNumber(attributeValue))
|
|
1206
|
-
attributes += `Pressure: ${attributeValue} hPa `;
|
|
1207
|
-
}
|
|
1208
|
-
if (clusterName === 'flowMeasurement' && attributeName === 'measuredValue') {
|
|
1209
|
-
if (attributeValue === null)
|
|
1210
|
-
attributes += `Flow: unknown `;
|
|
1211
|
-
else if (isValidNumber(attributeValue))
|
|
1212
|
-
attributes += `Flow: ${attributeValue / 10} m³/h `;
|
|
1213
|
-
}
|
|
1214
|
-
if (clusterId === SoilMeasurement.id && attributeName === 'soilMoistureMeasuredValue') {
|
|
1215
|
-
if (attributeValue === null)
|
|
1216
|
-
attributes += `Soil moisture: unknown `;
|
|
1217
|
-
else if (isValidNumber(attributeValue))
|
|
1218
|
-
attributes += `Soil moisture: ${attributeValue}% `;
|
|
1219
|
-
}
|
|
1216
|
+
appendMeasurement('CH₂O', getMeasurementText(attributeValue, 1, ''));
|
|
1217
|
+
if (clusterName === 'temperatureMeasurement' && attributeName === 'measuredValue')
|
|
1218
|
+
appendMeasurement('Temperature', getMeasurementText(attributeValue, 100, ' °C'));
|
|
1219
|
+
if (clusterName === 'relativeHumidityMeasurement' && attributeName === 'measuredValue')
|
|
1220
|
+
appendMeasurement('Humidity', getMeasurementText(attributeValue, 100, '%'));
|
|
1221
|
+
if (clusterName === 'pressureMeasurement' && attributeName === 'measuredValue')
|
|
1222
|
+
appendMeasurement('Pressure', getMeasurementText(attributeValue, 1, ' hPa'));
|
|
1223
|
+
if (clusterName === 'flowMeasurement' && attributeName === 'measuredValue')
|
|
1224
|
+
appendMeasurement('Flow', getMeasurementText(attributeValue, 10, ' m³/h'));
|
|
1225
|
+
if (clusterId === SoilMeasurement.id && attributeName === 'soilMoistureMeasuredValue')
|
|
1226
|
+
appendMeasurement('Soil moisture', getMeasurementText(attributeValue, 1, '%'));
|
|
1220
1227
|
if (clusterName === 'electricalPowerMeasurement' && attributeName === 'voltage')
|
|
1221
1228
|
appendMeasurement('Voltage', getMeasurementText(attributeValue, 1_000, 'V'));
|
|
1222
1229
|
if (clusterName === 'electricalPowerMeasurement' && attributeName === 'activeCurrent')
|
package/dist/matterNode.js
CHANGED
|
@@ -864,6 +864,7 @@ export class MatterNode extends EventEmitter {
|
|
|
864
864
|
{ cluster: 'FanControl', attribute: 'fanMode' },
|
|
865
865
|
{ cluster: 'FanControl', attribute: 'fanModeSequence' },
|
|
866
866
|
{ cluster: 'FanControl', attribute: 'percentSetting' },
|
|
867
|
+
{ cluster: 'FanControl', attribute: 'percentCurrent' },
|
|
867
868
|
{ cluster: 'ModeSelect', attribute: 'currentMode' },
|
|
868
869
|
{ cluster: 'RvcRunMode', attribute: 'currentMode' },
|
|
869
870
|
{ cluster: 'RvcCleanMode', attribute: 'currentMode' },
|
package/dist/matterbridge.js
CHANGED
|
@@ -1569,12 +1569,18 @@ export class Matterbridge extends EventEmitter {
|
|
|
1569
1569
|
this.aggregatorNode = await this.createAggregatorNode(this.matterbridgeContext);
|
|
1570
1570
|
await this.serverNode.add(this.aggregatorNode);
|
|
1571
1571
|
await addVirtualDevices(this, this.aggregatorNode);
|
|
1572
|
-
if (process.env.
|
|
1572
|
+
if (process.env.MATTERBRIDGE_DEMO_DEVICES || hasParameter('demo-devices')) {
|
|
1573
|
+
this.log.warn(' *********************************************************************************');
|
|
1574
|
+
this.log.warn(' * MATTERBRIDGE_DEMO_DEVICES environment variable is set. Creating demo devices. *');
|
|
1575
|
+
this.log.warn(' *********************************************************************************');
|
|
1576
|
+
const { createDemoDevices } = await import('./demoDevices.js');
|
|
1577
|
+
await createDemoDevices(this);
|
|
1578
|
+
}
|
|
1579
|
+
if (process.env.MATTERBRIDGE_CHIP_TEST && fs.existsSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'chipTests.js'))) {
|
|
1580
|
+
this.log.warn(' ***********************************************************************************');
|
|
1581
|
+
this.log.warn(' * MATTERBRIDGE_CHIP_TEST environment variable is set. Running chip test app pipe. *');
|
|
1582
|
+
this.log.warn(' ***********************************************************************************');
|
|
1573
1583
|
const { createChipTestAppPipe } = await import('./chipTests.js');
|
|
1574
|
-
if (process.env.MATTERBRIDGE_CHIP_TEST_DEVICES) {
|
|
1575
|
-
const { createChipTestDevices } = await import('./chipTestDevices.js');
|
|
1576
|
-
await createChipTestDevices(this);
|
|
1577
|
-
}
|
|
1578
1584
|
createChipTestAppPipe(this);
|
|
1579
1585
|
}
|
|
1580
1586
|
await this.startPlugins(false, true);
|
|
@@ -1887,7 +1893,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
1887
1893
|
discriminator = PaseClient.generateRandomDiscriminator(this.environment.get(Crypto));
|
|
1888
1894
|
}
|
|
1889
1895
|
let rootEndpoint = ServerNode.RootEndpoint.with(PowerSourceServer.with(PowerSource.Feature.Wired));
|
|
1890
|
-
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
1896
|
+
if (process.env.MATTERBRIDGE_CHIP_TEST && fs.existsSync(path.join(path.dirname(fileURLToPath(import.meta.url)), 'chipTests.js'))) {
|
|
1897
|
+
this.log.warn(' ****************************************************************************************');
|
|
1898
|
+
this.log.warn(' * MATTERBRIDGE_CHIP_TEST environment variable is set. Running TestEventTrigger server. *');
|
|
1899
|
+
this.log.warn(' ****************************************************************************************');
|
|
1891
1900
|
const { MatterbridgeGeneralDiagnosticsServer } = await import('./chipTests.js');
|
|
1892
1901
|
rootEndpoint = rootEndpoint.with(MatterbridgeGeneralDiagnosticsServer);
|
|
1893
1902
|
}
|
|
@@ -2291,6 +2300,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
2291
2300
|
{ cluster: 'FanControl', attribute: 'fanMode' },
|
|
2292
2301
|
{ cluster: 'FanControl', attribute: 'fanModeSequence' },
|
|
2293
2302
|
{ cluster: 'FanControl', attribute: 'percentSetting' },
|
|
2303
|
+
{ cluster: 'FanControl', attribute: 'percentCurrent' },
|
|
2294
2304
|
{ cluster: 'ModeSelect', attribute: 'currentMode' },
|
|
2295
2305
|
{ cluster: 'RvcRunMode', attribute: 'currentMode' },
|
|
2296
2306
|
{ cluster: 'RvcCleanMode', attribute: 'currentMode' },
|
|
@@ -9,6 +9,7 @@ import type { DeviceEnergyManagementMode } from '@matter/types/clusters/device-e
|
|
|
9
9
|
import { DoorLock } from '@matter/types/clusters/door-lock';
|
|
10
10
|
import { FanControl } from '@matter/types/clusters/fan-control';
|
|
11
11
|
import { Identify } from '@matter/types/clusters/identify';
|
|
12
|
+
import type { IlluminanceMeasurement } from '@matter/types/clusters/illuminance-measurement';
|
|
12
13
|
import type { ModeSelect } from '@matter/types/clusters/mode-select';
|
|
13
14
|
import { OnOff } from '@matter/types/clusters/on-off';
|
|
14
15
|
import { OperationalState } from '@matter/types/clusters/operational-state';
|
|
@@ -217,11 +218,11 @@ export declare class MatterbridgeEndpoint extends Endpoint {
|
|
|
217
218
|
createDefaultOperationalStateClusterServer(operationalState?: OperationalState.OperationalStateEnum): this;
|
|
218
219
|
createDefaultBooleanStateClusterServer(contact?: boolean): this;
|
|
219
220
|
createDefaultBooleanStateConfigurationClusterServer(sensorFault?: boolean, currentSensitivityLevel?: number, supportedSensitivityLevels?: number, defaultSensitivityLevel?: number): this;
|
|
220
|
-
createDefaultTemperatureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): this;
|
|
221
|
-
createDefaultRelativeHumidityMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): this;
|
|
222
|
-
createDefaultPressureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): this;
|
|
223
|
-
createDefaultIlluminanceMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): this;
|
|
224
|
-
createDefaultFlowMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): this;
|
|
221
|
+
createDefaultTemperatureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): this;
|
|
222
|
+
createDefaultRelativeHumidityMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): this;
|
|
223
|
+
createDefaultPressureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): this;
|
|
224
|
+
createDefaultIlluminanceMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number, lightSensorType?: IlluminanceMeasurement.LightSensorType | null): this;
|
|
225
|
+
createDefaultFlowMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): this;
|
|
225
226
|
createDefaultOccupancySensingClusterServer(occupied?: boolean, holdTime?: number, holdTimeMin?: number, holdTimeMax?: number): this;
|
|
226
227
|
createDefaultSoilMeasurementClusterServer(soilMoistureMeasuredValue?: number | null, soilMoistureMeasurementLimits?: MeasurementAccuracy): this;
|
|
227
228
|
createDefaultAirQualityClusterServer(airQuality?: AirQuality.AirQualityEnum): this;
|
|
@@ -1175,8 +1175,8 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
1175
1175
|
this.behaviors.require(FanControlServer, {
|
|
1176
1176
|
fanMode,
|
|
1177
1177
|
fanModeSequence: FanControl.FanModeSequence.OffHigh,
|
|
1178
|
-
percentSetting: 0,
|
|
1179
|
-
percentCurrent: 0,
|
|
1178
|
+
percentSetting: fanMode === FanControl.FanMode.Off ? 0 : 100,
|
|
1179
|
+
percentCurrent: fanMode === FanControl.FanMode.Off ? 0 : 100,
|
|
1180
1180
|
});
|
|
1181
1181
|
return this;
|
|
1182
1182
|
}
|
|
@@ -1487,7 +1487,7 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
1487
1487
|
});
|
|
1488
1488
|
return this;
|
|
1489
1489
|
}
|
|
1490
|
-
createDefaultBooleanStateConfigurationClusterServer(sensorFault = false, currentSensitivityLevel =
|
|
1490
|
+
createDefaultBooleanStateConfigurationClusterServer(sensorFault = false, currentSensitivityLevel = 1, supportedSensitivityLevels = 3, defaultSensitivityLevel = 1) {
|
|
1491
1491
|
this.behaviors.require(MatterbridgeBooleanStateConfigurationServer.with(BooleanStateConfiguration.Feature.Visual, BooleanStateConfiguration.Feature.Audible, BooleanStateConfiguration.Feature.AlarmSuppress, BooleanStateConfiguration.Feature.SensitivityLevel, BooleanStateConfiguration.Feature.FaultEvents).enable({
|
|
1492
1492
|
events: { alarmsStateChanged: true, sensorFault: true },
|
|
1493
1493
|
}), {
|
|
@@ -1502,24 +1502,24 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
1502
1502
|
});
|
|
1503
1503
|
return this;
|
|
1504
1504
|
}
|
|
1505
|
-
createDefaultTemperatureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1506
|
-
this.behaviors.require(TemperatureMeasurementServer, getDefaultTemperatureMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue));
|
|
1505
|
+
createDefaultTemperatureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1506
|
+
this.behaviors.require(TemperatureMeasurementServer, getDefaultTemperatureMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue, tolerance));
|
|
1507
1507
|
return this;
|
|
1508
1508
|
}
|
|
1509
|
-
createDefaultRelativeHumidityMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1510
|
-
this.behaviors.require(RelativeHumidityMeasurementServer, getDefaultRelativeHumidityMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue));
|
|
1509
|
+
createDefaultRelativeHumidityMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1510
|
+
this.behaviors.require(RelativeHumidityMeasurementServer, getDefaultRelativeHumidityMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue, tolerance));
|
|
1511
1511
|
return this;
|
|
1512
1512
|
}
|
|
1513
|
-
createDefaultPressureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1514
|
-
this.behaviors.require(PressureMeasurementServer, getDefaultPressureMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue));
|
|
1513
|
+
createDefaultPressureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1514
|
+
this.behaviors.require(PressureMeasurementServer, getDefaultPressureMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue, tolerance));
|
|
1515
1515
|
return this;
|
|
1516
1516
|
}
|
|
1517
|
-
createDefaultIlluminanceMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1518
|
-
this.behaviors.require(IlluminanceMeasurementServer, getDefaultIlluminanceMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue));
|
|
1517
|
+
createDefaultIlluminanceMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0, lightSensorType = null) {
|
|
1518
|
+
this.behaviors.require(IlluminanceMeasurementServer, getDefaultIlluminanceMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue, tolerance, lightSensorType));
|
|
1519
1519
|
return this;
|
|
1520
1520
|
}
|
|
1521
|
-
createDefaultFlowMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1522
|
-
this.behaviors.require(FlowMeasurementServer, getDefaultFlowMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue));
|
|
1521
|
+
createDefaultFlowMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1522
|
+
this.behaviors.require(FlowMeasurementServer, getDefaultFlowMeasurementClusterServer(measuredValue, minMeasuredValue, maxMeasuredValue, tolerance));
|
|
1523
1523
|
return this;
|
|
1524
1524
|
}
|
|
1525
1525
|
createDefaultOccupancySensingClusterServer(occupied = false, holdTime = 30, holdTimeMin = 1, holdTimeMax = 300) {
|
|
@@ -143,11 +143,11 @@ export declare function getDefaultDeviceEnergyManagementModeClusterServer(curren
|
|
|
143
143
|
onOff: false;
|
|
144
144
|
}>, typeof MatterbridgeDeviceEnergyManagementModeServer>>;
|
|
145
145
|
export declare function getDefaultOperationalStateClusterServer(operationalState?: OperationalState.OperationalStateEnum): Partial<import("@matter/node").ClusterState.Type<ClusterType.WithSupportedFeatures<OperationalState, {}>, typeof MatterbridgeOperationalStateServer>>;
|
|
146
|
-
export declare function getDefaultTemperatureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): Partial<import("@matter/node").ClusterState.Type<TemperatureMeasurement, typeof ClusterBehavior>>;
|
|
147
|
-
export declare function getDefaultRelativeHumidityMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): Partial<import("@matter/node").ClusterState.Type<RelativeHumidityMeasurement, typeof ClusterBehavior>>;
|
|
148
|
-
export declare function getDefaultPressureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): Partial<import("@matter/node").ClusterState.Type<PressureMeasurement, typeof ClusterBehavior>>;
|
|
149
|
-
export declare function getDefaultIlluminanceMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): Partial<import("@matter/node").ClusterState.Type<IlluminanceMeasurement, typeof ClusterBehavior>>;
|
|
150
|
-
export declare function getDefaultFlowMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null): Partial<import("@matter/node").ClusterState.Type<FlowMeasurement, typeof ClusterBehavior>>;
|
|
146
|
+
export declare function getDefaultTemperatureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): Partial<import("@matter/node").ClusterState.Type<TemperatureMeasurement, typeof ClusterBehavior>>;
|
|
147
|
+
export declare function getDefaultRelativeHumidityMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): Partial<import("@matter/node").ClusterState.Type<RelativeHumidityMeasurement, typeof ClusterBehavior>>;
|
|
148
|
+
export declare function getDefaultPressureMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): Partial<import("@matter/node").ClusterState.Type<PressureMeasurement, typeof ClusterBehavior>>;
|
|
149
|
+
export declare function getDefaultIlluminanceMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number, lightSensorType?: IlluminanceMeasurement.LightSensorType | null): Partial<import("@matter/node").ClusterState.Type<IlluminanceMeasurement, typeof ClusterBehavior>>;
|
|
150
|
+
export declare function getDefaultFlowMeasurementClusterServer(measuredValue?: number | null, minMeasuredValue?: number | null, maxMeasuredValue?: number | null, tolerance?: number): Partial<import("@matter/node").ClusterState.Type<FlowMeasurement, typeof ClusterBehavior>>;
|
|
151
151
|
export declare function getDefaultOccupancySensingClusterServer(occupied?: boolean, holdTime?: number, holdTimeMin?: number, holdTimeMax?: number): Partial<import("@matter/node").ClusterState.Type<ClusterType.WithSupportedFeatures<OccupancySensing, {
|
|
152
152
|
activeInfrared: false;
|
|
153
153
|
occupancyEvent: false;
|
|
@@ -1055,44 +1055,45 @@ export function getDefaultOperationalStateClusterServer(operationalState = Opera
|
|
|
1055
1055
|
operationalError: { errorStateId: OperationalState.ErrorState.NoError, errorStateDetails: 'Fully operational' },
|
|
1056
1056
|
});
|
|
1057
1057
|
}
|
|
1058
|
-
export function getDefaultTemperatureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1058
|
+
export function getDefaultTemperatureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1059
1059
|
return optionsFor(TemperatureMeasurementServer, {
|
|
1060
1060
|
measuredValue,
|
|
1061
1061
|
minMeasuredValue,
|
|
1062
1062
|
maxMeasuredValue,
|
|
1063
|
-
tolerance
|
|
1063
|
+
tolerance,
|
|
1064
1064
|
});
|
|
1065
1065
|
}
|
|
1066
|
-
export function getDefaultRelativeHumidityMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1066
|
+
export function getDefaultRelativeHumidityMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1067
1067
|
return optionsFor(RelativeHumidityMeasurementServer, {
|
|
1068
1068
|
measuredValue,
|
|
1069
1069
|
minMeasuredValue,
|
|
1070
1070
|
maxMeasuredValue,
|
|
1071
|
-
tolerance
|
|
1071
|
+
tolerance,
|
|
1072
1072
|
});
|
|
1073
1073
|
}
|
|
1074
|
-
export function getDefaultPressureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1074
|
+
export function getDefaultPressureMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1075
1075
|
return optionsFor(PressureMeasurementServer, {
|
|
1076
1076
|
measuredValue,
|
|
1077
1077
|
minMeasuredValue,
|
|
1078
1078
|
maxMeasuredValue,
|
|
1079
|
-
tolerance
|
|
1079
|
+
tolerance,
|
|
1080
1080
|
});
|
|
1081
1081
|
}
|
|
1082
|
-
export function getDefaultIlluminanceMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1082
|
+
export function getDefaultIlluminanceMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0, lightSensorType = null) {
|
|
1083
1083
|
return optionsFor(IlluminanceMeasurementServer, {
|
|
1084
1084
|
measuredValue,
|
|
1085
1085
|
minMeasuredValue,
|
|
1086
1086
|
maxMeasuredValue,
|
|
1087
|
-
tolerance
|
|
1087
|
+
tolerance,
|
|
1088
|
+
lightSensorType,
|
|
1088
1089
|
});
|
|
1089
1090
|
}
|
|
1090
|
-
export function getDefaultFlowMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null) {
|
|
1091
|
+
export function getDefaultFlowMeasurementClusterServer(measuredValue = null, minMeasuredValue = null, maxMeasuredValue = null, tolerance = 0) {
|
|
1091
1092
|
return optionsFor(FlowMeasurementServer, {
|
|
1092
1093
|
measuredValue,
|
|
1093
1094
|
minMeasuredValue,
|
|
1094
1095
|
maxMeasuredValue,
|
|
1095
|
-
tolerance
|
|
1096
|
+
tolerance,
|
|
1096
1097
|
});
|
|
1097
1098
|
}
|
|
1098
1099
|
export function getDefaultOccupancySensingClusterServer(occupied = false, holdTime = 30, holdTimeMin = 1, holdTimeMax = 300) {
|
package/dist/pluginManager.js
CHANGED
|
@@ -428,7 +428,7 @@ export class PluginManager extends EventEmitter {
|
|
|
428
428
|
}
|
|
429
429
|
async loadFromStorage() {
|
|
430
430
|
if (!this.matterbridge.nodeContext) {
|
|
431
|
-
throw new Error('loadFromStorage: node context is not available.');
|
|
431
|
+
throw new Error('PluginManager.loadFromStorage: node context is not available.');
|
|
432
432
|
}
|
|
433
433
|
const pluginsArray = await this.matterbridge.nodeContext.get('plugins', []);
|
|
434
434
|
for (const plugin of pluginsArray)
|
|
@@ -438,10 +438,12 @@ export class PluginManager extends EventEmitter {
|
|
|
438
438
|
}
|
|
439
439
|
async saveToStorage() {
|
|
440
440
|
if (!this.matterbridge.nodeContext) {
|
|
441
|
-
throw new Error('
|
|
441
|
+
throw new Error('PluginManager.saveToStorage: node context is not available.');
|
|
442
442
|
}
|
|
443
443
|
const plugins = [];
|
|
444
444
|
for (const plugin of this.array()) {
|
|
445
|
+
if (process.env.MATTERBRIDGE_DEMO_DEVICES && plugin.name === 'matterbridge-demo-devices')
|
|
446
|
+
continue;
|
|
445
447
|
plugins.push({
|
|
446
448
|
name: plugin.name,
|
|
447
449
|
path: plugin.path,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matterbridge/core",
|
|
3
|
-
"version": "3.10.6-dev-
|
|
3
|
+
"version": "3.10.6-dev-20260820-36b52be",
|
|
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.6-dev-
|
|
136
|
-
"@matterbridge/thread": "3.10.6-dev-
|
|
137
|
-
"@matterbridge/types": "3.10.6-dev-
|
|
138
|
-
"@matterbridge/utils": "3.10.6-dev-
|
|
135
|
+
"@matterbridge/dgram": "3.10.6-dev-20260820-36b52be",
|
|
136
|
+
"@matterbridge/thread": "3.10.6-dev-20260820-36b52be",
|
|
137
|
+
"@matterbridge/types": "3.10.6-dev-20260820-36b52be",
|
|
138
|
+
"@matterbridge/utils": "3.10.6-dev-20260820-36b52be",
|
|
139
139
|
"escape-html": "1.0.3",
|
|
140
140
|
"express": "5.2.1",
|
|
141
141
|
"express-rate-limit": "8.6.2",
|