@matterbridge/core 3.10.6-dev-20260820-36b52be → 3.10.6-dev-20260821-16f33ac

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.
@@ -3,8 +3,14 @@ import { AirQuality } from '@matter/types/clusters/air-quality';
3
3
  import { FanControl } from '@matter/types/clusters/fan-control';
4
4
  import { PowerSource } from '@matter/types/clusters/power-source';
5
5
  import { EndpointNumber } from '@matter/types/datatype';
6
+ import { BasicVideoPlayer } from './devices/basicVideoPlayer.js';
7
+ import { CastingVideoClient } from './devices/castingVideoClient.js';
8
+ import { CastingVideoPlayer } from './devices/castingVideoPlayer.js';
6
9
  import { Closure } from './devices/closure.js';
10
+ import { ContentApp } from './devices/contentApp.js';
7
11
  import { IrrigationSystem } from './devices/irrigationSystem.js';
12
+ import { Speaker } from './devices/speaker.js';
13
+ import { VideoRemoteControl } from './devices/videoRemoteControl.js';
8
14
  import { getSupportedDeviceType } from './matterbridgeDeviceTypes.js';
9
15
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
10
16
  import { getSemtag } from './matterbridgeEndpointHelpers.js';
@@ -251,4 +257,43 @@ export async function createDemoDevices(matterbridge) {
251
257
  await registerDevice(ep, 'Air Purifier', 'HVAC-09-03');
252
258
  ep = new MatterbridgeEndpoint([getSupportedDeviceType('ThermostatController'), bridgedNode, powerSource], { id: 'ThermostatController', number: EndpointNumber(9_04) });
253
259
  await registerDevice(ep, 'Thermostat Controller', 'HVAC-09-04');
260
+ ep = new BasicVideoPlayer('Basic Video Player', 'MEDIA-10-02', { id: 'BasicVideoPlayer', number: EndpointNumber(10_02) });
261
+ await registerDevice(ep, 'Basic Video Player', 'MEDIA-10-02');
262
+ ep = new CastingVideoPlayer('Casting Video Player', 'MEDIA-10-03', { id: 'CastingVideoPlayer', number: EndpointNumber(10_03) });
263
+ await registerDevice(ep, 'Casting Video Player', 'MEDIA-10-03');
264
+ ep = new Speaker('Speaker', 'MEDIA-10-04', { id: 'Speaker', number: EndpointNumber(10_04) });
265
+ await registerDevice(ep, 'Speaker', 'MEDIA-10-04');
266
+ ep = new ContentApp('Content App', 'MEDIA-10-05', { id: 'ContentApp', number: EndpointNumber(10_05) });
267
+ await registerDevice(ep, 'Content App', 'MEDIA-10-05');
268
+ ep = new CastingVideoClient('Casting Video Client', 'MEDIA-10-06', { id: 'CastingVideoClient', number: EndpointNumber(10_06) });
269
+ await registerDevice(ep, 'Casting Video Client', 'MEDIA-10-06');
270
+ ep = new VideoRemoteControl('Video Remote Control', 'MEDIA-10-07', { id: 'VideoRemoteControl', number: EndpointNumber(10_07) });
271
+ await registerDevice(ep, 'Video Remote Control', 'MEDIA-10-07');
272
+ ep = new MatterbridgeEndpoint([getSupportedDeviceType('ModeSelect'), bridgedNode, powerSource], { id: 'ModeSelect', number: EndpointNumber(11_01) });
273
+ ep.createDefaultPowerSourceWiredClusterServer();
274
+ ep.createDefaultModeSelectClusterServer('Mode', [
275
+ { label: 'Mode 1', mode: 0, semanticTags: [] },
276
+ { label: 'Mode 2', mode: 1, semanticTags: [] },
277
+ ]);
278
+ await registerDevice(ep, 'Mode Select', 'GENERIC-11-01');
279
+ ep = new MatterbridgeEndpoint([getSupportedDeviceType('Aggregator'), bridgedNode, powerSource], { id: 'Aggregator', number: EndpointNumber(11_02) });
280
+ ep.createDefaultPowerSourceWiredClusterServer();
281
+ await ep.addFixedLabel('composed', 'Aggregator');
282
+ ep.addChildDeviceType('Plug1', getSupportedDeviceType('OnOffPlugInUnit'), {
283
+ number: EndpointNumber(11_02_1),
284
+ tagList: [getSemtag(CommonNumberTag.One)],
285
+ }).addRequiredClusters();
286
+ ep.addChildDeviceType('Plug2', getSupportedDeviceType('OnOffPlugInUnit'), {
287
+ number: EndpointNumber(11_02_2),
288
+ tagList: [getSemtag(CommonNumberTag.Two)],
289
+ }).addRequiredClusters();
290
+ ep.addChildDeviceType('Plug3', getSupportedDeviceType('OnOffPlugInUnit'), {
291
+ number: EndpointNumber(11_02_3),
292
+ tagList: [getSemtag(CommonNumberTag.Three)],
293
+ }).addRequiredClusters();
294
+ ep.addChildDeviceType('Plug4', getSupportedDeviceType('OnOffPlugInUnit'), {
295
+ number: EndpointNumber(11_02_4),
296
+ tagList: [getSemtag(CommonNumberTag.Four)],
297
+ }).addRequiredClusters();
298
+ await registerDevice(ep, 'Aggregator', 'GENERIC-11-02');
254
299
  }
@@ -1,29 +1,14 @@
1
- import { KeypadInputServer } from '@matter/node/behaviors/keypad-input';
2
- import { MediaPlaybackServer } from '@matter/node/behaviors/media-playback';
3
- import { KeypadInput } from '@matter/types/clusters/keypad-input';
4
1
  import { MediaPlayback } from '@matter/types/clusters/media-playback';
2
+ import type { EndpointNumber } from '@matter/types/datatype';
5
3
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
4
+ import { type MediaPowerSourceType } from './mediaHelpers.js';
6
5
  export interface BasicVideoPlayerOptions {
7
6
  onOff?: boolean;
8
7
  playbackState?: MediaPlayback.PlaybackState;
8
+ powerSourceType?: MediaPowerSourceType;
9
+ id?: string;
10
+ number?: EndpointNumber;
9
11
  }
