@matterbridge/core 3.10.10-dev-20260912-2c1c047 → 3.10.10-dev-20260914-784e019
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/cameraAvSettingsUserLevelManagementServer.d.ts +1 -0
- package/dist/behaviors/cameraAvSettingsUserLevelManagementServer.js +2 -3
- package/dist/behaviors/cameraAvStreamManagementServer.d.ts +1 -0
- package/dist/behaviors/cameraAvStreamManagementServer.js +11 -12
- package/dist/behaviors/chimeServer.d.ts +2 -1
- package/dist/behaviors/chimeServer.js +2 -2
- package/dist/behaviors/colorControlServer.d.ts +2 -0
- package/dist/behaviors/colorControlServer.js +18 -0
- package/dist/behaviors/levelControlServer.d.ts +3 -1
- package/dist/behaviors/levelControlServer.js +9 -0
- package/dist/behaviors/onOffServer.d.ts +2 -0
- package/dist/behaviors/onOffServer.js +6 -0
- package/dist/behaviors/webRtcTransportProviderServer.d.ts +2 -1
- package/dist/behaviors/webRtcTransportProviderServer.js +8 -8
- package/dist/behaviors/webRtcTransportRequestorServer.d.ts +2 -1
- package/dist/behaviors/webRtcTransportRequestorServer.js +5 -5
- package/dist/behaviors/weriftSession.d.ts +2 -0
- package/dist/behaviors/weriftSession.js +25 -1
- package/dist/demoDevices.js +64 -0
- package/dist/devices/camera/export.d.ts +9 -0
- package/dist/devices/camera/export.js +9 -0
- package/dist/devices/cameraController.d.ts +8 -0
- package/dist/devices/cameraController.js +35 -0
- package/dist/devices/floodlightCamera.d.ts +4 -2
- package/dist/devices/floodlightCamera.js +7 -6
- package/dist/devices/videoDoorbell.d.ts +4 -2
- package/dist/devices/videoDoorbell.js +7 -6
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.js +26 -0
- package/dist/matterbridge.js +9 -20
- package/dist/matterbridgeEndpoint.d.ts +5 -1
- package/dist/matterbridgeEndpoint.js +9 -4
- package/dist/matterbridgeEndpointHelpers.d.ts +1 -1
- package/dist/matterbridgeEndpointHelpers.js +0 -5
- package/dist/matterbridgePlatform.js +1 -1
- package/package.json +9 -5
|
@@ -9,6 +9,7 @@ declare const MatterbridgeCameraAvSettingsUserLevelManagementServer_base: import
|
|
|
9
9
|
mechanicalZoom: true;
|
|
10
10
|
}>, import("@matter/types").ClusterType.Concrete, new () => {}, "cameraAvSettingsUserLevelManagement">;
|
|
11
11
|
export declare class MatterbridgeCameraAvSettingsUserLevelManagementServer extends MatterbridgeCameraAvSettingsUserLevelManagementServer_base {
|
|
12
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
12
13
|
mptzSetPosition(request: CameraAvSettingsUserLevelManagement.MptzSetPositionRequest): void;
|
|
13
14
|
mptzRelativeMove(request: CameraAvSettingsUserLevelManagement.MptzRelativeMoveRequest): void;
|
|
14
15
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { CameraAvSettingsUserLevelManagementServer } from '@matter/node/behaviors/camera-av-settings-user-level-management';
|
|
2
2
|
import { Status, StatusResponseError } from '@matter/types';
|
|
3
3
|
import { CameraAvSettingsUserLevelManagement } from '@matter/types/clusters/camera-av-settings-user-level-management';
|
|
4
|
-
import { emitCommand } from '../matterbridgeEndpointHelpers.js';
|
|
5
4
|
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
6
5
|
function clamp(value, min, max) {
|
|
7
6
|
return Math.min(Math.max(value, min), max);
|
|
@@ -28,7 +27,7 @@ export class MatterbridgeCameraAvSettingsUserLevelManagementServer extends Camer
|
|
|
28
27
|
zoom: zoom ?? this.state.mptzPosition.zoom,
|
|
29
28
|
};
|
|
30
29
|
device.log.info(`MatterbridgeCameraAvSettingsUserLevelManagementServer: set mechanical PTZ position to pan ${this.state.mptzPosition.pan}°, tilt ${this.state.mptzPosition.tilt}°, zoom ${this.state.mptzPosition.zoom} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
31
|
-
|
|
30
|
+
this.endpoint.emitCommand(CameraAvSettingsUserLevelManagement, 'mptzSetPosition', request, this.context);
|
|
32
31
|
}
|
|
33
32
|
mptzRelativeMove(request) {
|
|
34
33
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -41,7 +40,7 @@ export class MatterbridgeCameraAvSettingsUserLevelManagementServer extends Camer
|
|
|
41
40
|
const zoom = request.zoomDelta === undefined ? current.zoom : clamp((current.zoom ?? 1) + request.zoomDelta, 1, this.state.zoomMax);
|
|
42
41
|
this.state.mptzPosition = { pan, tilt, zoom };
|
|
43
42
|
device.log.info(`MatterbridgeCameraAvSettingsUserLevelManagementServer: moved mechanical PTZ position by pan ${request.panDelta ?? 0}°, tilt ${request.tiltDelta ?? 0}°, zoom ${request.zoomDelta ?? 0} to pan ${pan}°, tilt ${tilt}°, zoom ${zoom} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
44
|
-
|
|
43
|
+
this.endpoint.emitCommand(CameraAvSettingsUserLevelManagement, 'mptzRelativeMove', request, this.context);
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
export function createDefaultCameraAvSettingsUserLevelManagementClusterServer(endpoint, options) {
|
|
@@ -23,6 +23,7 @@ declare const MatterbridgeCameraAvStreamManagementServer_base: import("@matter/n
|
|
|
23
23
|
}>, import("@matter/types").ClusterType.Concrete, new () => {}, "cameraAvStreamManagement">;
|
|
24
24
|
export declare class MatterbridgeCameraAvStreamManagementServer extends MatterbridgeCameraAvStreamManagementServer_base {
|
|
25
25
|
#private;
|
|
26
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
26
27
|
initialize(): void;
|
|
27
28
|
setStreamPriorities(request: CameraAvStreamManagement.SetStreamPrioritiesRequest): void;
|
|
28
29
|
videoStreamAllocate(request: CameraAvStreamManagement.VideoStreamAllocateRequest): CameraAvStreamManagement.VideoStreamAllocateResponse;
|
|
@@ -2,7 +2,6 @@ import { readFileSync } from 'node:fs';
|
|
|
2
2
|
import { CameraAvStreamManagementServer } from '@matter/node/behaviors/camera-av-stream-management';
|
|
3
3
|
import { Status, StatusResponseError, StreamUsage, ThreeLevelAuto } from '@matter/types';
|
|
4
4
|
import { CameraAvStreamManagement } from '@matter/types/clusters/camera-av-stream-management';
|
|
5
|
-
import { emitCommand } from '../matterbridgeEndpointHelpers.js';
|
|
6
5
|
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
7
6
|
const DEFAULT_CAMERA_COLOR_TEST_RESOLUTION = '640x480';
|
|
8
7
|
const AUDIO_STREAM_BIT_DEPTHS = [8, 16, 24, 32];
|
|
@@ -112,7 +111,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
112
111
|
}
|
|
113
112
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: setting stream priorities to [${request.streamPriorities.join(', ')}] (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
114
113
|
this.state.streamUsagePriorities = request.streamPriorities;
|
|
115
|
-
|
|
114
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'setStreamPriorities', request, this.context);
|
|
116
115
|
}
|
|
117
116
|
videoStreamAllocate(request) {
|
|
118
117
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -153,7 +152,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
153
152
|
stream.keyFrameInterval === request.keyFrameInterval);
|
|
154
153
|
if (existingStream) {
|
|
155
154
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: reused video stream ${existingStream.videoStreamId} for usage ${request.streamUsage} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
156
|
-
|
|
155
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'videoStreamAllocate', request, this.context);
|
|
157
156
|
return { videoStreamId: existingStream.videoStreamId };
|
|
158
157
|
}
|
|
159
158
|
if (this.state.allocatedVideoStreams.length >= this.state.maxConcurrentEncoders) {
|
|
@@ -182,7 +181,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
182
181
|
},
|
|
183
182
|
];
|
|
184
183
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: allocated video stream ${videoStreamId} for usage ${request.streamUsage} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
185
|
-
|
|
184
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'videoStreamAllocate', request, this.context);
|
|
186
185
|
return { videoStreamId };
|
|
187
186
|
}
|
|
188
187
|
videoStreamDeallocate(request) {
|
|
@@ -192,7 +191,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
192
191
|
}
|
|
193
192
|
this.state.allocatedVideoStreams = this.state.allocatedVideoStreams.filter((stream) => stream.videoStreamId !== request.videoStreamId);
|
|
194
193
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: deallocated video stream ${request.videoStreamId} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
195
|
-
|
|
194
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'videoStreamDeallocate', request, this.context);
|
|
196
195
|
}
|
|
197
196
|
audioStreamAllocate(request) {
|
|
198
197
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -224,7 +223,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
224
223
|
stream.bitDepth === request.bitDepth);
|
|
225
224
|
if (existingStream) {
|
|
226
225
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: reused audio stream ${existingStream.audioStreamId} for usage ${request.streamUsage} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
227
|
-
|
|
226
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'audioStreamAllocate', request, this.context);
|
|
228
227
|
return { audioStreamId: existingStream.audioStreamId };
|
|
229
228
|
}
|
|
230
229
|
let audioStreamId = 0;
|
|
@@ -245,7 +244,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
245
244
|
},
|
|
246
245
|
];
|
|
247
246
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: allocated audio stream ${audioStreamId} for usage ${request.streamUsage} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
248
|
-
|
|
247
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'audioStreamAllocate', request, this.context);
|
|
249
248
|
return { audioStreamId };
|
|
250
249
|
}
|
|
251
250
|
audioStreamDeallocate(request) {
|
|
@@ -255,7 +254,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
255
254
|
}
|
|
256
255
|
this.state.allocatedAudioStreams = this.state.allocatedAudioStreams.filter((stream) => stream.audioStreamId !== request.audioStreamId);
|
|
257
256
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: deallocated audio stream ${request.audioStreamId} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
258
|
-
|
|
257
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'audioStreamDeallocate', request, this.context);
|
|
259
258
|
}
|
|
260
259
|
async snapshotStreamAllocate(request) {
|
|
261
260
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -293,7 +292,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
293
292
|
}
|
|
294
293
|
: stream);
|
|
295
294
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: reused snapshot stream ${existingStream.snapshotStreamId} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
296
|
-
|
|
295
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'snapshotStreamAllocate', request, this.context);
|
|
297
296
|
return { snapshotStreamId: existingStream.snapshotStreamId };
|
|
298
297
|
}
|
|
299
298
|
let snapshotStreamId = 0;
|
|
@@ -317,7 +316,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
317
316
|
},
|
|
318
317
|
];
|
|
319
318
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: allocated snapshot stream ${snapshotStreamId} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
320
|
-
|
|
319
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'snapshotStreamAllocate', request, this.context);
|
|
321
320
|
return { snapshotStreamId };
|
|
322
321
|
}
|
|
323
322
|
async snapshotStreamDeallocate(request) {
|
|
@@ -327,7 +326,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
327
326
|
}
|
|
328
327
|
this.state.allocatedSnapshotStreams = this.state.allocatedSnapshotStreams.filter((stream) => stream.snapshotStreamId !== request.snapshotStreamId);
|
|
329
328
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: deallocated snapshot stream ${request.snapshotStreamId} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
330
|
-
|
|
329
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'snapshotStreamDeallocate', request, this.context);
|
|
331
330
|
}
|
|
332
331
|
captureSnapshot(request) {
|
|
333
332
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -339,7 +338,7 @@ export class MatterbridgeCameraAvStreamManagementServer extends CameraAvStreamMa
|
|
|
339
338
|
device.log.info(`MatterbridgeCameraAvStreamManagementServer: capturing snapshot ${snapshotStreamId ?? 'auto'} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
340
339
|
device.log.debug(`MatterbridgeCameraAvStreamManagementServer: captureSnapshot called with snapshotStreamId ${request.snapshotStreamId} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
341
340
|
const { data, resolution } = cameraColorTestJpegForResolution(request.requestedResolution);
|
|
342
|
-
|
|
341
|
+
this.endpoint.emitCommand(CameraAvStreamManagement, 'captureSnapshot', request, this.context);
|
|
343
342
|
return {
|
|
344
343
|
data,
|
|
345
344
|
imageCodec: CameraAvStreamManagement.ImageCodec.Jpeg,
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { ChimeServer } from '@matter/node/behaviors/chime';
|
|
2
|
-
import
|
|
2
|
+
import { Chime } from '@matter/types/clusters/chime';
|
|
3
3
|
import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
4
4
|
export type ChimeId = number;
|
|
5
5
|
declare const ChimeServerBase: import("@matter/node").ClusterBehavior.Type<typeof ChimeServer, import("@matter/types").ClusterType.WithEnabledAttributes<import("@matter/types").ClusterType.WithEnabledEvents<Chime, "chimeStartedPlaying">, never>, import("@matter/types").ClusterType.Concrete, new () => {}, "chime">;
|
|
6
6
|
export declare class MatterbridgeChimeServer extends ChimeServerBase {
|
|
7
7
|
#private;
|
|
8
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
8
9
|
initialize(): void;
|
|
9
10
|
playChimeSound(request: Chime.PlayChimeSoundRequest): Promise<void>;
|
|
10
11
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ChimeServer } from '@matter/node/behaviors/chime';
|
|
2
2
|
import { Status, StatusResponseError } from '@matter/types';
|
|
3
|
-
import {
|
|
3
|
+
import { Chime } from '@matter/types/clusters/chime';
|
|
4
4
|
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
5
5
|
const ChimeServerBase = ChimeServer.enable({ events: { chimeStartedPlaying: true } });
|
|
6
6
|
export class MatterbridgeChimeServer extends ChimeServerBase {
|
|
@@ -24,7 +24,7 @@ export class MatterbridgeChimeServer extends ChimeServerBase {
|
|
|
24
24
|
}
|
|
25
25
|
device.log.info(`MatterbridgeChimeServer: playing chime sound with chimeId ${chimeId} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
26
26
|
this.events.chimeStartedPlaying.emit({ chimeId }, this.context);
|
|
27
|
-
|
|
27
|
+
this.endpoint.emitCommand(Chime, 'playChimeSound', request, this.context);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
export function createDefaultChimeClusterServer(endpoint, installedChimeSounds, selectedChime, enabled = true) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MaybePromise } from '@matter/general';
|
|
2
2
|
import { ColorControlServer } from '@matter/node/behaviors/color-control';
|
|
3
3
|
import { ColorControl } from '@matter/types/clusters/color-control';
|
|
4
|
+
import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
4
5
|
declare const MatterbridgeColorControlServer_base: import("@matter/node").ClusterBehavior.Type<typeof ColorControlServer, import("@matter/types").ClusterType.WithSupportedFeatures<ColorControl, {
|
|
5
6
|
colorLoop: false;
|
|
6
7
|
colorTemperature: true;
|
|
@@ -9,6 +10,7 @@ declare const MatterbridgeColorControlServer_base: import("@matter/node").Cluste
|
|
|
9
10
|
xy: true;
|
|
10
11
|
}>, import("@matter/types").ClusterType.Concrete, typeof import("@matter/node/behaviors/color-control").ColorControlBaseServer.Internal, "colorControl">;
|
|
11
12
|
export declare class MatterbridgeColorControlServer extends MatterbridgeColorControlServer_base {
|
|
13
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
12
14
|
initialize(): MaybePromise;
|
|
13
15
|
moveToHue(request: ColorControl.MoveToHueRequest): Promise<void>;
|
|
14
16
|
moveHue(request: ColorControl.MoveHueRequest): Promise<void>;
|
|
@@ -24,6 +24,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
24
24
|
});
|
|
25
25
|
device.log.debug(`MatterbridgeColorControlServer: moveToHue called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
26
26
|
await super.moveToHue(request);
|
|
27
|
+
this.endpoint.emitCommand(ColorControl, 'moveToHue', request, this.context);
|
|
27
28
|
}
|
|
28
29
|
async moveHue(request) {
|
|
29
30
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -42,6 +43,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
42
43
|
});
|
|
43
44
|
device.log.debug(`MatterbridgeColorControlServer: moveHue called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
44
45
|
await super.moveHue(request);
|
|
46
|
+
this.endpoint.emitCommand(ColorControl, 'moveHue', request, this.context);
|
|
45
47
|
}
|
|
46
48
|
async stepHue(request) {
|
|
47
49
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -60,6 +62,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
60
62
|
});
|
|
61
63
|
device.log.debug(`MatterbridgeColorControlServer: stepHue called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
62
64
|
await super.stepHue(request);
|
|
65
|
+
this.endpoint.emitCommand(ColorControl, 'stepHue', request, this.context);
|
|
63
66
|
}
|
|
64
67
|
async enhancedMoveToHue(request) {
|
|
65
68
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -78,6 +81,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
78
81
|
});
|
|
79
82
|
device.log.debug(`MatterbridgeColorControlServer: enhancedMoveToHue called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
80
83
|
await super.enhancedMoveToHue(request);
|
|
84
|
+
this.endpoint.emitCommand(ColorControl, 'enhancedMoveToHue', request, this.context);
|
|
81
85
|
}
|
|
82
86
|
async enhancedMoveHue(request) {
|
|
83
87
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -96,6 +100,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
96
100
|
});
|
|
97
101
|
device.log.debug(`MatterbridgeColorControlServer: enhancedMoveHue called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
98
102
|
await super.enhancedMoveHue(request);
|
|
103
|
+
this.endpoint.emitCommand(ColorControl, 'enhancedMoveHue', request, this.context);
|
|
99
104
|
}
|
|
100
105
|
async enhancedStepHue(request) {
|
|
101
106
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -114,6 +119,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
114
119
|
});
|
|
115
120
|
device.log.debug(`MatterbridgeColorControlServer: enhancedStepHue called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
116
121
|
await super.enhancedStepHue(request);
|
|
122
|
+
this.endpoint.emitCommand(ColorControl, 'enhancedStepHue', request, this.context);
|
|
117
123
|
}
|
|
118
124
|
async moveToSaturation(request) {
|
|
119
125
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -132,6 +138,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
132
138
|
});
|
|
133
139
|
device.log.debug(`MatterbridgeColorControlServer: moveToSaturation called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
134
140
|
await super.moveToSaturation(request);
|
|
141
|
+
this.endpoint.emitCommand(ColorControl, 'moveToSaturation', request, this.context);
|
|
135
142
|
}
|
|
136
143
|
async moveSaturation(request) {
|
|
137
144
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -150,6 +157,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
150
157
|
});
|
|
151
158
|
device.log.debug(`MatterbridgeColorControlServer: moveSaturation called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
152
159
|
await super.moveSaturation(request);
|
|
160
|
+
this.endpoint.emitCommand(ColorControl, 'moveSaturation', request, this.context);
|
|
153
161
|
}
|
|
154
162
|
async stepSaturation(request) {
|
|
155
163
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -168,6 +176,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
168
176
|
});
|
|
169
177
|
device.log.debug(`MatterbridgeColorControlServer: stepSaturation called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
170
178
|
await super.stepSaturation(request);
|
|
179
|
+
this.endpoint.emitCommand(ColorControl, 'stepSaturation', request, this.context);
|
|
171
180
|
}
|
|
172
181
|
async moveToHueAndSaturation(request) {
|
|
173
182
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -186,6 +195,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
186
195
|
});
|
|
187
196
|
device.log.debug(`MatterbridgeColorControlServer: moveToHueAndSaturation called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
188
197
|
await super.moveToHueAndSaturation(request);
|
|
198
|
+
this.endpoint.emitCommand(ColorControl, 'moveToHueAndSaturation', request, this.context);
|
|
189
199
|
}
|
|
190
200
|
async enhancedMoveToHueAndSaturation(request) {
|
|
191
201
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -204,6 +214,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
204
214
|
});
|
|
205
215
|
device.log.debug(`MatterbridgeColorControlServer: enhancedMoveToHueAndSaturation called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
206
216
|
await super.enhancedMoveToHueAndSaturation(request);
|
|
217
|
+
this.endpoint.emitCommand(ColorControl, 'enhancedMoveToHueAndSaturation', request, this.context);
|
|
207
218
|
}
|
|
208
219
|
async moveToColor(request) {
|
|
209
220
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -222,6 +233,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
222
233
|
});
|
|
223
234
|
device.log.debug(`MatterbridgeColorControlServer: moveToColor called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
224
235
|
await super.moveToColor(request);
|
|
236
|
+
this.endpoint.emitCommand(ColorControl, 'moveToColor', request, this.context);
|
|
225
237
|
}
|
|
226
238
|
async moveColor(request) {
|
|
227
239
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -240,6 +252,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
240
252
|
});
|
|
241
253
|
device.log.debug(`MatterbridgeColorControlServer: moveColor called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
242
254
|
await super.moveColor(request);
|
|
255
|
+
this.endpoint.emitCommand(ColorControl, 'moveColor', request, this.context);
|
|
243
256
|
}
|
|
244
257
|
async stepColor(request) {
|
|
245
258
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -258,6 +271,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
258
271
|
});
|
|
259
272
|
device.log.debug(`MatterbridgeColorControlServer: stepColor called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
260
273
|
await super.stepColor(request);
|
|
274
|
+
this.endpoint.emitCommand(ColorControl, 'stepColor', request, this.context);
|
|
261
275
|
}
|
|
262
276
|
async moveToColorTemperature(request) {
|
|
263
277
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -276,6 +290,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
276
290
|
});
|
|
277
291
|
device.log.debug(`MatterbridgeColorControlServer: moveToColorTemperature called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
278
292
|
await super.moveToColorTemperature(request);
|
|
293
|
+
this.endpoint.emitCommand(ColorControl, 'moveToColorTemperature', request, this.context);
|
|
279
294
|
}
|
|
280
295
|
async moveColorTemperature(request) {
|
|
281
296
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -294,6 +309,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
294
309
|
});
|
|
295
310
|
device.log.debug(`MatterbridgeColorControlServer: moveColorTemperature called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
296
311
|
await super.moveColorTemperature(request);
|
|
312
|
+
this.endpoint.emitCommand(ColorControl, 'moveColorTemperature', request, this.context);
|
|
297
313
|
}
|
|
298
314
|
async stepColorTemperature(request) {
|
|
299
315
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -312,6 +328,7 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
312
328
|
});
|
|
313
329
|
device.log.debug(`MatterbridgeColorControlServer: stepColorTemperature called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
314
330
|
await super.stepColorTemperature(request);
|
|
331
|
+
this.endpoint.emitCommand(ColorControl, 'stepColorTemperature', request, this.context);
|
|
315
332
|
}
|
|
316
333
|
async stopMoveStep(request) {
|
|
317
334
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -330,5 +347,6 @@ export class MatterbridgeColorControlServer extends ColorControlServer.with(Colo
|
|
|
330
347
|
});
|
|
331
348
|
device.log.debug(`MatterbridgeColorControlServer: stopMoveStep called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
332
349
|
await super.stopMoveStep(request);
|
|
350
|
+
this.endpoint.emitCommand(ColorControl, 'stopMoveStep', request, this.context);
|
|
333
351
|
}
|
|
334
352
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { MaybePromise } from '@matter/general';
|
|
2
2
|
import { LevelControlServer } from '@matter/node/behaviors/level-control';
|
|
3
|
-
import
|
|
3
|
+
import { LevelControl } from '@matter/types/clusters/level-control';
|
|
4
|
+
import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
4
5
|
export declare class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
6
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
5
7
|
initialize(): MaybePromise;
|
|
6
8
|
moveToLevel(request: LevelControl.MoveToLevelRequest): Promise<void>;
|
|
7
9
|
moveToLevelWithOnOff(request: LevelControl.MoveToLevelRequest): Promise<void>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LevelControlServer } from '@matter/node/behaviors/level-control';
|
|
2
|
+
import { LevelControl } from '@matter/types/clusters/level-control';
|
|
2
3
|
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
3
4
|
export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
4
5
|
initialize() {
|
|
@@ -23,6 +24,7 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
23
24
|
});
|
|
24
25
|
device.log.debug(`MatterbridgeLevelControlServer: moveToLevel called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
25
26
|
await super.moveToLevel(request);
|
|
27
|
+
this.endpoint.emitCommand(LevelControl, 'moveToLevel', request, this.context);
|
|
26
28
|
}
|
|
27
29
|
async moveToLevelWithOnOff(request) {
|
|
28
30
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -41,6 +43,7 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
41
43
|
});
|
|
42
44
|
device.log.debug(`MatterbridgeLevelControlServer: moveToLevelWithOnOff called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
43
45
|
await super.moveToLevelWithOnOff(request);
|
|
46
|
+
this.endpoint.emitCommand(LevelControl, 'moveToLevelWithOnOff', request, this.context);
|
|
44
47
|
}
|
|
45
48
|
async move(request) {
|
|
46
49
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -59,6 +62,7 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
59
62
|
});
|
|
60
63
|
device.log.debug(`MatterbridgeLevelControlServer: move called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
61
64
|
await super.move(request);
|
|
65
|
+
this.endpoint.emitCommand(LevelControl, 'move', request, this.context);
|
|
62
66
|
}
|
|
63
67
|
async moveWithOnOff(request) {
|
|
64
68
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -77,6 +81,7 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
77
81
|
});
|
|
78
82
|
device.log.debug(`MatterbridgeLevelControlServer: moveWithOnOff called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
79
83
|
await super.moveWithOnOff(request);
|
|
84
|
+
this.endpoint.emitCommand(LevelControl, 'moveWithOnOff', request, this.context);
|
|
80
85
|
}
|
|
81
86
|
async step(request) {
|
|
82
87
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -95,6 +100,7 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
95
100
|
});
|
|
96
101
|
device.log.debug(`MatterbridgeLevelControlServer: step called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
97
102
|
await super.step(request);
|
|
103
|
+
this.endpoint.emitCommand(LevelControl, 'step', request, this.context);
|
|
98
104
|
}
|
|
99
105
|
async stepWithOnOff(request) {
|
|
100
106
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -113,6 +119,7 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
113
119
|
});
|
|
114
120
|
device.log.debug(`MatterbridgeLevelControlServer: stepWithOnOff called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
115
121
|
await super.stepWithOnOff(request);
|
|
122
|
+
this.endpoint.emitCommand(LevelControl, 'stepWithOnOff', request, this.context);
|
|
116
123
|
}
|
|
117
124
|
async stop(request) {
|
|
118
125
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -131,6 +138,7 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
131
138
|
});
|
|
132
139
|
device.log.debug(`MatterbridgeLevelControlServer: stop called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
133
140
|
await super.stop(request);
|
|
141
|
+
this.endpoint.emitCommand(LevelControl, 'stop', request, this.context);
|
|
134
142
|
}
|
|
135
143
|
async stopWithOnOff(request) {
|
|
136
144
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -149,5 +157,6 @@ export class MatterbridgeLevelControlServer extends LevelControlServer {
|
|
|
149
157
|
});
|
|
150
158
|
device.log.debug(`MatterbridgeLevelControlServer: stopWithOnOff called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
151
159
|
await super.stopWithOnOff(request);
|
|
160
|
+
this.endpoint.emitCommand(LevelControl, 'stopWithOnOff', request, this.context);
|
|
152
161
|
}
|
|
153
162
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { OnOffServer } from '@matter/node/behaviors/on-off';
|
|
2
2
|
import { OnOff } from '@matter/types/clusters/on-off';
|
|
3
|
+
import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
3
4
|
declare const MatterbridgeOnOffServer_base: import("@matter/node").ClusterBehavior.Type<typeof OnOffServer, import("@matter/types").ClusterType.WithSupportedFeatures<import("@matter/types").ClusterType.WithSupportedFeatures<import("@matter/types").ClusterType.WithSupportedFeatures<OnOff, {
|
|
4
5
|
deadFrontBehavior: false;
|
|
5
6
|
lighting: true;
|
|
@@ -14,6 +15,7 @@ declare const MatterbridgeOnOffServer_base: import("@matter/node").ClusterBehavi
|
|
|
14
15
|
offOnly: false;
|
|
15
16
|
}>, import("@matter/types").ClusterType.Concrete, typeof import("@matter/node/behaviors/on-off").OnOffBaseServer.Internal, "onOff">;
|
|
16
17
|
export declare class MatterbridgeOnOffServer extends MatterbridgeOnOffServer_base {
|
|
18
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
17
19
|
on(): Promise<void>;
|
|
18
20
|
off(): Promise<void>;
|
|
19
21
|
toggle(): Promise<void>;
|
|
@@ -19,6 +19,7 @@ export class MatterbridgeOnOffServer extends OnOffServer.with(OnOff.Feature.Ligh
|
|
|
19
19
|
});
|
|
20
20
|
device.log.debug(`MatterbridgeOnOffServer: on called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
21
21
|
await super.on();
|
|
22
|
+
this.endpoint.emitCommand(OnOff, 'on', {}, this.context);
|
|
22
23
|
}
|
|
23
24
|
async off() {
|
|
24
25
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -37,6 +38,7 @@ export class MatterbridgeOnOffServer extends OnOffServer.with(OnOff.Feature.Ligh
|
|
|
37
38
|
});
|
|
38
39
|
device.log.debug(`MatterbridgeOnOffServer: off called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
39
40
|
await super.off();
|
|
41
|
+
this.endpoint.emitCommand(OnOff, 'off', {}, this.context);
|
|
40
42
|
}
|
|
41
43
|
async toggle() {
|
|
42
44
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -55,6 +57,7 @@ export class MatterbridgeOnOffServer extends OnOffServer.with(OnOff.Feature.Ligh
|
|
|
55
57
|
});
|
|
56
58
|
device.log.debug(`MatterbridgeOnOffServer: toggle called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
57
59
|
await super.toggle();
|
|
60
|
+
this.endpoint.emitCommand(OnOff, 'toggle', {}, this.context);
|
|
58
61
|
}
|
|
59
62
|
async offWithEffect(request) {
|
|
60
63
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -73,6 +76,7 @@ export class MatterbridgeOnOffServer extends OnOffServer.with(OnOff.Feature.Ligh
|
|
|
73
76
|
});
|
|
74
77
|
device.log.debug(`MatterbridgeOnOffServer: offWithEffect called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
75
78
|
await super.offWithEffect(request);
|
|
79
|
+
this.endpoint.emitCommand(OnOff, 'offWithEffect', request, this.context);
|
|
76
80
|
}
|
|
77
81
|
async onWithRecallGlobalScene() {
|
|
78
82
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -91,6 +95,7 @@ export class MatterbridgeOnOffServer extends OnOffServer.with(OnOff.Feature.Ligh
|
|
|
91
95
|
});
|
|
92
96
|
device.log.debug(`MatterbridgeOnOffServer: onWithRecallGlobalScene called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
93
97
|
await super.onWithRecallGlobalScene();
|
|
98
|
+
this.endpoint.emitCommand(OnOff, 'onWithRecallGlobalScene', {}, this.context);
|
|
94
99
|
}
|
|
95
100
|
async onWithTimedOff(request) {
|
|
96
101
|
if (process.env.MATTERBRIDGE_CHIP_TEST) {
|
|
@@ -109,5 +114,6 @@ export class MatterbridgeOnOffServer extends OnOffServer.with(OnOff.Feature.Ligh
|
|
|
109
114
|
});
|
|
110
115
|
device.log.debug(`MatterbridgeOnOffServer: onWithTimedOff called (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
111
116
|
await super.onWithTimedOff(request);
|
|
117
|
+
this.endpoint.emitCommand(OnOff, 'onWithTimedOff', request, this.context);
|
|
112
118
|
}
|
|
113
119
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebRtcTransportProviderServer } from '@matter/node/behaviors/web-rtc-transport-provider';
|
|
2
|
-
import
|
|
2
|
+
import { WebRtcTransportProvider } from '@matter/types/clusters/web-rtc-transport-provider';
|
|
3
3
|
import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
4
4
|
import { type WeriftOfferOptions, WeriftWebRtcSession } from './weriftSession.js';
|
|
5
5
|
export declare function allocateWebRtcSessionId(nextCandidate: number, activeSessionIds: ReadonlySet<number>): {
|
|
@@ -8,6 +8,7 @@ export declare function allocateWebRtcSessionId(nextCandidate: number, activeSes
|
|
|
8
8
|
};
|
|
9
9
|
export declare class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportProviderServer {
|
|
10
10
|
#private;
|
|
11
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
11
12
|
state: MatterbridgeWebRtcTransportProviderServer.State;
|
|
12
13
|
internal: MatterbridgeWebRtcTransportProviderServer.Internal;
|
|
13
14
|
solicitOffer(request: WebRtcTransportProvider.SolicitOfferRequest): Promise<WebRtcTransportProvider.SolicitOfferResponse>;
|
|
@@ -3,7 +3,7 @@ import { WebRtcTransportProviderServer } from '@matter/node/behaviors/web-rtc-tr
|
|
|
3
3
|
import { WebRtcTransportRequestorClient } from '@matter/node/behaviors/web-rtc-transport-requestor';
|
|
4
4
|
import { EndpointNumber, FabricIndex, NodeId, StreamUsage, Status, StatusResponseError } from '@matter/types';
|
|
5
5
|
import { WebRtcTransportDefinitions } from '@matter/types/clusters/web-rtc-transport-definitions';
|
|
6
|
-
import {
|
|
6
|
+
import { WebRtcTransportProvider } from '@matter/types/clusters/web-rtc-transport-provider';
|
|
7
7
|
import { MatterbridgeCameraAvStreamManagementServer } from './cameraAvStreamManagementServer.js';
|
|
8
8
|
import { MatterbridgeServer } from './matterbridgeServer.js';
|
|
9
9
|
import { WeriftWebRtcSession } from './weriftSession.js';
|
|
@@ -249,7 +249,7 @@ export class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportPr
|
|
|
249
249
|
device.log.info(`MatterbridgeWebRtcTransportProviderServer.solicitOffer: solicited a WebRTC offer for session ${webRtcSessionId} (stream usage ${request.streamUsage}) (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
250
250
|
const requestorEndpoint = await this.#resolvePeerRequestorEndpoint(peerNodeId, fabricIndex, request.originatingEndpointId);
|
|
251
251
|
if (this.#evictIfOverCapacity(webRtcSessionId, requestorEndpoint)) {
|
|
252
|
-
|
|
252
|
+
this.endpoint.emitCommand(WebRtcTransportProvider, 'solicitOffer', request, this.context);
|
|
253
253
|
return { webRtcSessionId, deferredOffer: false, ...this.#echoDeprecatedStreamIds(request, videoStreams, audioStreams) };
|
|
254
254
|
}
|
|
255
255
|
const webRtcPeer = new WeriftWebRtcSession(webRtcSessionId, this.state.weriftOfferOptions);
|
|
@@ -266,7 +266,7 @@ export class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportPr
|
|
|
266
266
|
else {
|
|
267
267
|
device.log.info(`MatterbridgeWebRtcTransportProviderServer.solicitOffer: could not reach the peer's WebRtcTransportRequestor; the Offer for session ${webRtcSessionId} was not sent (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
268
268
|
}
|
|
269
|
-
|
|
269
|
+
this.endpoint.emitCommand(WebRtcTransportProvider, 'solicitOffer', request, this.context);
|
|
270
270
|
return { webRtcSessionId, deferredOffer: false, ...this.#echoDeprecatedStreamIds(request, videoStreams, audioStreams) };
|
|
271
271
|
}
|
|
272
272
|
async provideOffer(request) {
|
|
@@ -311,7 +311,7 @@ export class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportPr
|
|
|
311
311
|
];
|
|
312
312
|
const requestorEndpointForCapacityCheck = await this.#resolvePeerRequestorEndpoint(peerNodeId, fabricIndex, request.originatingEndpointId ?? EndpointNumber(0));
|
|
313
313
|
if (this.#evictIfOverCapacity(webRtcSessionId, requestorEndpointForCapacityCheck)) {
|
|
314
|
-
|
|
314
|
+
this.endpoint.emitCommand(WebRtcTransportProvider, 'provideOffer', request, this.context);
|
|
315
315
|
return { webRtcSessionId, ...this.#echoDeprecatedStreamIds(request, videoStreams, audioStreams) };
|
|
316
316
|
}
|
|
317
317
|
}
|
|
@@ -336,7 +336,7 @@ export class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportPr
|
|
|
336
336
|
else {
|
|
337
337
|
device.log.info(`MatterbridgeWebRtcTransportProviderServer.provideOffer: could not reach the peer's WebRtcTransportRequestor; the Answer for session ${webRtcSessionId} was not sent (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
338
338
|
}
|
|
339
|
-
|
|
339
|
+
this.endpoint.emitCommand(WebRtcTransportProvider, 'provideOffer', request, this.context);
|
|
340
340
|
return { webRtcSessionId, ...this.#echoDeprecatedStreamIds(request, session.videoStreams && [...session.videoStreams], session.audioStreams && [...session.audioStreams]) };
|
|
341
341
|
}
|
|
342
342
|
async provideAnswer(request) {
|
|
@@ -350,7 +350,7 @@ export class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportPr
|
|
|
350
350
|
if (webRtcPeer) {
|
|
351
351
|
await webRtcPeer.applyAnswer(request.sdp);
|
|
352
352
|
}
|
|
353
|
-
|
|
353
|
+
this.endpoint.emitCommand(WebRtcTransportProvider, 'provideAnswer', request, this.context);
|
|
354
354
|
}
|
|
355
355
|
async provideIceCandidates(request) {
|
|
356
356
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -388,7 +388,7 @@ export class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportPr
|
|
|
388
388
|
}
|
|
389
389
|
}));
|
|
390
390
|
}
|
|
391
|
-
|
|
391
|
+
this.endpoint.emitCommand(WebRtcTransportProvider, 'provideIceCandidates', request, this.context);
|
|
392
392
|
}
|
|
393
393
|
async endSession(request) {
|
|
394
394
|
const device = this.endpoint.stateOf(MatterbridgeServer);
|
|
@@ -402,7 +402,7 @@ export class MatterbridgeWebRtcTransportProviderServer extends WebRtcTransportPr
|
|
|
402
402
|
await webRtcPeer.close();
|
|
403
403
|
}
|
|
404
404
|
device.log.info(`MatterbridgeWebRtcTransportProviderServer.endSession: ended webRTC session ${request.webRtcSessionId} (reason ${request.reason}) (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
|
|
405
|
-
|
|
405
|
+
this.endpoint.emitCommand(WebRtcTransportProvider, 'endSession', request, this.context);
|
|
406
406
|
}
|
|
407
407
|
}
|
|
408
408
|
(function (MatterbridgeWebRtcTransportProviderServer) {
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { WebRtcTransportRequestorServer } from '@matter/node/behaviors/web-rtc-transport-requestor';
|
|
2
|
-
import
|
|
2
|
+
import { WebRtcTransportRequestor } from '@matter/types/clusters/web-rtc-transport-requestor';
|
|
3
3
|
import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
4
4
|
export declare class MatterbridgeWebRtcTransportRequestorServer extends WebRtcTransportRequestorServer {
|
|
5
|
+
readonly endpoint: MatterbridgeEndpoint;
|
|
5
6
|
offer(request: WebRtcTransportRequestor.OfferRequest): Promise<void>;
|
|
6
7
|
answer(request: WebRtcTransportRequestor.AnswerRequest): Promise<void>;
|
|
7
8
|
iceCandidates(request: WebRtcTransportRequestor.IceCandidatesRequest): Promise<void>;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import { WebRtcTransportRequestorServer } from '@matter/node/behaviors/web-rtc-transport-requestor';
|
|
2
|
-
import {
|
|
2
|
+
import { WebRtcTransportRequestor } from '@matter/types/clusters/web-rtc-transport-requestor';
|
|
3
3
|
export class MatterbridgeWebRtcTransportRequestorServer extends WebRtcTransportRequestorServer {
|
|
4
4
|
async offer(request) {
|
|
5
5
|
await super.offer(request);
|
|
6
|
-
|
|
6
|
+
this.endpoint.emitCommand(WebRtcTransportRequestor, 'offer', request, this.context);
|
|
7
7
|
}
|
|
8
8
|
async answer(request) {
|
|
9
9
|
await super.answer(request);
|
|
10
|
-
|
|
10
|
+
this.endpoint.emitCommand(WebRtcTransportRequestor, 'answer', request, this.context);
|
|
11
11
|
}
|
|
12
12
|
async iceCandidates(request) {
|
|
13
13
|
await super.iceCandidates(request);
|
|
14
|
-
|
|
14
|
+
this.endpoint.emitCommand(WebRtcTransportRequestor, 'iceCandidates', request, this.context);
|
|
15
15
|
}
|
|
16
16
|
async end(request) {
|
|
17
17
|
await super.end(request);
|
|
18
|
-
|
|
18
|
+
this.endpoint.emitCommand(WebRtcTransportRequestor, 'end', request, this.context);
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
export function createDefaultWebRtcTransportRequestorClusterServer(endpoint) {
|
|
@@ -29,6 +29,8 @@ export declare class WeriftWebRtcSession {
|
|
|
29
29
|
private static readonly DIAGNOSTICS_INTERVAL_MS;
|
|
30
30
|
private lastDiagnosticsCounters?;
|
|
31
31
|
private readonly dtlsTransportsWithStateLogging;
|
|
32
|
+
private static parseIcePortRange;
|
|
33
|
+
private static parseIceAdditionalHostAddresses;
|
|
32
34
|
constructor(webRtcSessionId: number, options: WeriftOfferOptions);
|
|
33
35
|
private summarizeSdp;
|
|
34
36
|
private getFreeUdpPort;
|
|
@@ -22,11 +22,35 @@ export class WeriftWebRtcSession {
|
|
|
22
22
|
static DIAGNOSTICS_INTERVAL_MS = 10_000;
|
|
23
23
|
lastDiagnosticsCounters;
|
|
24
24
|
dtlsTransportsWithStateLogging = new Set();
|
|
25
|
+
static parseIcePortRange() {
|
|
26
|
+
const raw = process.env.MATTERBRIDGE_ICE_PORT_RANGE?.trim();
|
|
27
|
+
if (!raw)
|
|
28
|
+
return undefined;
|
|
29
|
+
const match = /^(\d{1,5})-(\d{1,5})$/.exec(raw);
|
|
30
|
+
if (!match)
|
|
31
|
+
return undefined;
|
|
32
|
+
const min = Number(match[1]);
|
|
33
|
+
const max = Number(match[2]);
|
|
34
|
+
if (min < 1024 || max > 65_535 || min >= max)
|
|
35
|
+
return undefined;
|
|
36
|
+
return [min, max];
|
|
37
|
+
}
|
|
38
|
+
static parseIceAdditionalHostAddresses() {
|
|
39
|
+
const addresses = process.env.MATTERBRIDGE_ICE_HOST_ADDRESSES?.split(',')
|
|
40
|
+
.map((address) => address.trim())
|
|
41
|
+
.filter((address) => address.length > 0) ?? [];
|
|
42
|
+
return addresses.length > 0 ? addresses : undefined;
|
|
43
|
+
}
|
|
25
44
|
constructor(webRtcSessionId, options) {
|
|
26
45
|
this.webRtcSessionId = webRtcSessionId;
|
|
27
46
|
this.options = { ...options };
|
|
28
|
-
|
|
47
|
+
const icePortRange = WeriftWebRtcSession.parseIcePortRange();
|
|
48
|
+
const iceAdditionalHostAddresses = WeriftWebRtcSession.parseIceAdditionalHostAddresses();
|
|
49
|
+
this.peerConnection = new RTCPeerConnection({ codecs: { audio: [useOPUS(), usePCMU()], video: [useH264(), useVP8()] }, icePortRange, iceAdditionalHostAddresses });
|
|
29
50
|
this.log = new AnsiLogger({ logName: `WebRTC session ${webRtcSessionId}`, logLevel: "debug", logNameColor: MAGENTA, logTimestampFormat: 4 });
|
|
51
|
+
if (icePortRange || iceAdditionalHostAddresses) {
|
|
52
|
+
this.log.debug(`ICE overrides: portRange=${icePortRange ? `${icePortRange[0]}-${icePortRange[1]}` : 'default'} additionalHostAddresses=${iceAdditionalHostAddresses?.join(', ') ?? 'none'}`);
|
|
53
|
+
}
|
|
30
54
|
this.peerConnection.iceGatheringStateChange.subscribe((state) => {
|
|
31
55
|
this.log.info(`ICE gathering state: ${state}`);
|
|
32
56
|
});
|
package/dist/demoDevices.js
CHANGED
|
@@ -5,6 +5,7 @@ import { AirQuality } from '@matter/types/clusters/air-quality';
|
|
|
5
5
|
import { ClosureDimension } from '@matter/types/clusters/closure-dimension';
|
|
6
6
|
import { DoorLock } from '@matter/types/clusters/door-lock';
|
|
7
7
|
import { FanControl } from '@matter/types/clusters/fan-control';
|
|
8
|
+
import { Identify } from '@matter/types/clusters/identify';
|
|
8
9
|
import { PowerSource } from '@matter/types/clusters/power-source';
|
|
9
10
|
import { PowerTopology } from '@matter/types/clusters/power-topology';
|
|
10
11
|
import { ResourceMonitoring } from '@matter/types/clusters/resource-monitoring';
|
|
@@ -14,18 +15,25 @@ import { Thermostat } from '@matter/types/clusters/thermostat';
|
|
|
14
15
|
import { EndpointNumber } from '@matter/types/datatype';
|
|
15
16
|
import { getErrorMessage } from '@matterbridge/utils/error';
|
|
16
17
|
import { AirConditioner } from './devices/airConditioner.js';
|
|
18
|
+
import { AudioDoorbell } from './devices/audioDoorbell.js';
|
|
17
19
|
import { BasicVideoPlayer } from './devices/basicVideoPlayer.js';
|
|
18
20
|
import { BatteryStorage } from './devices/batteryStorage.js';
|
|
21
|
+
import { Camera } from './devices/camera.js';
|
|
22
|
+
import { CameraController } from './devices/cameraController.js';
|
|
19
23
|
import { CastingVideoClient } from './devices/castingVideoClient.js';
|
|
20
24
|
import { CastingVideoPlayer } from './devices/castingVideoPlayer.js';
|
|
25
|
+
import { Chime } from './devices/chime.js';
|
|
21
26
|
import { Closure } from './devices/closure.js';
|
|
22
27
|
import { ContentApp } from './devices/contentApp.js';
|
|
23
28
|
import { Cooktop } from './devices/cooktop.js';
|
|
24
29
|
import { Dishwasher } from './devices/dishwasher.js';
|
|
30
|
+
import { Doorbell } from './devices/doorbell.js';
|
|
25
31
|
import { ElectricalUtilityMeter } from './devices/electricalUtilityMeter.js';
|
|
26
32
|
import { Evse } from './devices/evse.js';
|
|
27
33
|
import { ExtractorHood } from './devices/extractorHood.js';
|
|
34
|
+
import { FloodlightCamera } from './devices/floodlightCamera.js';
|
|
28
35
|
import { HeatPump } from './devices/heatPump.js';
|
|
36
|
+
import { Intercom } from './devices/intercom.js';
|
|
29
37
|
import { IrrigationSystem } from './devices/irrigationSystem.js';
|
|
30
38
|
import { LaundryDryer } from './devices/laundryDryer.js';
|
|
31
39
|
import { LaundryWasher } from './devices/laundryWasher.js';
|
|
@@ -33,8 +41,10 @@ import { MicrowaveOven } from './devices/microwaveOven.js';
|
|
|
33
41
|
import { Oven } from './devices/oven.js';
|
|
34
42
|
import { Refrigerator } from './devices/refrigerator.js';
|
|
35
43
|
import { RoboticVacuumCleaner } from './devices/roboticVacuumCleaner.js';
|
|
44
|
+
import { SnapshotCamera } from './devices/snapshotCamera.js';
|
|
36
45
|
import { SolarPower } from './devices/solarPower.js';
|
|
37
46
|
import { Speaker } from './devices/speaker.js';
|
|
47
|
+
import { VideoDoorbell } from './devices/videoDoorbell.js';
|
|
38
48
|
import { VideoRemoteControl } from './devices/videoRemoteControl.js';
|
|
39
49
|
import { WaterHeater } from './devices/waterHeater.js';
|
|
40
50
|
import { getSupportedDeviceType } from './matterbridgeDeviceTypes.js';
|
|
@@ -823,4 +833,58 @@ export async function createDemoDevices(matterbridge) {
|
|
|
823
833
|
tagList: [getSemtag(ElectricalMeasurementTag.Ac), getSemtag(PowerSourceTag.Ev), getSemtag(CommodityTariffFlowTag.Import), getSemtag(CommodityTariffChronologyTag.Upcoming)],
|
|
824
834
|
});
|
|
825
835
|
await registerDevice(electricalUtilityMeterEvEndpoint, 'Electrical Utility Meter Ev', 'ENERGY-14-10');
|
|
836
|
+
ep = new Camera('Camera', 'CAMERA-16-01', {
|
|
837
|
+
id: 'Camera',
|
|
838
|
+
number: EndpointNumber(16_01),
|
|
839
|
+
weriftOfferOptions: { video: true, audio: true, videoSource: 'test', audioSource: 'test' },
|
|
840
|
+
});
|
|
841
|
+
await registerDevice(ep, 'Camera', 'CAMERA-16-01');
|
|
842
|
+
ep = new Camera('Camera Ptz', 'CAMERA-16-01-1', {
|
|
843
|
+
id: 'CameraPtz',
|
|
844
|
+
number: EndpointNumber(16_01_1),
|
|
845
|
+
ptz: true,
|
|
846
|
+
identifyType: Identify.IdentifyType.VisibleIndicator,
|
|
847
|
+
weriftOfferOptions: { video: true, audio: true, videoSource: 'test', audioSource: 'test' },
|
|
848
|
+
});
|
|
849
|
+
await registerDevice(ep, 'Camera Ptz', 'CAMERA-16-01-1');
|
|
850
|
+
ep = new FloodlightCamera('Floodlight Camera', 'CAMERA-16-02', {
|
|
851
|
+
id: 'FloodlightCamera',
|
|
852
|
+
number: EndpointNumber(16_02),
|
|
853
|
+
cameraOptions: { number: EndpointNumber(16_02_1), ptz: true, identifyType: Identify.IdentifyType.VisibleIndicator },
|
|
854
|
+
lightOptions: { number: EndpointNumber(16_02_2) },
|
|
855
|
+
});
|
|
856
|
+
await registerDevice(ep, 'Floodlight Camera', 'CAMERA-16-02');
|
|
857
|
+
ep = new VideoDoorbell('Video Doorbell', 'CAMERA-16-03', {
|
|
858
|
+
id: 'VideoDoorbell',
|
|
859
|
+
number: EndpointNumber(16_03),
|
|
860
|
+
cameraOptions: { number: EndpointNumber(16_03_1), ptz: true, identifyType: Identify.IdentifyType.VisibleIndicator },
|
|
861
|
+
doorbellOptions: { number: EndpointNumber(16_03_2) },
|
|
862
|
+
});
|
|
863
|
+
await registerDevice(ep, 'Video Doorbell', 'CAMERA-16-03');
|
|
864
|
+
ep = new Intercom('Intercom I', 'CAMERA-16-04', { id: 'Intercom', number: EndpointNumber(16_04), identifyType: Identify.IdentifyType.VisibleIndicator });
|
|
865
|
+
await registerDevice(ep, 'Intercom I', 'CAMERA-16-04');
|
|
866
|
+
ep = new Intercom('Intercom II', 'CAMERA-16-04-1', { id: 'IntercomII', number: EndpointNumber(16_04_1), identifyType: Identify.IdentifyType.VisibleIndicator });
|
|
867
|
+
await registerDevice(ep, 'Intercom II', 'CAMERA-16-04-1');
|
|
868
|
+
ep = new AudioDoorbell('Audio Doorbell', 'CAMERA-16-05', { id: 'AudioDoorbell', number: EndpointNumber(16_05) });
|
|
869
|
+
await registerDevice(ep, 'Audio Doorbell', 'CAMERA-16-05');
|
|
870
|
+
ep = new SnapshotCamera('Snapshot Camera', 'CAMERA-16-06', {
|
|
871
|
+
id: 'SnapshotCamera',
|
|
872
|
+
number: EndpointNumber(16_06),
|
|
873
|
+
identifyType: Identify.IdentifyType.VisibleIndicator,
|
|
874
|
+
});
|
|
875
|
+
await registerDevice(ep, 'Snapshot Camera', 'CAMERA-16-06');
|
|
876
|
+
ep = new Chime('Chime', 'CAMERA-16-07', {
|
|
877
|
+
id: 'Chime',
|
|
878
|
+
number: EndpointNumber(16_07),
|
|
879
|
+
identifyType: Identify.IdentifyType.AudibleBeep,
|
|
880
|
+
installedChimeSounds: [
|
|
881
|
+
{ chimeId: 0, name: 'Default Chime' },
|
|
882
|
+
{ chimeId: 1, name: 'Westminster' },
|
|
883
|
+
],
|
|
884
|
+
});
|
|
885
|
+
await registerDevice(ep, 'Chime', 'CAMERA-16-07');
|
|
886
|
+
ep = new CameraController('Camera Controller', 'CAMERA-16-08', { id: 'CameraController', number: EndpointNumber(16_08) });
|
|
887
|
+
await registerDevice(ep, 'Camera Controller', 'CAMERA-16-08');
|
|
888
|
+
ep = new Doorbell('Doorbell', 'CAMERA-16-09', { id: 'Doorbell', number: EndpointNumber(16_09) });
|
|
889
|
+
await registerDevice(ep, 'Doorbell', 'CAMERA-16-09');
|
|
826
890
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../audioDoorbell.js';
|
|
2
|
+
export * from '../camera.js';
|
|
3
|
+
export * from '../cameraController.js';
|
|
4
|
+
export * from '../chime.js';
|
|
5
|
+
export * from '../doorbell.js';
|
|
6
|
+
export * from '../floodlightCamera.js';
|
|
7
|
+
export * from '../intercom.js';
|
|
8
|
+
export * from '../snapshotCamera.js';
|
|
9
|
+
export * from '../videoDoorbell.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from '../audioDoorbell.js';
|
|
2
|
+
export * from '../camera.js';
|
|
3
|
+
export * from '../cameraController.js';
|
|
4
|
+
export * from '../chime.js';
|
|
5
|
+
export * from '../doorbell.js';
|
|
6
|
+
export * from '../floodlightCamera.js';
|
|
7
|
+
export * from '../intercom.js';
|
|
8
|
+
export * from '../snapshotCamera.js';
|
|
9
|
+
export * from '../videoDoorbell.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
2
|
+
import type { MatterbridgeEndpointOptions } from '../matterbridgeEndpointTypes.js';
|
|
3
|
+
export interface CameraControllerOptions extends MatterbridgeEndpointOptions {
|
|
4
|
+
powerSourceType?: 'Rechargeable' | 'Replaceable' | 'Battery' | 'Wired' | 'None';
|
|
5
|
+
}
|
|
6
|
+
export declare class CameraController extends MatterbridgeEndpoint {
|
|
7
|
+
constructor(name: string, serial: string, options?: CameraControllerOptions);
|
|
8
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { addWebRtcTransportProviderClient } from '../behaviors/clients.js';
|
|
2
|
+
import { createDefaultWebRtcTransportRequestorClusterServer } from '../behaviors/webRtcTransportRequestorServer.js';
|
|
3
|
+
import { cameraController, powerSource } from '../matterbridgeDeviceTypes.js';
|
|
4
|
+
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
5
|
+
export class CameraController extends MatterbridgeEndpoint {
|
|
6
|
+
constructor(name, serial, options = {}) {
|
|
7
|
+
const { powerSourceType = 'Wired', id, number, tagList, mode } = options;
|
|
8
|
+
super(powerSourceType === 'None' ? [cameraController] : [cameraController, powerSource], {
|
|
9
|
+
id: id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
|
|
10
|
+
number,
|
|
11
|
+
tagList,
|
|
12
|
+
mode,
|
|
13
|
+
});
|
|
14
|
+
this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Camera Controller');
|
|
15
|
+
switch (powerSourceType) {
|
|
16
|
+
case 'Rechargeable':
|
|
17
|
+
this.createDefaultPowerSourceRechargeableBatteryClusterServer();
|
|
18
|
+
break;
|
|
19
|
+
case 'Replaceable':
|
|
20
|
+
this.createDefaultPowerSourceReplaceableBatteryClusterServer();
|
|
21
|
+
break;
|
|
22
|
+
case 'Battery':
|
|
23
|
+
this.createDefaultPowerSourceBatteryClusterServer();
|
|
24
|
+
break;
|
|
25
|
+
case 'Wired':
|
|
26
|
+
this.createDefaultPowerSourceWiredClusterServer();
|
|
27
|
+
break;
|
|
28
|
+
case 'None':
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
createDefaultWebRtcTransportRequestorClusterServer(this);
|
|
32
|
+
addWebRtcTransportProviderClient(this);
|
|
33
|
+
this.addRequiredClusters();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { Semtag } from '@matter/types';
|
|
2
|
+
import type { EndpointNumber } from '@matter/types/datatype';
|
|
2
3
|
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
3
4
|
import type { MatterbridgeEndpointOptions } from '../matterbridgeEndpointTypes.js';
|
|
4
5
|
import type { CameraOptions } from './camera.js';
|
|
5
|
-
export type FloodlightCameraCameraOptions = Omit<CameraOptions, 'id' | '
|
|
6
|
+
export type FloodlightCameraCameraOptions = Omit<CameraOptions, 'id' | 'mode' | 'powerSourceType'>;
|
|
6
7
|
export interface FloodlightCameraLightOptions {
|
|
7
8
|
name?: string;
|
|
8
9
|
tagList?: Semtag[];
|
|
10
|
+
number?: EndpointNumber;
|
|
9
11
|
onOff?: boolean;
|
|
10
12
|
}
|
|
11
13
|
export interface FloodlightCameraOptions extends MatterbridgeEndpointOptions {
|
|
@@ -15,5 +17,5 @@ export interface FloodlightCameraOptions extends MatterbridgeEndpointOptions {
|
|
|
15
17
|
}
|
|
16
18
|
export declare class FloodlightCamera extends MatterbridgeEndpoint {
|
|
17
19
|
constructor(name: string, serial: string, options?: FloodlightCameraOptions);
|
|
18
|
-
addLight(name: string,
|
|
20
|
+
addLight(name: string, options?: FloodlightCameraLightOptions): MatterbridgeEndpoint;
|
|
19
21
|
}
|
|
@@ -43,8 +43,8 @@ export class FloodlightCamera extends MatterbridgeEndpoint {
|
|
|
43
43
|
{ resolution: { width: 640, height: 480 }, maxFrameRate: 10, imageCodec: CameraAvStreamManagement.ImageCodec.Jpeg, requiresEncodedPixels: false },
|
|
44
44
|
{ resolution: { width: 1280, height: 720 }, maxFrameRate: 10, imageCodec: CameraAvStreamManagement.ImageCodec.Jpeg, requiresEncodedPixels: false },
|
|
45
45
|
{ resolution: { width: 1920, height: 1080 }, maxFrameRate: 10, imageCodec: CameraAvStreamManagement.ImageCodec.Jpeg, requiresEncodedPixels: false },
|
|
46
|
-
], weriftOfferOptions, } = cameraOptions;
|
|
47
|
-
const cameraChild = this.addChildDeviceType('Camera', camera, {});
|
|
46
|
+
], weriftOfferOptions, number: cameraNumber, tagList: cameraTagList = [], } = cameraOptions;
|
|
47
|
+
const cameraChild = this.addChildDeviceType('Camera', camera, { number: cameraNumber, ...(cameraTagList.length > 0 ? { tagList: cameraTagList } : {}) });
|
|
48
48
|
cameraChild.log.logName = 'Camera';
|
|
49
49
|
if (identifyType !== Identify.IdentifyType.None) {
|
|
50
50
|
cameraChild.createDefaultIdentifyClusterServer(identifyTime, identifyType);
|
|
@@ -67,11 +67,12 @@ export class FloodlightCamera extends MatterbridgeEndpoint {
|
|
|
67
67
|
createDefaultWebRtcTransportProviderClusterServer(cameraChild, weriftOfferOptions);
|
|
68
68
|
addWebRtcTransportRequestorClient(cameraChild);
|
|
69
69
|
cameraChild.addRequiredClusters();
|
|
70
|
-
const { name: lightName = 'Light', tagList: lightTagList = [], onOff: lightOnOff = false } = lightOptions;
|
|
71
|
-
this.addLight(lightName, lightTagList, lightOnOff);
|
|
70
|
+
const { name: lightName = 'Light', tagList: lightTagList = [], number: lightNumber, onOff: lightOnOff = false } = lightOptions;
|
|
71
|
+
this.addLight(lightName, { tagList: lightTagList, number: lightNumber, onOff: lightOnOff });
|
|
72
72
|
}
|
|
73
|
-
addLight(name,
|
|
74
|
-
const
|
|
73
|
+
addLight(name, options = {}) {
|
|
74
|
+
const { tagList = [], number, onOff = false } = options;
|
|
75
|
+
const light = this.addChildDeviceType(name, onOffLight, { number, ...(tagList.length > 0 ? { tagList } : {}) });
|
|
75
76
|
light.log.logName = name;
|
|
76
77
|
light.createDefaultIdentifyClusterServer();
|
|
77
78
|
light.createDefaultOnOffClusterServer(onOff);
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import type { Semtag } from '@matter/types';
|
|
2
2
|
import { Identify } from '@matter/types/clusters/identify';
|
|
3
|
+
import type { EndpointNumber } from '@matter/types/datatype';
|
|
3
4
|
import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
4
5
|
import type { MatterbridgeEndpointOptions } from '../matterbridgeEndpointTypes.js';
|
|
5
6
|
import type { CameraOptions } from './camera.js';
|
|
6
|
-
export type VideoDoorbellCameraOptions = Omit<CameraOptions, 'id' | '
|
|
7
|
+
export type VideoDoorbellCameraOptions = Omit<CameraOptions, 'id' | 'mode' | 'powerSourceType'>;
|
|
7
8
|
export interface VideoDoorbellDoorbellOptions {
|
|
8
9
|
name?: string;
|
|
9
10
|
tagList?: Semtag[];
|
|
11
|
+
number?: EndpointNumber;
|
|
10
12
|
identifyTime?: number;
|
|
11
13
|
identifyType?: Identify.IdentifyType;
|
|
12
14
|
}
|
|
@@ -17,5 +19,5 @@ export interface VideoDoorbellOptions extends MatterbridgeEndpointOptions {
|
|
|
17
19
|
}
|
|
18
20
|
export declare class VideoDoorbell extends MatterbridgeEndpoint {
|
|
19
21
|
constructor(name: string, serial: string, options?: VideoDoorbellOptions);
|
|
20
|
-
addDoorbell(name: string,
|
|
22
|
+
addDoorbell(name: string, options?: VideoDoorbellDoorbellOptions): MatterbridgeEndpoint;
|
|
21
23
|
}
|
|
@@ -43,8 +43,8 @@ export class VideoDoorbell extends MatterbridgeEndpoint {
|
|
|
43
43
|
{ resolution: { width: 640, height: 480 }, maxFrameRate: 10, imageCodec: CameraAvStreamManagement.ImageCodec.Jpeg, requiresEncodedPixels: false },
|
|
44
44
|
{ resolution: { width: 1280, height: 720 }, maxFrameRate: 10, imageCodec: CameraAvStreamManagement.ImageCodec.Jpeg, requiresEncodedPixels: false },
|
|
45
45
|
{ resolution: { width: 1920, height: 1080 }, maxFrameRate: 10, imageCodec: CameraAvStreamManagement.ImageCodec.Jpeg, requiresEncodedPixels: false },
|
|
46
|
-
], weriftOfferOptions, } = cameraOptions;
|
|
47
|
-
const cameraChild = this.addChildDeviceType('Camera', camera, {});
|
|
46
|
+
], weriftOfferOptions, number: cameraNumber, tagList: cameraTagList = [], } = cameraOptions;
|
|
47
|
+
const cameraChild = this.addChildDeviceType('Camera', camera, { number: cameraNumber, ...(cameraTagList.length > 0 ? { tagList: cameraTagList } : {}) });
|
|
48
48
|
cameraChild.log.logName = 'Camera';
|
|
49
49
|
if (cameraIdentifyType !== Identify.IdentifyType.None) {
|
|
50
50
|
cameraChild.createDefaultIdentifyClusterServer(cameraIdentifyTime, cameraIdentifyType);
|
|
@@ -67,11 +67,12 @@ export class VideoDoorbell extends MatterbridgeEndpoint {
|
|
|
67
67
|
createDefaultWebRtcTransportProviderClusterServer(cameraChild, weriftOfferOptions);
|
|
68
68
|
addWebRtcTransportRequestorClient(cameraChild);
|
|
69
69
|
cameraChild.addRequiredClusters();
|
|
70
|
-
const { name: doorbellName = 'Doorbell', tagList: doorbellTagList = [], identifyTime = 0, identifyType = Identify.IdentifyType.None } = doorbellOptions;
|
|
71
|
-
this.addDoorbell(doorbellName, doorbellTagList, identifyTime, identifyType);
|
|
70
|
+
const { name: doorbellName = 'Doorbell', tagList: doorbellTagList = [], number: doorbellNumber, identifyTime = 0, identifyType = Identify.IdentifyType.None } = doorbellOptions;
|
|
71
|
+
this.addDoorbell(doorbellName, { tagList: doorbellTagList, number: doorbellNumber, identifyTime, identifyType });
|
|
72
72
|
}
|
|
73
|
-
addDoorbell(name,
|
|
74
|
-
const
|
|
73
|
+
addDoorbell(name, options = {}) {
|
|
74
|
+
const { tagList = [], number, identifyTime = 0, identifyType = Identify.IdentifyType.None } = options;
|
|
75
|
+
const doorbellChild = this.addChildDeviceType(name, doorbell, { number, ...(tagList.length > 0 ? { tagList } : {}) });
|
|
75
76
|
doorbellChild.log.logName = name;
|
|
76
77
|
doorbellChild.createDefaultIdentifyClusterServer(identifyTime, identifyType);
|
|
77
78
|
doorbellChild.createDefaultMomentarySwitchClusterServer();
|
package/dist/helpers.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ import type { AggregatorEndpoint } from '@matter/node/endpoints/aggregator';
|
|
|
3
3
|
import type { Matterbridge } from './matterbridge.js';
|
|
4
4
|
export declare function addVirtualDevice(aggregatorEndpoint: Endpoint<AggregatorEndpoint>, name: string, type: 'light' | 'outlet' | 'switch' | 'mounted_switch', callback: () => Promise<void>): Promise<Endpoint>;
|
|
5
5
|
export declare function addVirtualDevices(matterbridge: Matterbridge, aggregatorEndpoint: Endpoint<AggregatorEndpoint>): Promise<void>;
|
|
6
|
+
export declare function resolveRootDirectory(currentFileDirectory: string, maxLevels?: number): Promise<string | undefined>;
|
package/dist/helpers.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
1
3
|
import { Endpoint } from '@matter/node';
|
|
2
4
|
import { BindingServer } from '@matter/node/behaviors/binding';
|
|
3
5
|
import { BridgedDeviceBasicInformationServer } from '@matter/node/behaviors/bridged-device-basic-information';
|
|
@@ -71,3 +73,27 @@ export async function addVirtualDevices(matterbridge, aggregatorEndpoint) {
|
|
|
71
73
|
});
|
|
72
74
|
}
|
|
73
75
|
}
|
|
76
|
+
async function isMatterbridgePackageDirectory(directory) {
|
|
77
|
+
try {
|
|
78
|
+
const packageJson = JSON.parse(await fs.promises.readFile(path.join(directory, 'package.json'), 'utf8'));
|
|
79
|
+
return packageJson?.name === 'matterbridge';
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
export async function resolveRootDirectory(currentFileDirectory, maxLevels = 10) {
|
|
86
|
+
let directory = currentFileDirectory;
|
|
87
|
+
for (let level = 0; level < maxLevels; level++) {
|
|
88
|
+
if (await isMatterbridgePackageDirectory(directory))
|
|
89
|
+
return directory;
|
|
90
|
+
const nodeModulesDirectory = path.join(directory, 'node_modules', 'matterbridge');
|
|
91
|
+
if (await isMatterbridgePackageDirectory(nodeModulesDirectory))
|
|
92
|
+
return nodeModulesDirectory;
|
|
93
|
+
const parentDirectory = path.dirname(directory);
|
|
94
|
+
if (parentDirectory === directory)
|
|
95
|
+
break;
|
|
96
|
+
directory = parentDirectory;
|
|
97
|
+
}
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
package/dist/matterbridge.js
CHANGED
|
@@ -30,7 +30,7 @@ import { AnsiLogger, BLUE, BRIGHT, CYAN, db, debugStringify, er, GREEN, nf, nt,
|
|
|
30
30
|
import { NodeStorageManager } from 'node-persist-manager';
|
|
31
31
|
import { DeviceManager } from './deviceManager.js';
|
|
32
32
|
import { Frontend } from './frontend.js';
|
|
33
|
-
import { addVirtualDevice, addVirtualDevices } from './helpers.js';
|
|
33
|
+
import { addVirtualDevice, addVirtualDevices, resolveRootDirectory } from './helpers.js';
|
|
34
34
|
import { bridge } from './matterbridgeDeviceTypes.js';
|
|
35
35
|
import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
|
|
36
36
|
import { PluginManager } from './pluginManager.js';
|
|
@@ -408,25 +408,14 @@ export class Matterbridge extends EventEmitter {
|
|
|
408
408
|
await createDirectory(this.matterbridgeCertDirectory, 'Matterbridge Matter Certificate Directory', this.log);
|
|
409
409
|
const currentFileDirectory = path.dirname(fileURLToPath(import.meta.url));
|
|
410
410
|
this.log.debug(`Determining root directory from currentFileDirectory = ${CYAN}${currentFileDirectory}${db}`);
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
this.log.
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
if (isBun()) {
|
|
422
|
-
this.rootDirectory = path.join(getGlobalBunModules(), 'matterbridge');
|
|
423
|
-
this.log.debug(`Found bun global core >>> root directory: ${CYAN}${this.rootDirectory}${db}`);
|
|
424
|
-
}
|
|
425
|
-
else {
|
|
426
|
-
this.rootDirectory = path.resolve(currentFileDirectory, '..', '..', '..', '..');
|
|
427
|
-
this.log.debug(`Found production core >>> root directory: ${CYAN}${this.rootDirectory}${db}`);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
411
|
+
const rootDirectory = await resolveRootDirectory(currentFileDirectory);
|
|
412
|
+
if (rootDirectory === undefined) {
|
|
413
|
+
const message = `Cannot determine the matterbridge root directory from ${currentFileDirectory}: no matterbridge package.json found in the parent directories.`;
|
|
414
|
+
this.log.fatal(message);
|
|
415
|
+
throw new Error(message);
|
|
416
|
+
}
|
|
417
|
+
this.rootDirectory = rootDirectory;
|
|
418
|
+
this.log.debug(`Found root directory: ${CYAN}${this.rootDirectory}${db}`);
|
|
430
419
|
this.environment.vars.set('log.level', MatterLogLevel.DEBUG);
|
|
431
420
|
this.environment.vars.set('log.format', hasParameter('no-ansi') || process.env.NO_COLOR === '1' ? MatterLogFormat.PLAIN : MatterLogFormat.ANSI);
|
|
432
421
|
this.environment.vars.set('path.root', path.join(this.matterbridgeDirectory, MATTER_STORAGE_DIR));
|
|
@@ -30,6 +30,7 @@ import type { DeviceTypeDefinition } from './matterbridgeDeviceTypes.js';
|
|
|
30
30
|
import { CommandHandler, type CommandHandlerData, type CommandHandlerExecutionResult, type CommandHandlerFunction, type CommandHandlers } from './matterbridgeEndpointCommandHandler.js';
|
|
31
31
|
import type { MatterbridgeEndpointOptions, SerializedMatterbridgeEndpoint, SubscribeCommandListener } from './matterbridgeEndpointTypes.js';
|
|
32
32
|
type FirstCommandParam<Params extends unknown[]> = Params extends [] ? undefined : Params[0];
|
|
33
|
+
type CommandRequest<P> = [P] extends [undefined] ? Record<string, never> : P;
|
|
33
34
|
type BehaviorCluster<T extends Behavior.Type> = T extends {
|
|
34
35
|
cluster: infer C extends ClusterType;
|
|
35
36
|
} ? C : ClusterType;
|
|
@@ -109,6 +110,9 @@ export declare class MatterbridgeEndpoint extends Endpoint {
|
|
|
109
110
|
subscribeCommand<T extends Behavior.Type, C extends BehaviorCommandName<T>>(cluster: T, command: C, listener: SubscribeCommandListener<BehaviorCommandParams<T, C>>, log?: AnsiLogger): MatterbridgeEndpoint;
|
|
110
111
|
subscribeCommand<T extends ClusterType, C extends ClusterCommandName<T>>(cluster: T, command: C, listener: SubscribeCommandListener<ClusterCommandParams<T, C>>, log?: AnsiLogger): MatterbridgeEndpoint;
|
|
111
112
|
subscribeCommand(cluster: ClusterId | string, command: string, listener: SubscribeCommandListener, log?: AnsiLogger): MatterbridgeEndpoint;
|
|
113
|
+
emitCommand<T extends Behavior.Type, C extends BehaviorCommandName<T>>(cluster: T, command: C, request: CommandRequest<BehaviorCommandParams<T, C>>, context: ActionContext): void;
|
|
114
|
+
emitCommand<T extends ClusterType, C extends ClusterCommandName<T>>(cluster: T, command: C, request: CommandRequest<ClusterCommandParams<T, C>>, context: ActionContext): void;
|
|
115
|
+
emitCommand(cluster: string, command: string, request: unknown, context: ActionContext): void;
|
|
112
116
|
setCluster<T extends Behavior.Type>(cluster: T, value: Behavior.StateOf<T>, log?: AnsiLogger): Promise<boolean>;
|
|
113
117
|
setCluster<T extends ClusterType>(cluster: T, value: Partial<ClusterAttributesOf<T>>, log?: AnsiLogger): Promise<boolean>;
|
|
114
118
|
setCluster(cluster: ClusterId | string, value: Record<string, boolean | number | bigint | string | object | undefined | null>, log?: AnsiLogger): Promise<boolean>;
|
|
@@ -149,7 +153,7 @@ export declare class MatterbridgeEndpoint extends Endpoint {
|
|
|
149
153
|
createDefaultPowerSourceReplaceableBatteryClusterServer(batPercentRemaining?: number | null, batChargeLevel?: PowerSource.BatChargeLevel, batVoltage?: number | null, batReplacementDescription?: string, batQuantity?: number, batReplaceability?: PowerSource.BatReplaceability): this;
|
|
150
154
|
createDefaultPowerSourceRechargeableBatteryClusterServer(batPercentRemaining?: number | null, batChargeLevel?: PowerSource.BatChargeLevel, batVoltage?: number | null, batReplaceability?: PowerSource.BatReplaceability): this;
|
|
151
155
|
createDefaultBasicInformationClusterServer(deviceName: string, serialNumber: string, vendorId?: number, vendorName?: string, productId?: number, productName?: string, softwareVersion?: number, softwareVersionString?: string, hardwareVersion?: number, hardwareVersionString?: string, productLabel?: string, productUrl?: string, configurationVersion?: number): this;
|
|
152
|
-
createDefaultBridgedDeviceBasicInformationClusterServer(deviceName: string, serialNumber: string, vendorId?: number, vendorName?: string, productName?: string, softwareVersion?: number, softwareVersionString?: string, hardwareVersion?: number, hardwareVersionString?: string, productLabel?: string, productUrl?: string, configurationVersion?: number): this;
|
|
156
|
+
createDefaultBridgedDeviceBasicInformationClusterServer(deviceName: string, serialNumber: string, vendorId?: number, vendorName?: string, productName?: string, softwareVersion?: number, softwareVersionString?: string, hardwareVersion?: number, hardwareVersionString?: string, productLabel?: string, productUrl?: string, configurationVersion?: number, productId?: number): this;
|
|
153
157
|
createDefaultPowerTopologyClusterServer(feature?: PowerTopology.Feature, availableEndpoints?: EndpointNumber[], activeEndpoints?: EndpointNumber[]): this;
|
|
154
158
|
createDefaultElectricalEnergyMeasurementClusterServer(energyImported?: number | bigint | null, energyExported?: number | bigint | null): this;
|
|
155
159
|
createImportedElectricalEnergyMeasurementClusterServer(energyImported?: number | bigint | null): this;
|
|
@@ -85,7 +85,7 @@ import { MatterbridgeValveConfigurationAndControlServer } from './behaviors/valv
|
|
|
85
85
|
import { MatterbridgeWaterTankLevelMonitoringServer } from './behaviors/waterTankLevelMonitoringServer.js';
|
|
86
86
|
import { MatterbridgeWindowCoveringServer } from './behaviors/windowCoveringServer.js';
|
|
87
87
|
import { CommandHandler, } from './matterbridgeEndpointCommandHandler.js';
|
|
88
|
-
import { addClusterClients, addClusterServers, addFixedLabel, addOptionalClusterClients, addOptionalClusterServers, addRequiredClusterClients, addRequiredClusterServers, addUserLabel, checkNotLatinCharacters, createUniqueId, defaultFor, featuresFor, generateUniqueId, getApparentElectricalPowerMeasurementClusterServer, getAttribute, getAttributeId, getBehavior, getBehaviourTypesFromClusterClientIds, getBehaviourTypesFromClusterServerIds, getCluster, getClusterId, getDefaultDeviceEnergyManagementClusterServer, getDefaultDeviceEnergyManagementModeClusterServer, getDefaultElectricalEnergyMeasurementClusterServer, getDefaultElectricalPowerMeasurementClusterServer, getDefaultFlowMeasurementClusterServer, getDefaultIlluminanceMeasurementClusterServer, getDefaultOccupancySensingClusterServer, getDefaultOperationalStateClusterServer, getDefaultPowerSourceBatteryClusterServer, getDefaultPowerSourceRechargeableBatteryClusterServer, getDefaultPowerSourceReplaceableBatteryClusterServer, getDefaultPowerSourceWiredClusterServer, getDefaultPressureMeasurementClusterServer, getDefaultRelativeHumidityMeasurementClusterServer, getDefaultSoilMeasurementClusterServer, getDefaultTemperatureMeasurementClusterServer, getExportedElectricalEnergyMeasurementClusterServer, getImportedElectricalEnergyMeasurementClusterServer, invokeBehaviorCommand, lowercaseFirstLetter, setAttribute, setCluster, subscribeAttribute, subscribeCommand, triggerEvent, updateAttribute, } from './matterbridgeEndpointHelpers.js';
|
|
88
|
+
import { addClusterClients, addClusterServers, addFixedLabel, addOptionalClusterClients, addOptionalClusterServers, addRequiredClusterClients, addRequiredClusterServers, addUserLabel, checkNotLatinCharacters, createUniqueId, defaultFor, emitCommand, featuresFor, generateUniqueId, getApparentElectricalPowerMeasurementClusterServer, getAttribute, getAttributeId, getBehavior, getBehaviourTypesFromClusterClientIds, getBehaviourTypesFromClusterServerIds, getCluster, getClusterId, getDefaultDeviceEnergyManagementClusterServer, getDefaultDeviceEnergyManagementModeClusterServer, getDefaultElectricalEnergyMeasurementClusterServer, getDefaultElectricalPowerMeasurementClusterServer, getDefaultFlowMeasurementClusterServer, getDefaultIlluminanceMeasurementClusterServer, getDefaultOccupancySensingClusterServer, getDefaultOperationalStateClusterServer, getDefaultPowerSourceBatteryClusterServer, getDefaultPowerSourceRechargeableBatteryClusterServer, getDefaultPowerSourceReplaceableBatteryClusterServer, getDefaultPowerSourceWiredClusterServer, getDefaultPressureMeasurementClusterServer, getDefaultRelativeHumidityMeasurementClusterServer, getDefaultSoilMeasurementClusterServer, getDefaultTemperatureMeasurementClusterServer, getExportedElectricalEnergyMeasurementClusterServer, getImportedElectricalEnergyMeasurementClusterServer, invokeBehaviorCommand, lowercaseFirstLetter, setAttribute, setCluster, subscribeAttribute, subscribeCommand, triggerEvent, updateAttribute, } from './matterbridgeEndpointHelpers.js';
|
|
89
89
|
logModuleLoaded('MatterbridgeEndpoint');
|
|
90
90
|
const MATTERBRIDGE_ENDPOINT_BRAND = Symbol('MatterbridgeEndpoint.brand');
|
|
91
91
|
export function isMatterbridgeEndpoint(value) {
|
|
@@ -254,6 +254,10 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
254
254
|
subscribeCommand(cluster, command, listener, log) {
|
|
255
255
|
return subscribeCommand(this, cluster, command, listener, log);
|
|
256
256
|
}
|
|
257
|
+
emitCommand(cluster, command, request, context) {
|
|
258
|
+
const clusterName = typeof cluster === 'string' ? cluster : typeof cluster.id === 'string' ? cluster.id : cluster.name;
|
|
259
|
+
emitCommand(this, clusterName, command, request, context);
|
|
260
|
+
}
|
|
257
261
|
async setCluster(cluster, value, log) {
|
|
258
262
|
return await setCluster(this, cluster, value, log);
|
|
259
263
|
}
|
|
@@ -518,7 +522,7 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
518
522
|
device.hardwareVersionString = serializedDevice.hardwareVersionString;
|
|
519
523
|
for (const clusterId of serializedDevice.clusterServersId) {
|
|
520
524
|
if (clusterId === BridgedDeviceBasicInformation.id)
|
|
521
|
-
device.createDefaultBridgedDeviceBasicInformationClusterServer(serializedDevice.deviceName, serializedDevice.serialNumber, serializedDevice.vendorId ?? 0xfff1, serializedDevice.vendorName ?? 'Matterbridge', serializedDevice.productName ?? 'Matterbridge device', serializedDevice.softwareVersion, serializedDevice.softwareVersionString, serializedDevice.hardwareVersion, serializedDevice.hardwareVersionString, serializedDevice.productLabel, serializedDevice.productUrl, serializedDevice.configurationVersion);
|
|
525
|
+
device.createDefaultBridgedDeviceBasicInformationClusterServer(serializedDevice.deviceName, serializedDevice.serialNumber, serializedDevice.vendorId ?? 0xfff1, serializedDevice.vendorName ?? 'Matterbridge', serializedDevice.productName ?? 'Matterbridge device', serializedDevice.softwareVersion, serializedDevice.softwareVersionString, serializedDevice.hardwareVersion, serializedDevice.hardwareVersionString, serializedDevice.productLabel, serializedDevice.productUrl, serializedDevice.configurationVersion, serializedDevice.productId);
|
|
522
526
|
else if (clusterId === BasicInformation.id)
|
|
523
527
|
device.createDefaultBasicInformationClusterServer(serializedDevice.deviceName, serializedDevice.serialNumber, serializedDevice.vendorId ?? 0xfff1, serializedDevice.vendorName ?? 'Matterbridge', serializedDevice.productId ?? 0x8000, serializedDevice.productName ?? 'Matterbridge device', serializedDevice.softwareVersion, serializedDevice.softwareVersionString, serializedDevice.hardwareVersion, serializedDevice.hardwareVersionString, serializedDevice.productLabel, serializedDevice.productUrl, serializedDevice.configurationVersion);
|
|
524
528
|
else if (clusterId === PowerSource.id)
|
|
@@ -560,12 +564,12 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
560
564
|
this.configurationVersion = configurationVersion;
|
|
561
565
|
return this;
|
|
562
566
|
}
|
|
563
|
-
createDefaultBridgedDeviceBasicInformationClusterServer(deviceName, serialNumber, vendorId = 0xfff1, vendorName = 'Matterbridge', productName = 'Matterbridge device', softwareVersion = 1, softwareVersionString = '1.0.0', hardwareVersion = 1, hardwareVersionString = '1.0.0', productLabel = 'Matter Bridged Endpoint', productUrl = 'https://matterbridge.io', configurationVersion = 1) {
|
|
567
|
+
createDefaultBridgedDeviceBasicInformationClusterServer(deviceName, serialNumber, vendorId = 0xfff1, vendorName = 'Matterbridge', productName = 'Matterbridge device', softwareVersion = 1, softwareVersionString = '1.0.0', hardwareVersion = 1, hardwareVersionString = '1.0.0', productLabel = 'Matter Bridged Endpoint', productUrl = 'https://matterbridge.io', configurationVersion = 1, productId) {
|
|
564
568
|
this.log.logName = deviceName;
|
|
565
569
|
this.deviceName = deviceName;
|
|
566
570
|
this.serialNumber = serialNumber;
|
|
567
571
|
this.uniqueId = createUniqueId(deviceName, serialNumber, vendorName, productName);
|
|
568
|
-
this.productId =
|
|
572
|
+
this.productId = productId;
|
|
569
573
|
this.productName = productName;
|
|
570
574
|
this.productLabel = productLabel;
|
|
571
575
|
this.productUrl = productUrl;
|
|
@@ -593,6 +597,7 @@ export class MatterbridgeEndpoint extends Endpoint {
|
|
|
593
597
|
hardwareVersionString: isValidString(hardwareVersionString, 1, 64) ? hardwareVersionString : '1.0.0',
|
|
594
598
|
configurationVersion: isValidInteger(configurationVersion, 1, UINT32_MAX) ? configurationVersion : 1,
|
|
595
599
|
reachable: true,
|
|
600
|
+
...(isValidInteger(productId, 0, UINT16_MAX) ? { productId } : {}),
|
|
596
601
|
});
|
|
597
602
|
return this;
|
|
598
603
|
}
|
|
@@ -59,7 +59,7 @@ export declare function setAttribute(endpoint: MatterbridgeEndpoint, cluster: Be
|
|
|
59
59
|
export declare function updateAttribute(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, attribute: string, value: boolean | number | bigint | string | object | null, log?: AnsiLogger): Promise<boolean>;
|
|
60
60
|
export declare function subscribeAttribute(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, attribute: string, listener: (newValue: any, oldValue: any, context: ActionContext) => void, log?: AnsiLogger): MatterbridgeEndpoint;
|
|
61
61
|
export declare function subscribeCommand(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, command: string, listener: SubscribeCommandListener, log?: AnsiLogger): MatterbridgeEndpoint;
|
|
62
|
-
export declare function emitCommand(endpoint:
|
|
62
|
+
export declare function emitCommand(endpoint: MatterbridgeEndpoint, cluster: string, command: string, request: unknown, context: ActionContext): void;
|
|
63
63
|
export declare function setCluster(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, value: Record<string, boolean | number | bigint | string | object | undefined | null>, log?: AnsiLogger): Promise<boolean>;
|
|
64
64
|
export declare function getCluster(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, log?: AnsiLogger): Record<string, boolean | number | bigint | string | object | undefined | null> | undefined;
|
|
65
65
|
export declare function triggerEvent(endpoint: MatterbridgeEndpoint, cluster: Behavior.Type | ClusterType | ClusterId | string, event: string, payload: Record<string, boolean | number | bigint | string | object | undefined | null>, log?: AnsiLogger): Promise<boolean>;
|
|
@@ -836,15 +836,10 @@ export function subscribeCommand(endpoint, cluster, command, listener, log) {
|
|
|
836
836
|
return endpoint;
|
|
837
837
|
}
|
|
838
838
|
export function emitCommand(endpoint, cluster, command, request, context) {
|
|
839
|
-
if (!isCommandEndpoint(endpoint))
|
|
840
|
-
return;
|
|
841
839
|
const clusterName = lowercaseFirstLetter(cluster);
|
|
842
840
|
const commandName = lowercaseFirstLetter(command);
|
|
843
841
|
getCommandObservable(endpoint, clusterName, commandName, false)?.emit({ command: commandName, cluster: clusterName, request, endpoint, context });
|
|
844
842
|
}
|
|
845
|
-
function isCommandEndpoint(endpoint) {
|
|
846
|
-
return 'subscribeCommand' in endpoint && typeof endpoint.subscribeCommand === 'function';
|
|
847
|
-
}
|
|
848
843
|
export async function setCluster(endpoint, cluster, value, log) {
|
|
849
844
|
const clusterName = getBehavior(endpoint, cluster)?.id;
|
|
850
845
|
if (!clusterName) {
|
|
@@ -247,7 +247,7 @@ export class MatterbridgePlatform {
|
|
|
247
247
|
}
|
|
248
248
|
if (!device.hasClusterServer(BridgedDeviceBasicInformation.id)) {
|
|
249
249
|
this.log.debug(`Device with name ${CYAN}${device.deviceName}${db} has no BridgedDeviceBasicInformation cluster. Adding it...`);
|
|
250
|
-
device.createDefaultBridgedDeviceBasicInformationClusterServer(device.deviceName, device.serialNumber, device.vendorId, device.vendorName, device.productName, device.softwareVersion, device.softwareVersionString, device.hardwareVersion, device.hardwareVersionString, device.productLabel === 'Matter Endpoint' ? 'Matter Bridged Endpoint' : device.productLabel, device.productUrl, device.configurationVersion);
|
|
250
|
+
device.createDefaultBridgedDeviceBasicInformationClusterServer(device.deviceName, device.serialNumber, device.vendorId, device.vendorName, device.productName, device.softwareVersion, device.softwareVersionString, device.hardwareVersion, device.hardwareVersionString, device.productLabel === 'Matter Endpoint' ? 'Matter Bridged Endpoint' : device.productLabel, device.productUrl, device.configurationVersion, device.productId);
|
|
251
251
|
}
|
|
252
252
|
}
|
|
253
253
|
await this.#addBridgedEndpoint?.(this.name, device);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@matterbridge/core",
|
|
3
|
-
"version": "3.10.10-dev-
|
|
3
|
+
"version": "3.10.10-dev-20260914-784e019",
|
|
4
4
|
"description": "Matterbridge core library",
|
|
5
5
|
"author": "https://github.com/Luligu",
|
|
6
6
|
"homepage": "https://matterbridge.io/",
|
|
@@ -54,6 +54,10 @@
|
|
|
54
54
|
"types": "./dist/devices/export.d.ts",
|
|
55
55
|
"import": "./dist/devices/export.js"
|
|
56
56
|
},
|
|
57
|
+
"./devices/camera": {
|
|
58
|
+
"types": "./dist/devices/camera/export.d.ts",
|
|
59
|
+
"import": "./dist/devices/camera/export.js"
|
|
60
|
+
},
|
|
57
61
|
"./clusters": {
|
|
58
62
|
"types": "./dist/clusters/export.d.ts",
|
|
59
63
|
"import": "./dist/clusters/export.js"
|
|
@@ -132,10 +136,10 @@
|
|
|
132
136
|
},
|
|
133
137
|
"dependencies": {
|
|
134
138
|
"@matter/main": "0.17.9",
|
|
135
|
-
"@matterbridge/dgram": "3.10.10-dev-
|
|
136
|
-
"@matterbridge/thread": "3.10.10-dev-
|
|
137
|
-
"@matterbridge/types": "3.10.10-dev-
|
|
138
|
-
"@matterbridge/utils": "3.10.10-dev-
|
|
139
|
+
"@matterbridge/dgram": "3.10.10-dev-20260914-784e019",
|
|
140
|
+
"@matterbridge/thread": "3.10.10-dev-20260914-784e019",
|
|
141
|
+
"@matterbridge/types": "3.10.10-dev-20260914-784e019",
|
|
142
|
+
"@matterbridge/utils": "3.10.10-dev-20260914-784e019",
|
|
139
143
|
"escape-html": "1.0.3",
|
|
140
144
|
"express": "5.2.1",
|
|
141
145
|
"express-rate-limit": "8.7.0",
|