matterbridge 3.1.1-dev-20250629-f14b886 → 3.1.1-dev-20250630-1555eae

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/CHANGELOG.md CHANGED
@@ -10,8 +10,18 @@ If you like this project and find it useful, please consider giving it a star on
10
10
 
11
11
  ## [3.1.1] - 2025-07-??
12
12
 
13
+ ### Development Breaking Changes
14
+
15
+ - [devices]: The single devices (i.e. Rvc, Evse etc...) are only exported from matterbridge/devices. Please update your imports to use the new export path. Refer to the [documentation](README-DEV.md) for details on imports.
16
+
13
17
  ### Added
14
18
 
19
+ - [LaundryDryer]: Added LaundryDryer (not supported by the Home app) class and Jest test.
20
+ - [DeviceEnergyManagement]: Added MatterbridgeDeviceEnergyManagementServer with power adjustment methods.
21
+ - [SolarPower]: Added SolarPower class and Jest test (working on Home Assistant and SmartThings). Thanks Ludovic BOUÉ.
22
+ - [BatteryStorage]: Added BatteryStorage class and Jest test (working on Home Assistant and SmartThings). Thanks Ludovic BOUÉ.
23
+ - [HeatPump]: Added HeatPump class and Jest test (working on Home Assistant and SmartThings).
24
+
15
25
  ### Changed
16
26
 
17
27
  - [package]: Updated dependencies.