10
12
  export declare class BasicVideoPlayer extends MatterbridgeEndpoint {
11
13
  constructor(name: string, serial: string, options?: BasicVideoPlayerOptions);
12
- createDefaultMediaPlaybackClusterServer(currentState: MediaPlayback.PlaybackState): this;
13
- createDefaultKeypadInputClusterServer(): this;
14
- }
15
- export declare class MatterbridgeMediaPlaybackServer extends MediaPlaybackServer {
16
- initialize(): void;
17
- protected handleOnOffChange(_onOff: boolean): void;
18
- play(): Promise<MediaPlayback.PlaybackResponse>;
19
- pause(): Promise<MediaPlayback.PlaybackResponse>;
20
- stop(): Promise<MediaPlayback.PlaybackResponse>;
21
- previous(): Promise<MediaPlayback.PlaybackResponse>;
22
- next(): Promise<MediaPlayback.PlaybackResponse>;
23
- skipForward(request: MediaPlayback.SkipForwardRequest): Promise<MediaPlayback.PlaybackResponse>;
24
- skipBackward(request: MediaPlayback.SkipBackwardRequest): Promise<MediaPlayback.PlaybackResponse>;
25
- }
26
- export declare class MatterbridgeKeypadInputServer extends KeypadInputServer {
27
- initialize(): void;
28
- sendKey(request: KeypadInput.SendKeyRequest): Promise<KeypadInput.SendKeyResponse>;
29
14
  }
@@ -1,149 +1,18 @@
1
- import { KeypadInputServer } from '@matter/node/behaviors/keypad-input';
2
- import { MediaPlaybackServer } from '@matter/node/behaviors/media-playback';
3
- import { KeypadInput } from '@matter/types/clusters/keypad-input';
4
1
  import { MediaPlayback } from '@matter/types/clusters/media-playback';
5
- import { MatterbridgeServer } from '../behaviors/matterbridgeServer.js';
6
- import { MatterbridgeOnOffServer } from '../behaviors/onOffServer.js';
7
2
  import { basicVideoPlayer, powerSource } from '../matterbridgeDeviceTypes.js';