package/README-DEV.md CHANGED
@@ -1,10 +1,12 @@
1
- # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge
1
+ # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge development
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
4
4
  [![npm downloads](https://img.shields.io/npm/dt/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
5
5
  [![Docker Version](https://img.shields.io/docker/v/luligu/matterbridge?label=docker%20version&sort=semver)](https://hub.docker.com/r/luligu/matterbridge)
6
6
  [![Docker Pulls](https://img.shields.io/docker/pulls/luligu/matterbridge.svg)](https://hub.docker.com/r/luligu/matterbridge)
7
7
  ![Node.js CI](https://github.com/Luligu/matterbridge/actions/workflows/build.yml/badge.svg)
8
+ ![CodeQL](https://github.com/Luligu/matterbridge/actions/workflows/codeql.yml/badge.svg)
9
+ [![codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
8
10
 
9
11
  [![power by](https://img.shields.io/badge/powered%20by-matter--history-blue)](https://www.npmjs.com/package/matter-history)
10
12
  [![power by](https://img.shields.io/badge/powered%20by-node--ansi--logger-blue)](https://www.npmjs.com/package/node-ansi-logger)
package/README-DOCKER.md CHANGED
@@ -1,10 +1,12 @@
1
- # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge
1
+ # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge docker configuration
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
4
4
  [![npm downloads](https://img.shields.io/npm/dt/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
5
5
  [![Docker Version](https://img.shields.io/docker/v/luligu/matterbridge?label=docker%20version&sort=semver)](https://hub.docker.com/r/luligu/matterbridge)
6
6
  [![Docker Pulls](https://img.shields.io/docker/pulls/luligu/matterbridge.svg)](https://hub.docker.com/r/luligu/matterbridge)
7
7
  ![Node.js CI](https://github.com/Luligu/matterbridge/actions/workflows/build.yml/badge.svg)
8
+ ![CodeQL](https://github.com/Luligu/matterbridge/actions/workflows/codeql.yml/badge.svg)
9
+ [![codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
8
10
 
9
11
  [![power by](https://img.shields.io/badge/powered%20by-matter--history-blue)](https://www.npmjs.com/package/matter-history)
10
12
  [![power by](https://img.shields.io/badge/powered%20by-node--ansi--logger-blue)](https://www.npmjs.com/package/node-ansi-logger)
package/README-NGINX.md CHANGED
@@ -1,10 +1,12 @@
1
- # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge
1
+ # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge NGINX configuration
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
4
4
  [![npm downloads](https://img.shields.io/npm/dt/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
5
5
  [![Docker Version](https://img.shields.io/docker/v/luligu/matterbridge?label=docker%20version&sort=semver)](https://hub.docker.com/r/luligu/matterbridge)
6
6
  [![Docker Pulls](https://img.shields.io/docker/pulls/luligu/matterbridge.svg)](https://hub.docker.com/r/luligu/matterbridge)
7
7
  ![Node.js CI](https://github.com/Luligu/matterbridge/actions/workflows/build.yml/badge.svg)
8
+ ![CodeQL](https://github.com/Luligu/matterbridge/actions/workflows/codeql.yml/badge.svg)
9
+ [![codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
8
10
 
9
11
  [![power by](https://img.shields.io/badge/powered%20by-matter--history-blue)](https://www.npmjs.com/package/matter-history)
10
12
  [![power by](https://img.shields.io/badge/powered%20by-node--ansi--logger-blue)](https://www.npmjs.com/package/node-ansi-logger)
@@ -31,7 +33,7 @@ server {
31
33
  server_name _;
32
34
 
33
35
  location / {
34
- # Redirect to Matterbridge frontend
36
+ # Redirect to Matterbridge frontend from http:/server_name:80
35
37
  proxy_pass http://localhost:8283/;
36
38
  proxy_set_header Host $host;
37
39
  proxy_set_header X-Real-IP $remote_addr;
@@ -48,13 +50,13 @@ server {
48
50
 
49
51
  Add matterbridge to enabled sites
50
52
 
51
- ```
53
+ ```bash
52
54
  sudo ln -s /etc/nginx/sites-available/matterbridge /etc/nginx/sites-enabled/
53
55
  ```
54
56
 
55
57
  ### Create a basic nginx configuration file that redirect to http://yourhost:8283/matterbridge
56
58
 
57
- ```
59
+ ```bash
58
60
  sudo nano /etc/nginx/sites-available/matterbridge
59
61
  ```
60
62
 
@@ -67,7 +69,7 @@ server {
67
69
  server_name _;
68
70
 
69
71
  location /matterbridge/ {
70
- # Redirect to Matterbridge frontend
72
+ # Redirect to Matterbridge frontend from http:/server_name/matterbridge:80
71
73
  proxy_pass http://localhost:8283/;
72
74
  proxy_set_header Host $host;
73
75
  proxy_set_header X-Real-IP $remote_addr;
@@ -84,13 +86,20 @@ server {
84
86
 
85
87
  Add matterbridge to enabled sites
86
88
 
87
- ```
89
+ ```bash
88
90
  sudo ln -s /etc/nginx/sites-available/matterbridge /etc/nginx/sites-enabled/
89
91
  ```
90
92
 
91
- ### Create an advanced nginx configuration file that redirect to http://yourhost:8283 with ssl
93
+ Restart nginx and test the configuration
92
94
 
95
+ ```bash
96
+ sudo systemctl restart nginx
97
+ sudo nginx -t
93
98
  ```
99
+
100
+ ### Create an advanced nginx configuration file that redirect to http://yourhost:8283 with ssl
101
+
102
+ ```bash
94
103
  sudo nano /etc/nginx/sites-available/matterbridge
95
104
  ```
96
105
 
@@ -125,7 +134,7 @@ server {
125
134
  ssl_prefer_server_ciphers on;
126
135
 
127
136
  location / {
128
- # Redirect to Matterbridge frontend
137
+ # Redirect to Matterbridge frontend from https:/server_name:443
129
138
  proxy_pass http://localhost:8283/;
130
139
  proxy_set_header Host $host;
131
140
  proxy_set_header X-Real-IP $remote_addr;
@@ -142,13 +151,20 @@ server {
142
151
 
143
152
  Add matterbridge to enabled sites
144
153
 
145
- ```
154
+ ```bash
146
155
  sudo ln -s /etc/nginx/sites-available/matterbridge /etc/nginx/sites-enabled/
147
156
  ```
148
157
 
149
- ### Create an advanced nginx configuration file that redirect to http://yourhost/matterbridge with ssl
158
+ Restart nginx and test the configuration
150
159
 
160
+ ```bash
161
+ sudo systemctl restart nginx
162
+ sudo nginx -t
151
163
  ```
164
+
165
+ ### Create an advanced nginx configuration file that redirect to http://yourhost/matterbridge with ssl
166
+
167
+ ```bash
152
168
  sudo nano /etc/nginx/sites-available/matterbridge
153
169
  ```
154
170
 
@@ -190,7 +206,7 @@ server {
190
206
  }
191
207
 
192
208
  location /matterbridge/ {
193
- # Redirect to Matterbridge frontend
209
+ # Redirect to Matterbridge frontend from https:/server_name/matterbridge:443
194
210
  proxy_pass http://localhost:8283/;
195
211
  proxy_set_header Host $host;
196
212
  proxy_set_header X-Real-IP $remote_addr;
@@ -207,21 +223,13 @@ server {
207
223
 
208
224
  Add matterbridge to enabled sites
209
225
 
210
- ```
226
+ ```bash
211
227
  sudo ln -s /etc/nginx/sites-available/matterbridge /etc/nginx/sites-enabled/
212
228
  ```
213
229
 
214
- ### Restart nginx and test the configuration
230
+ Restart nginx and test the configuration
215
231
 
216
- ```
232
+ ```bash
217
233
  sudo systemctl restart nginx
218
234
  sudo nginx -t
219
235
  ```
220
-
221
- ### Use matterbridge with nginx
222
-
223
- http://ubuntu/matterbridge/
224
-
225
- or
226
-
227
- https://ubuntu/matterbridge/
package/README-PODMAN.md CHANGED
@@ -1,10 +1,12 @@
1
- # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge
1
+ # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge Podman configuration
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
4
4
  [![npm downloads](https://img.shields.io/npm/dt/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
5
5
  [![Docker Version](https://img.shields.io/docker/v/luligu/matterbridge?label=docker%20version&sort=semver)](https://hub.docker.com/r/luligu/matterbridge)
6
6
  [![Docker Pulls](https://img.shields.io/docker/pulls/luligu/matterbridge.svg)](https://hub.docker.com/r/luligu/matterbridge)
7
7
  ![Node.js CI](https://github.com/Luligu/matterbridge/actions/workflows/build.yml/badge.svg)
8
+ ![CodeQL](https://github.com/Luligu/matterbridge/actions/workflows/codeql.yml/badge.svg)
9
+ [![codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
8
10
 
9
11
  [![power by](https://img.shields.io/badge/powered%20by-matter--history-blue)](https://www.npmjs.com/package/matter-history)
10
12
  [![power by](https://img.shields.io/badge/powered%20by-node--ansi--logger-blue)](https://www.npmjs.com/package/node-ansi-logger)
package/README-SERVICE.md CHANGED
@@ -1,10 +1,12 @@
1
- # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge
1
+ # <img src="frontend/public/matterbridge.svg" alt="Matterbridge Logo" width="64px" height="64px">&nbsp;&nbsp;&nbsp;Matterbridge systemd configuration
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
4
4
  [![npm downloads](https://img.shields.io/npm/dt/matterbridge.svg)](https://www.npmjs.com/package/matterbridge)
5
5
  [![Docker Version](https://img.shields.io/docker/v/luligu/matterbridge?label=docker%20version&sort=semver)](https://hub.docker.com/r/luligu/matterbridge)
6
6
  [![Docker Pulls](https://img.shields.io/docker/pulls/luligu/matterbridge.svg)](https://hub.docker.com/r/luligu/matterbridge)
7
7
  ![Node.js CI](https://github.com/Luligu/matterbridge/actions/workflows/build.yml/badge.svg)
8
+ ![CodeQL](https://github.com/Luligu/matterbridge/actions/workflows/codeql.yml/badge.svg)
9
+ [![codecov](https://codecov.io/gh/Luligu/matterbridge/branch/main/graph/badge.svg)](https://codecov.io/gh/Luligu/matterbridge)
8
10
 
9
11
  [![power by](https://img.shields.io/badge/powered%20by-matter--history-blue)](https://www.npmjs.com/package/matter-history)
10
12
  [![power by](https://img.shields.io/badge/powered%20by-node--ansi--logger-blue)](https://www.npmjs.com/package/node-ansi-logger)
@@ -16,6 +18,10 @@
16
18
 
17
19
  ## Run matterbridge as a daemon with systemctl (Linux only)
18
20
 
21
+ The easiest way to add systemctl is to use [Matterbridge service cli for linux](https://github.com/Luligu/mb-service-linux).
22
+
23
+ If your setup is too complex or you prefer to do it manually follow this method. You can still use mb-service to manage systemd after.
24
+
19
25
  ### First create the Matterbridge directories
20
26
 
21
27
  This will create the required directories if they don't exist
@@ -75,7 +81,7 @@ If you use the matterbridge-bthome plugin add this:
75
81
  AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_NET_ADMIN
76
82
  ```
77
83
 
78
- If you modify it after, then run:
84
+ If you modify matterbridge.service after, then run:
79
85
 
80
86
  ```bash
81
87
  sudo systemctl daemon-reload
@@ -0,0 +1,28 @@
1
+ import { PowerSourceTag } from '@matter/main';
2
+ import { DeviceEnergyManagement } from '@matter/main/clusters/device-energy-management';
3
+ import { PowerSource } from '@matter/main/clusters/power-source';
4
+ import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
5
+ import { deviceEnergyManagement, electricalSensor, batteryStorage, powerSource } from './matterbridgeDeviceTypes.js';
6
+ export class BatteryStorage extends MatterbridgeEndpoint {
7
+ constructor(name, serial, batPercentRemaining = 100, batChargeLevel = PowerSource.BatChargeLevel.Ok, voltage = null, current = null, power = null, energyImported = null, energyExported = null, absMinPower = 0, absMaxPower = 0) {
8
+ super([batteryStorage, powerSource, electricalSensor, deviceEnergyManagement], { id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
9
+ this.createDefaultIdentifyClusterServer()
10
+ .createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Solar Power')
11
+ .createDefaultPowerTopologyClusterServer()
12
+ .createDefaultElectricalPowerMeasurementClusterServer(voltage, current, power)
13
+ .createDefaultElectricalEnergyMeasurementClusterServer(energyImported, energyExported)
14
+ .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.BatteryStorage, true, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
15
+ .createDefaultDeviceEnergyManagementModeClusterServer()
16
+ .addRequiredClusterServers();
17
+ this.addChildDeviceType('BatteryPowerSource', powerSource, {
18
+ tagList: [{ mfgCode: null, namespaceId: PowerSourceTag.Battery.namespaceId, tag: PowerSourceTag.Battery.tag, label: null }],
19
+ })
20
+ .createDefaultPowerSourceRechargeableBatteryClusterServer(batPercentRemaining, batChargeLevel)
21
+ .addRequiredClusterServers();
22
+ this.addChildDeviceType('GridPowerSource', powerSource, {
23
+ tagList: [{ mfgCode: null, namespaceId: PowerSourceTag.Grid.namespaceId, tag: PowerSourceTag.Grid.tag, label: null }],
24
+ })
25
+ .createDefaultPowerSourceWiredClusterServer()
26
+ .addRequiredClusterServers();
27
+ }
28
+ }
@@ -1,4 +1,7 @@
1
1
  export * from '../roboticVacuumCleaner.js';
2
2
  export * from '../laundryWasher.js';
3
+ export * from '../laundryDryer.js';
3
4
  export * from '../waterHeater.js';
4
5
  export * from '../evse.js';
6
+ export * from '../solarPower.js';
7
+ export * from '../batteryStorage.js';
package/dist/evse.js CHANGED
@@ -16,6 +16,7 @@ export class Evse extends MatterbridgeEndpoint {
16
16
  .createDefaultElectricalPowerMeasurementClusterServer()
17
17
  .createDefaultElectricalEnergyMeasurementClusterServer()
18
18
  .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.Evse, false, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
19
+ .createDefaultDeviceEnergyManagementModeClusterServer()
19
20
  .createDefaultEnergyEvseClusterServer(state, supplyState, faultState)
20
21
  .createDefaultEnergyEvseModeClusterServer(currentMode, supportedModes)
21
22
  .addRequiredClusterServers();
@@ -0,0 +1,21 @@
1
+ import { PowerSourceTag } from '@matter/main';
2
+ import { DeviceEnergyManagement } from '@matter/main/clusters/device-energy-management';
3
+ import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
4
+ import { deviceEnergyManagement, electricalSensor, powerSource, heatPump } from './matterbridgeDeviceTypes.js';
5
+ export class HeatPump extends MatterbridgeEndpoint {
6
+ constructor(name, serial, voltage = null, current = null, power = null, energyImported = null, absMinPower = 0, absMaxPower = 0) {
7
+ super([heatPump, powerSource, electricalSensor, deviceEnergyManagement], {
8
+ tagList: [{ mfgCode: null, namespaceId: PowerSourceTag.Grid.namespaceId, tag: PowerSourceTag.Grid.tag, label: null }],
9
+ id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
10
+ }, true);
11
+ this.createDefaultIdentifyClusterServer()
12
+ .createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Heat Pump')
13
+ .createDefaultPowerSourceWiredClusterServer()
14
+ .createDefaultPowerTopologyClusterServer()
15
+ .createDefaultElectricalPowerMeasurementClusterServer(voltage, current, power)
16
+ .createDefaultElectricalEnergyMeasurementClusterServer(energyImported)
17
+ .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.Other, true, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
18
+ .createDefaultDeviceEnergyManagementModeClusterServer()
19
+ .addRequiredClusterServers();
20
+ }
21
+ }
package/dist/index.js CHANGED
@@ -15,6 +15,8 @@ export * from './roboticVacuumCleaner.js';
15
15
  export * from './laundryWasher.js';
16
16
  export * from './waterHeater.js';
17
17
  export * from './evse.js';
18
+ export * from './solarPower.js';
19
+ export * from './batteryStorage.js';
18
20
  const log = new AnsiLogger({ logName: 'Main', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
19
21
  async function main() {
20
22
  log.debug('***Matterbridge.loadInstance() called');
@@ -0,0 +1,58 @@
1
+ import { LaundryWasherMode } from '@matter/main/clusters/laundry-washer-mode';
2
+ import { TemperatureControl } from '@matter/main/clusters/temperature-control';
3
+ import { LaundryDryerControls } from '@matter/main/clusters/laundry-dryer-controls';
4
+ import { LaundryDryerControlsServer } from '@matter/main/behaviors/laundry-dryer-controls';
5
+ import { laundryDryer, powerSource } from './matterbridgeDeviceTypes.js';
6
+ import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
7
+ import { MatterbridgeLaundryWasherModeServer, MatterbridgeLevelTemperatureControlServer, MatterbridgeNumberTemperatureControlServer } from './laundryWasher.js';
8
+ export class LaundryDryer extends MatterbridgeEndpoint {
9
+ constructor(name, serial, currentMode, supportedModes, selectedTemperatureLevel, supportedTemperatureLevels, temperatureSetpoint, minTemperature, maxTemperature, step, operationalState) {
10
+ super([laundryDryer, powerSource], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
11
+ this.createDefaultIdentifyClusterServer();
12
+ this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Laundry Dryer');
13
+ this.createDefaultPowerSourceWiredClusterServer();
14
+ this.createDeadFrontOnOffClusterServer(true);
15
+ this.createDefaultLaundryWasherModeClusterServer(currentMode, supportedModes);
16
+ this.createDefaultLaundryDryerControlsClusterServer(1);
17
+ if (temperatureSetpoint)
18
+ this.createNumberTemperatureControlClusterServer(temperatureSetpoint, minTemperature, maxTemperature, step);
19
+ else
20
+ this.createLevelTemperatureControlClusterServer(selectedTemperatureLevel, supportedTemperatureLevels);
21
+ this.createDefaultOperationalStateClusterServer(operationalState);
22
+ }
23
+ createDefaultLaundryWasherModeClusterServer(currentMode = 2, supportedModes = [
24
+ { label: 'Delicate', mode: 1, modeTags: [{ value: LaundryWasherMode.ModeTag.Delicate }] },
25
+ { label: 'Normal', mode: 2, modeTags: [{ value: LaundryWasherMode.ModeTag.Normal }] },
26
+ { label: 'Heavy', mode: 3, modeTags: [{ value: LaundryWasherMode.ModeTag.Heavy }] },
27
+ { label: 'Whites', mode: 4, modeTags: [{ value: LaundryWasherMode.ModeTag.Whites }] },
28
+ ]) {
29
+ this.behaviors.require(MatterbridgeLaundryWasherModeServer, {
30
+ supportedModes,
31
+ currentMode,
32
+ });
33
+ return this;
34
+ }
35
+ createDefaultLaundryDryerControlsClusterServer(selectedDrynessLevel, supportedDrynessLevels) {
36
+ this.behaviors.require(LaundryDryerControlsServer, {
37
+ supportedDrynessLevels: supportedDrynessLevels ?? [LaundryDryerControls.DrynessLevel.Low, LaundryDryerControls.DrynessLevel.Normal, LaundryDryerControls.DrynessLevel.Extra, LaundryDryerControls.DrynessLevel.Max],
38
+ selectedDrynessLevel,
39
+ });
40
+ return this;
41
+ }
42
+ createLevelTemperatureControlClusterServer(selectedTemperatureLevel = 1, supportedTemperatureLevels = ['Cold', 'Warm', 'Hot', '30°', '40°', '60°', '80°']) {
43
+ this.behaviors.require(MatterbridgeLevelTemperatureControlServer.with(TemperatureControl.Feature.TemperatureLevel), {
44
+ selectedTemperatureLevel,
45
+ supportedTemperatureLevels,
46
+ });
47
+ return this;
48
+ }
49
+ createNumberTemperatureControlClusterServer(temperatureSetpoint = 40 * 100, minTemperature = 30 * 100, maxTemperature = 60 * 100, step = 10 * 100) {
50
+ this.behaviors.require(MatterbridgeNumberTemperatureControlServer.with(TemperatureControl.Feature.TemperatureNumber, TemperatureControl.Feature.TemperatureStep), {
51
+ temperatureSetpoint,
52
+ minTemperature,
53
+ maxTemperature,
54
+ step,
55
+ });
56
+ return this;
57
+ }
58
+ }
@@ -5,12 +5,12 @@ import { ModeBase } from '@matter/main/clusters/mode-base';
5
5
  import { TemperatureControlServer } from '@matter/main/behaviors/temperature-control';
6
6
  import { LaundryWasherModeServer } from '@matter/main/behaviors/laundry-washer-mode';
7
7
  import { LaundryWasherControlsServer } from '@matter/main/behaviors/laundry-washer-controls';
8
- import { laundryWasher } from './matterbridgeDeviceTypes.js';
8
+ import { laundryWasher, powerSource } from './matterbridgeDeviceTypes.js';
9
9
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
10
10
  import { MatterbridgeOnOffServer, MatterbridgeServer } from './matterbridgeBehaviors.js';
11
11
  export class LaundryWasher extends MatterbridgeEndpoint {
12
12
  constructor(name, serial, currentMode, supportedModes, spinSpeedCurrent, spinSpeeds, numberOfRinses, supportedRinses, selectedTemperatureLevel, supportedTemperatureLevels, temperatureSetpoint, minTemperature, maxTemperature, step, operationalState) {
13
- super(laundryWasher, { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
13
+ super([laundryWasher, powerSource], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
14
14
  this.createDefaultIdentifyClusterServer();
15
15
  this.createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Laundry Washer');
16
16
  this.createDefaultPowerSourceWiredClusterServer();
@@ -24,6 +24,7 @@ import { SmokeCoAlarmServer } from '@matter/main/behaviors/smoke-co-alarm';
24
24
  import { SwitchServer } from '@matter/main/behaviors/switch';
25
25
  import { OperationalStateServer } from '@matter/main/behaviors/operational-state';
26
26
  import { ServiceAreaServer } from '@matter/main/behaviors/service-area';
27
+ import { DeviceEnergyManagementServer } from '@matter/main/behaviors/device-energy-management';
27
28
  import { DeviceEnergyManagementModeServer } from '@matter/main/behaviors/device-energy-management-mode';
28
29
  export class MatterbridgeServer extends Behavior {
29
30
  static id = 'matterbridge';
@@ -392,6 +393,20 @@ export class MatterbridgeModeSelectServer extends ModeSelectServer {
392
393
  super.changeToMode(request);
393
394
  }
394
395
  }
396
+ export class MatterbridgeDeviceEnergyManagementServer extends DeviceEnergyManagementServer {
397
+ powerAdjustRequest(request) {
398
+ const device = this.endpoint.stateOf(MatterbridgeServer);
399
+ device.log.info(`Adjusting power to ${request.power} duration ${request.duration} cause ${request.cause} (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
400
+ device.commandHandler.executeHandler('powerAdjustRequest', { request, cluster: DeviceEnergyManagementServer.id, attributes: this.state, endpoint: this.endpoint });
401
+ device.log.debug(`MatterbridgeDeviceEnergyManagementServer powerAdjustRequest called with power ${request.power} duration ${request.duration} cause ${request.cause}`);
402
+ }
403
+ cancelPowerAdjustRequest() {
404
+ const device = this.endpoint.stateOf(MatterbridgeServer);
405
+ device.log.info(`Cancelling power adjustment (endpoint ${this.endpoint.maybeId}.${this.endpoint.maybeNumber})`);
406
+ device.commandHandler.executeHandler('cancelPowerAdjustRequest', { cluster: DeviceEnergyManagementServer.id, attributes: this.state, endpoint: this.endpoint });
407
+ device.log.debug(`MatterbridgeDeviceEnergyManagementServer cancelPowerAdjustRequest called`);
408
+ }
409
+ }
395
410
  export class MatterbridgeDeviceEnergyManagementModeServer extends DeviceEnergyManagementModeServer {
396
411
  changeToMode(request) {
397
412
  const device = this.endpoint.stateOf(MatterbridgeServer);
@@ -59,11 +59,10 @@ import { ResourceMonitoring } from '@matter/main/clusters/resource-monitoring';
59
59
  import { HepaFilterMonitoringServer } from '@matter/main/behaviors/hepa-filter-monitoring';
60
60
  import { ActivatedCarbonFilterMonitoringServer } from '@matter/main/behaviors/activated-carbon-filter-monitoring';
61
61
  import { ThermostatUserInterfaceConfigurationServer } from '@matter/main/behaviors/thermostat-user-interface-configuration';
62
- import { DeviceEnergyManagementServer } from '@matter/main/behaviors/device-energy-management';
63
62
  import { AnsiLogger, CYAN, YELLOW, db, debugStringify, hk, or, zb } from './logger/export.js';
64
63
  import { bridgedNode } from './matterbridgeDeviceTypes.js';
65
64
  import { isValidNumber, isValidObject, isValidString } from './utils/export.js';
66
- import { MatterbridgeServer, MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer, MatterbridgeLiftWindowCoveringServer, MatterbridgeLiftTiltWindowCoveringServer, MatterbridgeThermostatServer, MatterbridgeFanControlServer, MatterbridgeDoorLockServer, MatterbridgeModeSelectServer, MatterbridgeValveConfigurationAndControlServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeBooleanStateConfigurationServer, MatterbridgeSwitchServer, MatterbridgeOperationalStateServer, MatterbridgeDeviceEnergyManagementModeServer, } from './matterbridgeBehaviors.js';
65
+ import { MatterbridgeServer, MatterbridgeIdentifyServer, MatterbridgeOnOffServer, MatterbridgeLevelControlServer, MatterbridgeColorControlServer, MatterbridgeLiftWindowCoveringServer, MatterbridgeLiftTiltWindowCoveringServer, MatterbridgeThermostatServer, MatterbridgeFanControlServer, MatterbridgeDoorLockServer, MatterbridgeModeSelectServer, MatterbridgeValveConfigurationAndControlServer, MatterbridgeSmokeCoAlarmServer, MatterbridgeBooleanStateConfigurationServer, MatterbridgeSwitchServer, MatterbridgeOperationalStateServer, MatterbridgeDeviceEnergyManagementModeServer, MatterbridgeDeviceEnergyManagementServer, } from './matterbridgeBehaviors.js';
67
66
  import { addClusterServers, addFixedLabel, addOptionalClusterServers, addRequiredClusterServers, addUserLabel, createUniqueId, getBehavior, getBehaviourTypesFromClusterClientIds, getBehaviourTypesFromClusterServerIds, getDefaultOperationalStateClusterServer, getDefaultFlowMeasurementClusterServer, getDefaultIlluminanceMeasurementClusterServer, getDefaultPressureMeasurementClusterServer, getDefaultRelativeHumidityMeasurementClusterServer, getDefaultTemperatureMeasurementClusterServer, getDefaultOccupancySensingClusterServer, lowercaseFirstLetter, updateAttribute, getClusterId, getAttributeId, setAttribute, getAttribute, checkNotLatinCharacters, generateUniqueId, subscribeAttribute, invokeBehaviorCommand, triggerEvent, } from './matterbridgeEndpointHelpers.js';
68
67
  export class MatterbridgeEndpoint extends Endpoint {
69
68
  static bridgeMode = '';
@@ -1066,8 +1065,9 @@ export class MatterbridgeEndpoint extends Endpoint {
1066
1065
  return this;
1067
1066
  }
1068
1067
  createDefaultDeviceEnergyManagementClusterServer(esaType = DeviceEnergyManagement.EsaType.Other, esaCanGenerate = false, esaState = DeviceEnergyManagement.EsaState.Online, absMinPower = 0, absMaxPower = 0) {
1069
- this.behaviors.require(DeviceEnergyManagementServer.with(DeviceEnergyManagement.Feature.PowerForecastReporting), {
1068
+ this.behaviors.require(MatterbridgeDeviceEnergyManagementServer.with(DeviceEnergyManagement.Feature.PowerForecastReporting, DeviceEnergyManagement.Feature.PowerAdjustment), {
1070
1069
  forecast: null,
1070
+ powerAdjustmentCapability: null,
1071
1071
  esaType,
1072
1072
  esaCanGenerate,
1073
1073
  esaState,
@@ -8,11 +8,11 @@ import { RvcOperationalState } from '@matter/main/clusters/rvc-operational-state
8
8
  import { ModeBase } from '@matter/main/clusters/mode-base';
9
9
  import { OperationalState } from '@matter/main/clusters/operational-state';
10
10
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
11
- import { roboticVacuumCleaner } from './matterbridgeDeviceTypes.js';
11
+ import { powerSource, roboticVacuumCleaner } from './matterbridgeDeviceTypes.js';
12
12
  import { MatterbridgeServer, MatterbridgeServiceAreaServer } from './matterbridgeBehaviors.js';
13
13
  export class RoboticVacuumCleaner extends MatterbridgeEndpoint {
14
14
  constructor(name, serial, currentRunMode, supportedRunModes, currentCleanMode, supportedCleanModes, currentPhase = null, phaseList = null, operationalState, operationalStateList, supportedAreas, selectedAreas, currentArea) {
15
- super(roboticVacuumCleaner, { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
15
+ super([roboticVacuumCleaner, powerSource], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
16
16
  this.createDefaultIdentifyClusterServer()
17
17
  .createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Robot Vacuum Cleaner')
18
18
  .createDefaultPowerSourceRechargeableBatteryClusterServer(80, PowerSource.BatChargeLevel.Ok, 5900)
@@ -0,0 +1,21 @@
1
+ import { PowerSourceTag } from '@matter/main';
2
+ import { DeviceEnergyManagement } from '@matter/main/clusters/device-energy-management';
3
+ import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
4
+ import { deviceEnergyManagement, electricalSensor, solarPower, powerSource } from './matterbridgeDeviceTypes.js';
5
+ export class SolarPower extends MatterbridgeEndpoint {
6
+ constructor(name, serial, voltage = null, current = null, power = null, energyExported = null, absMinPower = 0, absMaxPower = 0) {
7
+ super([solarPower, powerSource, electricalSensor, deviceEnergyManagement], {
8
+ tagList: [{ mfgCode: null, namespaceId: PowerSourceTag.Solar.namespaceId, tag: PowerSourceTag.Solar.tag, label: null }],
9
+ id: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`,
10
+ }, true);
11
+ this.createDefaultIdentifyClusterServer()
12
+ .createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Solar Power')
13
+ .createDefaultPowerSourceWiredClusterServer()
14
+ .createDefaultPowerTopologyClusterServer()
15
+ .createDefaultElectricalPowerMeasurementClusterServer(voltage, current, power)
16
+ .createDefaultElectricalEnergyMeasurementClusterServer(0, energyExported)
17
+ .createDefaultDeviceEnergyManagementClusterServer(DeviceEnergyManagement.EsaType.SolarPv, true, DeviceEnergyManagement.EsaState.Online, absMinPower, absMaxPower)
18
+ .createDefaultDeviceEnergyManagementModeClusterServer()
19
+ .addRequiredClusterServers();
20
+ }
21
+ }
@@ -4,11 +4,11 @@ import { WaterHeaterMode } from '@matter/main/clusters/water-heater-mode';
4
4
  import { WaterHeaterManagementServer } from '@matter/main/behaviors/water-heater-management';
5
5
  import { WaterHeaterModeServer } from '@matter/main/behaviors/water-heater-mode';
6
6
  import { MatterbridgeServer } from './matterbridgeBehaviors.js';
7
- import { waterHeater } from './matterbridgeDeviceTypes.js';
7
+ import { electricalSensor, powerSource, waterHeater } from './matterbridgeDeviceTypes.js';
8
8
  import { MatterbridgeEndpoint } from './matterbridgeEndpoint.js';
9
9
  export class WaterHeater extends MatterbridgeEndpoint {
10
10
  constructor(name, serial, waterTemperature = 50, targetWaterTemperature = 55, minHeatSetpointLimit = 20, maxHeatSetpointLimit = 80, heaterTypes = { immersionElement1: true }, tankPercentage = 90) {
11
- super(waterHeater, { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
11
+ super([waterHeater, powerSource, electricalSensor], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}` }, true);
12
12
  this.createDefaultIdentifyClusterServer()
13
13
  .createDefaultBasicInformationClusterServer(name, serial, 0xfff1, 'Matterbridge', 0x8000, 'Matterbridge Water Heater')
14
14
  .createDefaultPowerSourceWiredClusterServer()
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.1.1-dev-20250629-f14b886",
3
+ "version": "3.1.1-dev-20250630-1555eae",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "matterbridge",
9
- "version": "3.1.1-dev-20250629-f14b886",
9
+ "version": "3.1.1-dev-20250630-1555eae",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@matter/main": "0.15.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "matterbridge",
3
- "version": "3.1.1-dev-20250629-f14b886",
3
+ "version": "3.1.1-dev-20250630-1555eae",
4
4
  "description": "Matterbridge plugin manager for Matter",
5
5
  "author": "https://github.com/Luligu",
6
6
  "license": "Apache-2.0",