8
3
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
4
+ import { createDefaultKeypadInputClusterServer, createDefaultMediaPlaybackClusterServer, createDefaultMediaPowerSourceClusterServer, } from './mediaHelpers.js';
9
5
  export class BasicVideoPlayer extends MatterbridgeEndpoint {
10
6
  constructor(name, serial, options = {}) {
11
- const { onOff = false, playbackState = MediaPlayback.PlaybackState.NotPlaying } = options;
12
- super([basicVideoPlayer, powerSource], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
7
+ const { onOff = false, playbackState = MediaPlayback.PlaybackState.NotPlaying, powerSourceType = 'Wired' } = options;
8
+ super(powerSourceType === 'None' ? [basicVideoPlayer] : [basicVideoPlayer, powerSource], {
9
+ id: options.id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
10
+ number: options.number,
11
+ });
13
12
  this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Basic Video Player');
14
- this.createDefaultPowerSourceWiredClusterServer();
13
+ createDefaultMediaPowerSourceClusterServer(this, powerSourceType);
15
14
  this.createOnOffClusterServer(onOff);
16
- this.createDefaultMediaPlaybackClusterServer(playbackState);
17
- this.createDefaultKeypadInputClusterServer();
18
- }
19
- createDefaultMediaPlaybackClusterServer(currentState) {
20
- this.behaviors.require(MatterbridgeMediaPlaybackServer.enable({
21
- commands: { next: true, previous: true, skipForward: true, skipBackward: true },
22
- }), {
23
- currentState,
24
- });
25
- return this;
26
- }
27
- createDefaultKeypadInputClusterServer() {
28
- this.behaviors.require(MatterbridgeKeypadInputServer, {});
29
- return this;
30
- }
31
- }
32
- export class MatterbridgeMediaPlaybackServer extends MediaPlaybackServer {
33
- initialize() {
34
- const device = this.endpoint.stateOf(MatterbridgeServer);
35
- device.log.info(`MatterbridgeMediaPlaybackServer initialized: currentState is ${this.state.currentState}`);
36
- this.reactTo(this.agent.get(MatterbridgeOnOffServer.with()).events.onOff$Changed, this.handleOnOffChange);
37
- }
38
- handleOnOffChange(_onOff) {
39
- this.state.currentState = MediaPlayback.PlaybackState.NotPlaying;
40
- }
41
- async play() {
42
- const device = this.endpoint.stateOf(MatterbridgeServer);
43
- device.log.info(`Play (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
44
- await device.commandHandler.executeHandler('MediaPlayback.play', {
45
- command: 'play',
46
- request: {},
47
- cluster: MediaPlaybackServer.id,
48
- attributes: this.state,
49
- endpoint: this.endpoint,
50
- });
51
- if (this.endpoint.stateOf(MatterbridgeOnOffServer.with()).onOff)
52
- this.state.currentState = MediaPlayback.PlaybackState.Playing;
53
- return { status: MediaPlayback.Status.Success };
54
- }
55
- async pause() {
56
- const device = this.endpoint.stateOf(MatterbridgeServer);
57
- device.log.info(`Pause (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
58
- await device.commandHandler.executeHandler('MediaPlayback.pause', {
59
- command: 'pause',
60
- request: {},
61
- cluster: MediaPlaybackServer.id,
62
- attributes: this.state,
63
- endpoint: this.endpoint,
64
- });
65
- if (this.endpoint.stateOf(MatterbridgeOnOffServer.with()).onOff)
66
- this.state.currentState = MediaPlayback.PlaybackState.Paused;
67
- return { status: MediaPlayback.Status.Success };
68
- }
69
- async stop() {
70
- const device = this.endpoint.stateOf(MatterbridgeServer);
71
- device.log.info(`Stop (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
72
- await device.commandHandler.executeHandler('MediaPlayback.stop', {
73
- command: 'stop',
74
- request: {},
75
- cluster: MediaPlaybackServer.id,
76
- attributes: this.state,
77
- endpoint: this.endpoint,
78
- });
79
- if (this.endpoint.stateOf(MatterbridgeOnOffServer.with()).onOff)
80
- this.state.currentState = MediaPlayback.PlaybackState.NotPlaying;
81
- return { status: MediaPlayback.Status.Success };
82
- }
83
- async previous() {
84
- const device = this.endpoint.stateOf(MatterbridgeServer);
85
- device.log.info(`Previous (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
86
- await device.commandHandler.executeHandler('MediaPlayback.previous', {
87
- command: 'previous',
88
- request: {},
89
- cluster: MediaPlaybackServer.id,
90
- attributes: this.state,
91
- endpoint: this.endpoint,
92
- });
93
- return { status: MediaPlayback.Status.Success };
94
- }
95
- async next() {
96
- const device = this.endpoint.stateOf(MatterbridgeServer);
97
- device.log.info(`Next (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
98
- await device.commandHandler.executeHandler('MediaPlayback.next', {
99
- command: 'next',
100
- request: {},
101
- cluster: MediaPlaybackServer.id,
102
- attributes: this.state,
103
- endpoint: this.endpoint,
104
- });
105
- return { status: MediaPlayback.Status.Success };
106
- }
107
- async skipForward(request) {
108
- const device = this.endpoint.stateOf(MatterbridgeServer);
109
- device.log.info(`SkipForward (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
110
- await device.commandHandler.executeHandler('MediaPlayback.skipForward', {
111
- command: 'skipForward',
112
- request,
113
- cluster: MediaPlaybackServer.id,
114
- attributes: this.state,
115
- endpoint: this.endpoint,
116
- });
117
- return { status: MediaPlayback.Status.Success };
118
- }
119
- async skipBackward(request) {
120
- const device = this.endpoint.stateOf(MatterbridgeServer);
121
- device.log.info(`SkipBackward (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
122
- await device.commandHandler.executeHandler('MediaPlayback.skipBackward', {
123
- command: 'skipBackward',
124
- request,
125
- cluster: MediaPlaybackServer.id,
126
- attributes: this.state,
127
- endpoint: this.endpoint,
128
- });
129
- return { status: MediaPlayback.Status.Success };
130
- }
131
- }
132
- export class MatterbridgeKeypadInputServer extends KeypadInputServer {
133
- initialize() {
134
- const device = this.endpoint.stateOf(MatterbridgeServer);
135
- device.log.info(`MatterbridgeKeypadInputServer initialized`);
136
- }
137
- async sendKey(request) {
138
- const device = this.endpoint.stateOf(MatterbridgeServer);
139
- device.log.info(`SendKey keyCode ${request.keyCode} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
140
- await device.commandHandler.executeHandler('KeypadInput.sendKey', {
141
- command: 'sendKey',
142
- request,
143
- cluster: KeypadInputServer.id,
144
- attributes: {},
145
- endpoint: this.endpoint,
146
- });
147
- return { status: KeypadInput.Status.Success };
15
+ createDefaultMediaPlaybackClusterServer(this, playbackState, true);
16
+ createDefaultKeypadInputClusterServer(this);
148
17
  }
149
18
  }
@@ -0,0 +1,11 @@
1
+ import type { EndpointNumber } from '@matter/types/datatype';
2
+ import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
3
+ import { type MediaPowerSourceType } from './mediaHelpers.js';
4
+ export interface CastingVideoClientOptions {
5
+ powerSourceType?: MediaPowerSourceType;
6
+ id?: string;
7
+ number?: EndpointNumber;
8
+ }
9
+ export declare class CastingVideoClient extends MatterbridgeEndpoint {
10
+ constructor(name: string, serial: string, options?: CastingVideoClientOptions);
11
+ }
@@ -0,0 +1,19 @@
1
+ import { ApplicationBasic } from '@matter/types/clusters/application-basic';
2
+ import { ContentLauncher } from '@matter/types/clusters/content-launcher';
3
+ import { KeypadInput } from '@matter/types/clusters/keypad-input';
4
+ import { OnOff } from '@matter/types/clusters/on-off';
5
+ import { castingVideoClient, powerSource } from '../matterbridgeDeviceTypes.js';
6
+ import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
7
+ import { createDefaultMediaBindingClusterServer, createDefaultMediaPowerSourceClusterServer } from './mediaHelpers.js';
8
+ export class CastingVideoClient extends MatterbridgeEndpoint {
9
+ constructor(name, serial, options = {}) {
10
+ const { powerSourceType = 'Wired' } = options;
11
+ super(powerSourceType === 'None' ? [castingVideoClient] : [castingVideoClient, powerSource], {
12
+ id: options.id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
13
+ number: options.number,
14
+ });
15
+ this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Casting Video Client');
16
+ createDefaultMediaPowerSourceClusterServer(this, powerSourceType);
17
+ createDefaultMediaBindingClusterServer(this, [OnOff.id, KeypadInput.id, ContentLauncher.id, ApplicationBasic.id]);
18
+ }
19
+ }
@@ -1,16 +1,14 @@
1
- import { ContentLauncherServer } from '@matter/node/behaviors/content-launcher';
2
1
  import { MediaPlayback } from '@matter/types/clusters/media-playback';
2
+ import type { EndpointNumber } from '@matter/types/datatype';
3
3
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
4
+ import { type MediaPowerSourceType } from './mediaHelpers.js';
4
5
  export interface CastingVideoPlayerOptions {
5
6
  onOff?: boolean;
6
7
  playbackState?: MediaPlayback.PlaybackState;
8
+ powerSourceType?: MediaPowerSourceType;
9
+ id?: string;
10
+ number?: EndpointNumber;
7
11
  }
8
12
  export declare class CastingVideoPlayer extends MatterbridgeEndpoint {
9
13
  constructor(name: string, serial: string, options?: CastingVideoPlayerOptions);
10
- createDefaultMediaPlaybackClusterServer(currentState: MediaPlayback.PlaybackState): this;
11
- createDefaultKeypadInputClusterServer(): this;
12
- createDefaultContentLauncherClusterServer(): this;
13
- }
14
- export declare class MatterbridgeContentLauncherServer extends ContentLauncherServer {
15
- initialize(): void;
16
14
  }
@@ -1,38 +1,19 @@
1
- import { ContentLauncherServer } from '@matter/node/behaviors/content-launcher';
2
1
  import { MediaPlayback } from '@matter/types/clusters/media-playback';
3
- import { MatterbridgeServer } from '../behaviors/matterbridgeServer.js';
4
2
  import { castingVideoPlayer, powerSource } from '../matterbridgeDeviceTypes.js';
5
3
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
6
- import { MatterbridgeKeypadInputServer, MatterbridgeMediaPlaybackServer } from './basicVideoPlayer.js';
4
+ import { createDefaultContentLauncherClusterServer, createDefaultKeypadInputClusterServer, createDefaultMediaPlaybackClusterServer, createDefaultMediaPowerSourceClusterServer, } from './mediaHelpers.js';
7
5
  export class CastingVideoPlayer extends MatterbridgeEndpoint {
8
6
  constructor(name, serial, options = {}) {
9
- const { onOff = false, playbackState = MediaPlayback.PlaybackState.NotPlaying } = options;
10
- super([castingVideoPlayer, powerSource], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
7
+ const { onOff = false, playbackState = MediaPlayback.PlaybackState.NotPlaying, powerSourceType = 'Wired' } = options;
8
+ super(powerSourceType === 'None' ? [castingVideoPlayer] : [castingVideoPlayer, powerSource], {
9
+ id: options.id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
10
+ number: options.number,
11
+ });
11
12
  this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Casting Video Player');
12
- this.createDefaultPowerSourceWiredClusterServer();
13
+ createDefaultMediaPowerSourceClusterServer(this, powerSourceType);
13
14
  this.createOnOffClusterServer(onOff);
14
- this.createDefaultMediaPlaybackClusterServer(playbackState);
15
- this.createDefaultKeypadInputClusterServer();
16
- this.createDefaultContentLauncherClusterServer();
17
- }
18
- createDefaultMediaPlaybackClusterServer(currentState) {
19
- this.behaviors.require(MatterbridgeMediaPlaybackServer, {
20
- currentState,
21
- });
22
- return this;
23
- }
24
- createDefaultKeypadInputClusterServer() {
25
- this.behaviors.require(MatterbridgeKeypadInputServer, {});
26
- return this;
27
- }
28
- createDefaultContentLauncherClusterServer() {
29
- this.behaviors.require(MatterbridgeContentLauncherServer, {});
30
- return this;
31
- }
32
- }
33
- export class MatterbridgeContentLauncherServer extends ContentLauncherServer {
34
- initialize() {
35
- const device = this.endpoint.stateOf(MatterbridgeServer);
36
- device.log.info(`MatterbridgeContentLauncherServer initialized`);
15
+ createDefaultMediaPlaybackClusterServer(this, playbackState);
16
+ createDefaultKeypadInputClusterServer(this);
17
+ createDefaultContentLauncherClusterServer(this);
37
18
  }
38
19
  }
@@ -0,0 +1,19 @@
1
+ import { ApplicationBasic } from '@matter/types/clusters/application-basic';
2
+ import { VendorId } from '@matter/types/datatype';
3
+ import type { EndpointNumber } from '@matter/types/datatype';
4
+ import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
5
+ import { type MediaPowerSourceType } from './mediaHelpers.js';
6
+ export interface ContentAppOptions {
7
+ applicationName?: string;
8
+ catalogVendorId?: number;
9
+ applicationId?: string;
10
+ status?: ApplicationBasic.ApplicationStatus;
11
+ applicationVersion?: string;
12
+ allowedVendorList?: VendorId[];
13
+ powerSourceType?: MediaPowerSourceType;
14
+ id?: string;
15
+ number?: EndpointNumber;
16
+ }
17
+ export declare class ContentApp extends MatterbridgeEndpoint {
18
+ constructor(name: string, serial: string, options?: ContentAppOptions);
19
+ }
@@ -0,0 +1,19 @@
1
+ import { ApplicationBasic } from '@matter/types/clusters/application-basic';
2
+ import { VendorId } from '@matter/types/datatype';
3
+ import { contentApp, powerSource } from '../matterbridgeDeviceTypes.js';
4
+ import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
5
+ import { createDefaultApplicationBasicClusterServer, createDefaultApplicationLauncherClusterServer, createDefaultKeypadInputClusterServer, createDefaultMediaPowerSourceClusterServer, } from './mediaHelpers.js';
6
+ export class ContentApp extends MatterbridgeEndpoint {
7
+ constructor(name, serial, options = {}) {
8
+ const { applicationName = name, catalogVendorId = 0xfff1, applicationId = 'matterbridge-content-app', status = ApplicationBasic.ApplicationStatus.ActiveVisibleFocus, applicationVersion = '1.0.0', allowedVendorList = [VendorId(0xfff1)], powerSourceType = 'Wired', } = options;
9
+ super(powerSourceType === 'None' ? [contentApp] : [contentApp, powerSource], {
10
+ id: options.id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
11
+ number: options.number,
12
+ });
13
+ this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Content App');
14
+ createDefaultMediaPowerSourceClusterServer(this, powerSourceType);
15
+ createDefaultKeypadInputClusterServer(this);
16
+ createDefaultApplicationLauncherClusterServer(this);
17
+ createDefaultApplicationBasicClusterServer(this, applicationName, catalogVendorId, applicationId, status, applicationVersion, allowedVendorList);
18
+ }
19
+ }
@@ -1,6 +1,10 @@
1
1
  export * from './basicVideoPlayer.js';
2
+ export * from './castingVideoClient.js';
2
3
  export * from './castingVideoPlayer.js';
4
+ export * from './contentApp.js';
5
+ export * from './mediaHelpers.js';
3
6
  export * from './speaker.js';
7
+ export * from './videoRemoteControl.js';
4
8
  export * from './closure.js';
5
9
  export * from './closurePanel.js';
6
10
  export * from './irrigationSystem.js';
@@ -1,6 +1,10 @@
1
1
  export * from './basicVideoPlayer.js';
2
+ export * from './castingVideoClient.js';
2
3
  export * from './castingVideoPlayer.js';
4
+ export * from './contentApp.js';
5
+ export * from './mediaHelpers.js';
3
6
  export * from './speaker.js';
7
+ export * from './videoRemoteControl.js';
4
8
  export * from './closure.js';
5
9
  export * from './closurePanel.js';
6
10
  export * from './irrigationSystem.js';
@@ -0,0 +1,46 @@
1
+ import { ApplicationBasicServer } from '@matter/node/behaviors/application-basic';
2
+ import { ApplicationLauncherServer } from '@matter/node/behaviors/application-launcher';
3
+ import { ContentLauncherServer } from '@matter/node/behaviors/content-launcher';
4
+ import { KeypadInputServer } from '@matter/node/behaviors/keypad-input';
5
+ import { MediaPlaybackServer } from '@matter/node/behaviors/media-playback';
6
+ import { ApplicationBasic } from '@matter/types/clusters/application-basic';
7
+ import { ApplicationLauncher } from '@matter/types/clusters/application-launcher';
8
+ import { KeypadInput } from '@matter/types/clusters/keypad-input';
9
+ import { MediaPlayback } from '@matter/types/clusters/media-playback';
10
+ import type { ClusterId, VendorId } from '@matter/types/datatype';
11
+ import type { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
12
+ export declare class MatterbridgeMediaPlaybackServer extends MediaPlaybackServer {
13
+ initialize(): void;
14
+ protected handleOnOffChange(_onOff: boolean): void;
15
+ play(): Promise<MediaPlayback.PlaybackResponse>;
16
+ pause(): Promise<MediaPlayback.PlaybackResponse>;
17
+ stop(): Promise<MediaPlayback.PlaybackResponse>;
18
+ previous(): Promise<MediaPlayback.PlaybackResponse>;
19
+ next(): Promise<MediaPlayback.PlaybackResponse>;
20
+ skipForward(request: MediaPlayback.SkipForwardRequest): Promise<MediaPlayback.PlaybackResponse>;
21
+ skipBackward(request: MediaPlayback.SkipBackwardRequest): Promise<MediaPlayback.PlaybackResponse>;
22
+ }
23
+ export declare class MatterbridgeKeypadInputServer extends KeypadInputServer {
24
+ initialize(): void;
25
+ sendKey(request: KeypadInput.SendKeyRequest): Promise<KeypadInput.SendKeyResponse>;
26
+ }
27
+ export declare class MatterbridgeContentLauncherServer extends ContentLauncherServer {
28
+ initialize(): void;
29
+ }
30
+ export declare class MatterbridgeApplicationBasicServer extends ApplicationBasicServer {
31
+ initialize(): void;
32
+ }
33
+ export declare class MatterbridgeApplicationLauncherServer extends ApplicationLauncherServer {
34
+ initialize(): void;
35
+ launchApp(request: ApplicationLauncher.LaunchAppRequest): Promise<ApplicationLauncher.LauncherResponse>;
36
+ stopApp(request: ApplicationLauncher.StopAppRequest): Promise<ApplicationLauncher.LauncherResponse>;
37
+ hideApp(request: ApplicationLauncher.HideAppRequest): Promise<ApplicationLauncher.LauncherResponse>;
38
+ }
39
+ export declare function createDefaultMediaPlaybackClusterServer(endpoint: MatterbridgeEndpoint, currentState: MediaPlayback.PlaybackState, extendedCommands?: boolean): void;
40
+ export declare function createDefaultKeypadInputClusterServer(endpoint: MatterbridgeEndpoint): void;
41
+ export declare function createDefaultContentLauncherClusterServer(endpoint: MatterbridgeEndpoint): void;
42
+ export declare function createDefaultApplicationLauncherClusterServer(endpoint: MatterbridgeEndpoint): void;
43
+ export declare function createDefaultApplicationBasicClusterServer(endpoint: MatterbridgeEndpoint, applicationName: string, catalogVendorId: number, applicationId: string, status: ApplicationBasic.ApplicationStatus, applicationVersion: string, allowedVendorList: VendorId[]): void;
44
+ export declare function createDefaultMediaBindingClusterServer(endpoint: MatterbridgeEndpoint, clientList: ClusterId[]): void;
45
+ export type MediaPowerSourceType = 'Rechargeable' | 'Replaceable' | 'Battery' | 'Wired' | 'None';
46
+ export declare function createDefaultMediaPowerSourceClusterServer(endpoint: MatterbridgeEndpoint, powerSourceType: MediaPowerSourceType): void;
@@ -0,0 +1,281 @@
1
+ import { AccountLoginClient } from '@matter/node/behaviors/account-login';
2
+ import { ApplicationBasicClient, ApplicationBasicServer } from '@matter/node/behaviors/application-basic';
3
+ import { ApplicationLauncherClient, ApplicationLauncherServer } from '@matter/node/behaviors/application-launcher';
4
+ import { AudioOutputClient } from '@matter/node/behaviors/audio-output';
5
+ import { ChannelClient } from '@matter/node/behaviors/channel';
6
+ import { ContentAppObserverClient } from '@matter/node/behaviors/content-app-observer';
7
+ import { ContentControlClient } from '@matter/node/behaviors/content-control';
8
+ import { ContentLauncherClient, ContentLauncherServer } from '@matter/node/behaviors/content-launcher';
9
+ import { KeypadInputClient, KeypadInputServer } from '@matter/node/behaviors/keypad-input';
10
+ import { LevelControlClient } from '@matter/node/behaviors/level-control';
11
+ import { LowPowerClient } from '@matter/node/behaviors/low-power';
12
+ import { MediaInputClient } from '@matter/node/behaviors/media-input';
13
+ import { MediaPlaybackClient, MediaPlaybackServer } from '@matter/node/behaviors/media-playback';
14
+ import { MessagesClient } from '@matter/node/behaviors/messages';
15
+ import { OnOffClient } from '@matter/node/behaviors/on-off';
16
+ import { TargetNavigatorClient } from '@matter/node/behaviors/target-navigator';
17
+ import { WakeOnLanClient } from '@matter/node/behaviors/wake-on-lan';
18
+ import { getClusterNameById } from '@matter/types/cluster';
19
+ import { AccountLogin } from '@matter/types/clusters/account-login';
20
+ import { ApplicationBasic } from '@matter/types/clusters/application-basic';
21
+ import { ApplicationLauncher } from '@matter/types/clusters/application-launcher';
22
+ import { AudioOutput } from '@matter/types/clusters/audio-output';
23
+ import { Channel } from '@matter/types/clusters/channel';
24
+ import { ContentAppObserver } from '@matter/types/clusters/content-app-observer';
25
+ import { ContentControl } from '@matter/types/clusters/content-control';
26
+ import { ContentLauncher } from '@matter/types/clusters/content-launcher';
27
+ import { KeypadInput } from '@matter/types/clusters/keypad-input';
28
+ import { LevelControl } from '@matter/types/clusters/level-control';
29
+ import { LowPower } from '@matter/types/clusters/low-power';
30
+ import { MediaInput } from '@matter/types/clusters/media-input';
31
+ import { MediaPlayback } from '@matter/types/clusters/media-playback';
32
+ import { Messages } from '@matter/types/clusters/messages';
33
+ import { OnOff } from '@matter/types/clusters/on-off';
34
+ import { TargetNavigator } from '@matter/types/clusters/target-navigator';
35
+ import { WakeOnLan } from '@matter/types/clusters/wake-on-lan';
36
+ import { MatterbridgeBindingServer } from '../behaviors/bindingServer.js';
37
+ import { MatterbridgeServer } from '../behaviors/matterbridgeServer.js';
38
+ import { MatterbridgeOnOffServer } from '../behaviors/onOffServer.js';
39
+ import { lowercaseFirstLetter } from '../matterbridgeEndpointHelpers.js';
40
+ export class MatterbridgeMediaPlaybackServer extends MediaPlaybackServer {
41
+ initialize() {
42
+ const device = this.endpoint.stateOf(MatterbridgeServer);
43
+ device.log.info(`MatterbridgeMediaPlaybackServer initialized: currentState is ${this.state.currentState}`);
44
+ this.reactTo(this.agent.get(MatterbridgeOnOffServer.with()).events.onOff$Changed, this.handleOnOffChange);
45
+ }
46
+ handleOnOffChange(_onOff) {
47
+ this.state.currentState = MediaPlayback.PlaybackState.NotPlaying;
48
+ }
49
+ async play() {
50
+ const device = this.endpoint.stateOf(MatterbridgeServer);
51
+ device.log.info(`Play (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
52
+ await device.commandHandler.executeHandler('MediaPlayback.play', {
53
+ command: 'play',
54
+ request: {},
55
+ cluster: MediaPlaybackServer.id,
56
+ attributes: this.state,
57
+ endpoint: this.endpoint,
58
+ });
59
+ if (this.endpoint.stateOf(MatterbridgeOnOffServer.with()).onOff)
60
+ this.state.currentState = MediaPlayback.PlaybackState.Playing;
61
+ return { status: MediaPlayback.Status.Success };
62
+ }
63
+ async pause() {
64
+ const device = this.endpoint.stateOf(MatterbridgeServer);
65
+ device.log.info(`Pause (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
66
+ await device.commandHandler.executeHandler('MediaPlayback.pause', {
67
+ command: 'pause',
68
+ request: {},
69
+ cluster: MediaPlaybackServer.id,
70
+ attributes: this.state,
71
+ endpoint: this.endpoint,
72
+ });
73
+ if (this.endpoint.stateOf(MatterbridgeOnOffServer.with()).onOff)
74
+ this.state.currentState = MediaPlayback.PlaybackState.Paused;
75
+ return { status: MediaPlayback.Status.Success };
76
+ }
77
+ async stop() {
78
+ const device = this.endpoint.stateOf(MatterbridgeServer);
79
+ device.log.info(`Stop (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
80
+ await device.commandHandler.executeHandler('MediaPlayback.stop', {
81
+ command: 'stop',
82
+ request: {},
83
+ cluster: MediaPlaybackServer.id,
84
+ attributes: this.state,
85
+ endpoint: this.endpoint,
86
+ });
87
+ if (this.endpoint.stateOf(MatterbridgeOnOffServer.with()).onOff)
88
+ this.state.currentState = MediaPlayback.PlaybackState.NotPlaying;
89
+ return { status: MediaPlayback.Status.Success };
90
+ }
91
+ async previous() {
92
+ const device = this.endpoint.stateOf(MatterbridgeServer);
93
+ device.log.info(`Previous (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
94
+ await device.commandHandler.executeHandler('MediaPlayback.previous', {
95
+ command: 'previous',
96
+ request: {},
97
+ cluster: MediaPlaybackServer.id,
98
+ attributes: this.state,
99
+ endpoint: this.endpoint,
100
+ });
101
+ return { status: MediaPlayback.Status.Success };
102
+ }
103
+ async next() {
104
+ const device = this.endpoint.stateOf(MatterbridgeServer);
105
+ device.log.info(`Next (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
106
+ await device.commandHandler.executeHandler('MediaPlayback.next', {
107
+ command: 'next',
108
+ request: {},
109
+ cluster: MediaPlaybackServer.id,
110
+ attributes: this.state,
111
+ endpoint: this.endpoint,
112
+ });
113
+ return { status: MediaPlayback.Status.Success };
114
+ }
115
+ async skipForward(request) {
116
+ const device = this.endpoint.stateOf(MatterbridgeServer);
117
+ device.log.info(`SkipForward (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
118
+ await device.commandHandler.executeHandler('MediaPlayback.skipForward', {
119
+ command: 'skipForward',
120
+ request,
121
+ cluster: MediaPlaybackServer.id,
122
+ attributes: this.state,
123
+ endpoint: this.endpoint,
124
+ });
125
+ return { status: MediaPlayback.Status.Success };
126
+ }
127
+ async skipBackward(request) {
128
+ const device = this.endpoint.stateOf(MatterbridgeServer);
129
+ device.log.info(`SkipBackward (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
130
+ await device.commandHandler.executeHandler('MediaPlayback.skipBackward', {
131
+ command: 'skipBackward',
132
+ request,
133
+ cluster: MediaPlaybackServer.id,
134
+ attributes: this.state,
135
+ endpoint: this.endpoint,
136
+ });
137
+ return { status: MediaPlayback.Status.Success };
138
+ }
139
+ }
140
+ export class MatterbridgeKeypadInputServer extends KeypadInputServer {
141
+ initialize() {
142
+ const device = this.endpoint.stateOf(MatterbridgeServer);
143
+ device.log.info(`MatterbridgeKeypadInputServer initialized`);
144
+ }
145
+ async sendKey(request) {
146
+ const device = this.endpoint.stateOf(MatterbridgeServer);
147
+ device.log.info(`SendKey keyCode ${request.keyCode} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
148
+ await device.commandHandler.executeHandler('KeypadInput.sendKey', {
149
+ command: 'sendKey',
150
+ request,
151
+ cluster: KeypadInputServer.id,
152
+ attributes: {},
153
+ endpoint: this.endpoint,
154
+ });
155
+ return { status: KeypadInput.Status.Success };
156
+ }
157
+ }
158
+ export class MatterbridgeContentLauncherServer extends ContentLauncherServer {
159
+ initialize() {
160
+ const device = this.endpoint.stateOf(MatterbridgeServer);
161
+ device.log.info(`MatterbridgeContentLauncherServer initialized`);
162
+ }
163
+ }
164
+ export class MatterbridgeApplicationBasicServer extends ApplicationBasicServer {
165
+ initialize() {
166
+ const device = this.endpoint.stateOf(MatterbridgeServer);
167
+ device.log.info(`MatterbridgeApplicationBasicServer initialized`);
168
+ }
169
+ }
170
+ export class MatterbridgeApplicationLauncherServer extends ApplicationLauncherServer {
171
+ initialize() {
172
+ const device = this.endpoint.stateOf(MatterbridgeServer);
173
+ device.log.info(`MatterbridgeApplicationLauncherServer initialized`);
174
+ }
175
+ async launchApp(request) {
176
+ const device = this.endpoint.stateOf(MatterbridgeServer);
177
+ device.log.info(`LaunchApp (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
178
+ await device.commandHandler.executeHandler('ApplicationLauncher.launchApp', {
179
+ command: 'launchApp',
180
+ request,
181
+ cluster: ApplicationLauncherServer.id,
182
+ attributes: this.state,
183
+ endpoint: this.endpoint,
184
+ });
185
+ return { status: ApplicationLauncher.Status.Success };
186
+ }
187
+ async stopApp(request) {
188
+ const device = this.endpoint.stateOf(MatterbridgeServer);
189
+ device.log.info(`StopApp (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
190
+ await device.commandHandler.executeHandler('ApplicationLauncher.stopApp', {
191
+ command: 'stopApp',
192
+ request,
193
+ cluster: ApplicationLauncherServer.id,
194
+ attributes: this.state,
195
+ endpoint: this.endpoint,
196
+ });
197
+ return { status: ApplicationLauncher.Status.Success };
198
+ }
199
+ async hideApp(request) {
200
+ const device = this.endpoint.stateOf(MatterbridgeServer);
201
+ device.log.info(`HideApp (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
202
+ await device.commandHandler.executeHandler('ApplicationLauncher.hideApp', {
203
+ command: 'hideApp',
204
+ request,
205
+ cluster: ApplicationLauncherServer.id,
206
+ attributes: this.state,
207
+ endpoint: this.endpoint,
208
+ });
209
+ return { status: ApplicationLauncher.Status.Success };
210
+ }
211
+ }
212
+ export function createDefaultMediaPlaybackClusterServer(endpoint, currentState, extendedCommands = false) {
213
+ endpoint.behaviors.require(extendedCommands
214
+ ? MatterbridgeMediaPlaybackServer.enable({ commands: { next: true, previous: true, skipForward: true, skipBackward: true } })
215
+ : MatterbridgeMediaPlaybackServer, { currentState });
216
+ }
217
+ export function createDefaultKeypadInputClusterServer(endpoint) {
218
+ endpoint.behaviors.require(MatterbridgeKeypadInputServer, {});
219
+ }
220
+ export function createDefaultContentLauncherClusterServer(endpoint) {
221
+ endpoint.behaviors.require(MatterbridgeContentLauncherServer, {});
222
+ }
223
+ export function createDefaultApplicationLauncherClusterServer(endpoint) {
224
+ endpoint.behaviors.require(MatterbridgeApplicationLauncherServer, {
225
+ currentApp: null,
226
+ });
227
+ }
228
+ export function createDefaultApplicationBasicClusterServer(endpoint, applicationName, catalogVendorId, applicationId, status, applicationVersion, allowedVendorList) {
229
+ endpoint.behaviors.require(MatterbridgeApplicationBasicServer, {
230
+ applicationName,
231
+ application: new ApplicationBasic.Application({ catalogVendorId, applicationId }),
232
+ status,
233
+ applicationVersion,
234
+ allowedVendorList,
235
+ });
236
+ }
237
+ const mediaClientBehaviors = new Map([
238
+ [OnOff.id, OnOffClient],
239
+ [KeypadInput.id, KeypadInputClient],
240
+ [MediaPlayback.id, MediaPlaybackClient],
241
+ [ContentLauncher.id, ContentLauncherClient],
242
+ [ApplicationBasic.id, ApplicationBasicClient],
243
+ [LevelControl.id, LevelControlClient],
244
+ [Messages.id, MessagesClient],
245
+ [WakeOnLan.id, WakeOnLanClient],
246
+ [Channel.id, ChannelClient],
247
+ [TargetNavigator.id, TargetNavigatorClient],
248
+ [MediaInput.id, MediaInputClient],
249
+ [LowPower.id, LowPowerClient],
250
+ [AudioOutput.id, AudioOutputClient],
251
+ [ApplicationLauncher.id, ApplicationLauncherClient],
252
+ [AccountLogin.id, AccountLoginClient],
253
+ [ContentControl.id, ContentControlClient],
254
+ [ContentAppObserver.id, ContentAppObserverClient],
255
+ ]);
256
+ export function createDefaultMediaBindingClusterServer(endpoint, clientList) {
257
+ endpoint.behaviors.require(MatterbridgeBindingServer, { clientList });
258
+ for (const clusterId of clientList) {
259
+ const client = mediaClientBehaviors.get(clusterId);
260
+ if (client)
261
+ endpoint.type.clientClusters[lowercaseFirstLetter(getClusterNameById(clusterId))] ??= client;
262
+ }
263
+ }
264
+ export function createDefaultMediaPowerSourceClusterServer(endpoint, powerSourceType) {
265
+ switch (powerSourceType) {
266
+ case 'Rechargeable':
267
+ endpoint.createDefaultPowerSourceRechargeableBatteryClusterServer();
268
+ break;
269
+ case 'Replaceable':
270
+ endpoint.createDefaultPowerSourceReplaceableBatteryClusterServer();
271
+ break;
272
+ case 'Battery':
273
+ endpoint.createDefaultPowerSourceBatteryClusterServer();
274
+ break;
275
+ case 'Wired':
276
+ endpoint.createDefaultPowerSourceWiredClusterServer();
277
+ break;
278
+ case 'None':
279
+ break;
280
+ }
281
+ }
@@ -1,6 +1,15 @@
1
+ import type { EndpointNumber } from '@matter/types/datatype';
1
2
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
3
+ import { type MediaPowerSourceType } from './mediaHelpers.js';
4
+ export interface SpeakerOptions {
5
+ muted?: boolean;
6
+ volume?: number;
7
+ powerSourceType?: MediaPowerSourceType;
8
+ id?: string;
9
+ number?: EndpointNumber;
10
+ }
2
11
  export declare class Speaker extends MatterbridgeEndpoint {
3
- constructor(name: string, serial: string, muted?: boolean, volume?: number);
12
+ constructor(name: string, serial: string, options?: SpeakerOptions);
4
13
  setMuted(muted: boolean): Promise<void>;
5
14
  isMuted(): boolean;
6
15
  setVolume(level: number): Promise<void>;
@@ -1,17 +1,24 @@
1
1
  import { LevelControl } from '@matter/types/clusters/level-control';
2
2
  import { OnOff } from '@matter/types/clusters/on-off';
3
- import { speaker } from '../matterbridgeDeviceTypes.js';
3
+ import { powerSource, speaker } from '../matterbridgeDeviceTypes.js';
4
4
  import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
5
+ import { createDefaultMediaPowerSourceClusterServer } from './mediaHelpers.js';
5
6
  export class Speaker extends MatterbridgeEndpoint {
6
- constructor(name, serial, muted = false, volume = 128) {
7
+ constructor(name, serial, options = {}) {
8
+ const { muted = false, powerSourceType = 'Wired' } = options;
9
+ let { volume = 128 } = options;
7
10
  if (!Number.isFinite(volume))
8
11
  volume = 128;
9
12
  if (volume < 1)
10
13
  volume = 1;
11
14
  if (volume > 254)
12
15
  volume = 254;
13
- super([speaker], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` });
16
+ super(powerSourceType === 'None' ? [speaker] : [speaker, powerSource], {
17
+ id: options.id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
18
+ number: options.number,
19
+ });
14
20
  this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Speaker');
21
+ createDefaultMediaPowerSourceClusterServer(this, powerSourceType);
15
22
  this.createOnOffClusterServer(!muted);
16
23
  this.createLevelControlClusterServer(volume);
17
24
  }
@@ -0,0 +1,11 @@
1
+ import type { EndpointNumber } from '@matter/types/datatype';
2
+ import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
3
+ import { type MediaPowerSourceType } from './mediaHelpers.js';
4
+ export interface VideoRemoteControlOptions {
5
+ powerSourceType?: MediaPowerSourceType;
6
+ id?: string;
7
+ number?: EndpointNumber;
8
+ }
9
+ export declare class VideoRemoteControl extends MatterbridgeEndpoint {
10
+ constructor(name: string, serial: string, options?: VideoRemoteControlOptions);
11
+ }
@@ -0,0 +1,18 @@
1
+ import { KeypadInput } from '@matter/types/clusters/keypad-input';
2
+ import { MediaPlayback } from '@matter/types/clusters/media-playback';
3
+ import { OnOff } from '@matter/types/clusters/on-off';
4
+ import { powerSource, videoRemoteControl } from '../matterbridgeDeviceTypes.js';
5
+ import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
6
+ import { createDefaultMediaBindingClusterServer, createDefaultMediaPowerSourceClusterServer } from './mediaHelpers.js';
7
+ export class VideoRemoteControl extends MatterbridgeEndpoint {
8
+ constructor(name, serial, options = {}) {
9
+ const { powerSourceType = 'Battery' } = options;
10
+ super(powerSourceType === 'None' ? [videoRemoteControl] : [videoRemoteControl, powerSource], {
11
+ id: options.id ?? `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
12
+ number: options.number,
13
+ });
14
+ this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Video Remote Control');
15
+ createDefaultMediaPowerSourceClusterServer(this, powerSourceType);
16
+ createDefaultMediaBindingClusterServer(this, [OnOff.id, MediaPlayback.id, KeypadInput.id]);
17
+ }
18
+ }
package/dist/frontend.js CHANGED
@@ -1158,6 +1158,8 @@ export class Frontend extends EventEmitter {
1158
1158
  attributes += `State: ${getEnumDescription(ValveConfigurationAndControl.ValveState, attributeValue, { fallback: 'unknown' })} `;
1159
1159
  if (clusterName === 'levelControl' && attributeName === 'currentLevel')
1160
1160
  attributes += `Level: ${attributeValue} `;
1161
+ if (clusterName === 'applicationBasic' && attributeName === 'applicationName')
1162
+ attributes += `App: ${attributeValue} `;
1161
1163
  if (clusterName === 'colorControl' && attributeName === 'colorMode' && isValidNumber(attributeValue, 0, 2))
1162
1164
  attributes += `Mode: ${['HS', 'XY', 'CT'][attributeValue]} `;
1163
1165
  if (clusterName === 'colorControl' && getAttribute(device, 'colorControl', 'colorMode') === 0 && attributeName === 'currentHue' && isValidNumber(attributeValue))
@@ -1,6 +1,7 @@
1
1
  import type { ActionContext } from '@matter/main';
2
2
  import type { ClusterType } from '@matter/types/cluster';
3
3
  import type { ActivatedCarbonFilterMonitoring } from '@matter/types/clusters/activated-carbon-filter-monitoring';
4
+ import type { ApplicationLauncher } from '@matter/types/clusters/application-launcher';
4
5
  import type { BooleanStateConfiguration } from '@matter/types/clusters/boolean-state-configuration';
5
6
  import type { ColorControl } from '@matter/types/clusters/color-control';
6
7
  import type { DeviceEnergyManagement } from '@matter/types/clusters/device-energy-management';
@@ -868,6 +869,27 @@ export type CommandHandlerDataMap = {
868
869
  attributes: {};
869
870
  endpoint: MatterbridgeEndpoint;
870
871
  };
872
+ 'ApplicationLauncher.launchApp': {
873
+ command: 'launchApp';
874
+ request: ApplicationLauncher.LaunchAppRequest;
875
+ cluster: 'applicationLauncher';
876
+ attributes: ClusterAttributeValues<(typeof ApplicationLauncher)['attributes']>;
877
+ endpoint: MatterbridgeEndpoint;
878
+ };
879
+ 'ApplicationLauncher.stopApp': {
880
+ command: 'stopApp';
881
+ request: ApplicationLauncher.StopAppRequest;
882
+ cluster: 'applicationLauncher';
883
+ attributes: ClusterAttributeValues<(typeof ApplicationLauncher)['attributes']>;
884
+ endpoint: MatterbridgeEndpoint;
885
+ };
886
+ 'ApplicationLauncher.hideApp': {
887
+ command: 'hideApp';
888
+ request: ApplicationLauncher.HideAppRequest;
889
+ cluster: 'applicationLauncher';
890
+ attributes: ClusterAttributeValues<(typeof ApplicationLauncher)['attributes']>;
891
+ endpoint: MatterbridgeEndpoint;
892
+ };
871
893
  'resetCondition': CommandHandlerData<'ResourceMonitoring.resetCondition'>;
872
894
  'ResourceMonitoring.resetCondition': {
873
895
  command: 'resetCondition';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@matterbridge/core",
3
- "version": "3.10.6-dev-20260820-36b52be",
3
+ "version": "3.10.6-dev-20260821-16f33ac",
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-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",
135
+ "@matterbridge/dgram": "3.10.6-dev-20260821-16f33ac",
136
+ "@matterbridge/thread": "3.10.6-dev-20260821-16f33ac",
137
+ "@matterbridge/types": "3.10.6-dev-20260821-16f33ac",
138
+ "@matterbridge/utils": "3.10.6-dev-20260821-16f33ac",
139
139
  "escape-html": "1.0.3",
140
140
  "express": "5.2.1",
141
141
  "express-rate-limit": "8.6.2",