matterbridge 3.1.1-dev-20250704-aff5fcb → 3.1.2-dev-20250705-7da1eac
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 +21 -3
- package/README-DEV.md +6 -2
- package/README.md +5 -25
- package/dist/cli.js +2 -4
- package/dist/cliEmitter.js +6 -0
- package/dist/devices/roboticVacuumCleaner.js +2 -2
- package/dist/frontend.js +22 -4
- package/dist/index.js +0 -8
- package/dist/pluginManager.js +0 -2
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,7 +8,24 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
8
8
|
<img src="bmc-button.svg" alt="Buy me a coffee" width="120">
|
|
9
9
|
</a>
|
|
10
10
|
|
|
11
|
-
## [3.1.
|
|
11
|
+
## [3.1.2] - 2025-07-??
|
|
12
|
+
|
|
13
|
+
### Development Breaking Changes
|
|
14
|
+
|
|
15
|
+
- [exports]: 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
|
+
- [MatterbridgeEndpoint]: Added the mode property: `server` will make the device indipendent from its plugin. It has its own server node: QRCode, Fabrics and Sessions are visible in the Devices section of the Home page. This is a workaround for the Rvc Apple issue. With mode=server the Rvc (like any other device) can be paired directly to the controller like a native not bridged Matter device.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- [package]: Updated dependencies.
|
|
23
|
+
|
|
24
|
+
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
25
|
+
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
|
26
|
+
</a>
|
|
27
|
+
|
|
28
|
+
## [3.1.1] - 2025-07-04
|
|
12
29
|
|
|
13
30
|
### Development Breaking Changes
|
|
14
31
|
|
|
@@ -22,14 +39,15 @@ If you like this project and find it useful, please consider giving it a star on
|
|
|
22
39
|
- [SolarPower]: Added SolarPower class and Jest test (working on Home Assistant and SmartThings). Thanks Ludovic BOUÉ.
|
|
23
40
|
- [BatteryStorage]: Added BatteryStorage class and Jest test (working on Home Assistant and SmartThings). Thanks Ludovic BOUÉ.
|
|
24
41
|
- [HeatPump]: Added HeatPump class and Jest test (working on Home Assistant and SmartThings).
|
|
42
|
+
- [test]: Improved test units on Frontend class and all Matterbridge classes (coverage 93%).
|
|
25
43
|
|
|
26
44
|
### Changed
|
|
27
45
|
|
|
28
46
|
- [package]: Updated dependencies.
|
|
47
|
+
- [matter.js]: Bumped `matter.js` to 0.15.1 (https://github.com/project-chip/matter.js/discussions/2220). Great job matter.js!
|
|
29
48
|
- [frontend]: Added all esa devices.
|
|
30
49
|
- [frontend]: New default values: devices on the home page and icon view on the devices page.
|
|
31
|
-
- [
|
|
32
|
-
- [imports]: Added more dynamic imports to Matterbridge and Frontend classes.
|
|
50
|
+
- [imports]: Added dynamic imports to Matterbridge and Frontend classes.
|
|
33
51
|
|
|
34
52
|
<a href="https://www.buymeacoffee.com/luligugithub">
|
|
35
53
|
<img src="bmc-button.svg" alt="Buy me a coffee" width="80">
|
package/README-DEV.md
CHANGED
|
@@ -272,9 +272,9 @@ You create a Matter device with a new instance of MatterbridgeEndpoint(definitio
|
|
|
272
272
|
- @param {boolean} [debug] - Debug flag.
|
|
273
273
|
|
|
274
274
|
```typescript
|
|
275
|
-
const device = new MatterbridgeEndpoint([contactSensor, powerSource], {
|
|
275
|
+
const device = new MatterbridgeEndpoint([contactSensor, powerSource], { id: 'EntryDoor', mode: 'server' })
|
|
276
276
|
.createDefaultIdentifyClusterServer()
|
|
277
|
-
.createDefaultBasicInformationClusterServer('My
|
|
277
|
+
.createDefaultBasicInformationClusterServer('My entry door', '0123456789')
|
|
278
278
|
.createDefaultBooleanStateClusterServer(true)
|
|
279
279
|
.createDefaultPowerSourceReplaceableBatteryClusterServer(75)
|
|
280
280
|
.addRequiredClusterServers(); // Always better to call it at the end of the chain to add all the not already created but required clusters.
|
|
@@ -282,6 +282,10 @@ You create a Matter device with a new instance of MatterbridgeEndpoint(definitio
|
|
|
282
282
|
|
|
283
283
|
In the above example we create a contact sensor device type with also a power source device type feature replaceble battery.
|
|
284
284
|
|
|
285
|
+
The mode=`server` property of MatterbridgeEndpointOptions, allows to create an independent (not bridged) Matter device with its server node. In this case the bridge mode is not relevant.
|
|
286
|
+
|
|
287
|
+
The mode=`matter` property of MatterbridgeEndpointOptions, allows to create a (not bridged) Matter device that is added to the Matterbridge server node alongside the aggregator.
|
|
288
|
+
|
|
285
289
|
All device types are defined in src\matterbridgeDeviceTypes.ts and taken from the 'Matter-1.4-Device-Library-Specification.pdf'.
|
|
286
290
|
|
|
287
291
|
All default cluster helpers are available as methods of MatterbridgeEndpoint.
|
package/README.md
CHANGED
|
@@ -520,27 +520,13 @@ As of version 18.4.x, the Robot is supported by the Home app only as a single, n
|
|
|
520
520
|
|
|
521
521
|
If a Robot is present alongside other devices in the bridge, the entire bridge becomes unstable in the Home app.
|
|
522
522
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
So far is the only controller supporting some Matter 1.2, 1.3 and 1.4 device type:
|
|
526
|
-
|
|
527
|
-
- airQualitySensor code 0x002c (Matter 1.2)
|
|
528
|
-
- smokesmokeCoAlarm code 0x0076 (Matter 1.2)
|
|
529
|
-
- waterFreezeDetector code 0x0041 (Matter 1.3 with only BooleanState cluster)
|
|
530
|
-
- waterLeakDetector code 0x0043 (Matter 1.3 with only BooleanState cluster)
|
|
531
|
-
- rainSensor code 0x0044 (Matter 1.3 with only BooleanState cluster)
|
|
532
|
-
- deviceEnergyManagement code 0x050d (Matter 1.3 with only DeviceEnergyManagementMode cluster)
|
|
533
|
-
|
|
534
|
-
Electrical measurements:
|
|
523
|
+
A workaround has been released in Matterbridge 3.1.1. Ask the plugin authors to update the code.
|
|
535
524
|
|
|
536
|
-
|
|
537
|
-
- electricalSensor code 0x0510 with clusters: ElectricalPowerMeasurement and ElectricalEnergyMeasurement
|
|
538
|
-
|
|
539
|
-
Other supported cluster:
|
|
525
|
+
## Home Assistant
|
|
540
526
|
|
|
541
|
-
|
|
527
|
+
So far is the only controller supporting all Matter 1.2, 1.3 and 1.4 device type.
|
|
542
528
|
|
|
543
|
-
## Home Assistant issues
|
|
529
|
+
## Home Assistant issues
|
|
544
530
|
|
|
545
531
|
- If HA doesn't show all devices, reload the Matter Server Integration or reboot HA
|
|
546
532
|
- Home Assistant doesn't seem to always react when a device is removed from the bridge: they remain in HA unavailable forever...
|
|
@@ -565,8 +551,7 @@ There is no support for these Matter device types:
|
|
|
565
551
|
- pressure sensor
|
|
566
552
|
- flow sensor
|
|
567
553
|
|
|
568
|
-
In the zigbee2mqtt and shelly plugins select the option to expose
|
|
569
|
-
the switch devices like light or outlet cause they don't show up like switch
|
|
554
|
+
In the zigbee2mqtt and shelly plugins select the option to expose the switch devices like light or outlet cause they don't show up like switch
|
|
570
555
|
(Matterbridge uses a switch device type without client cluster).
|
|
571
556
|
|
|
572
557
|
## SmartThings
|
|
@@ -575,11 +560,6 @@ Tested by Tamer Salah
|
|
|
575
560
|
|
|
576
561
|
No issues reported so far.
|
|
577
562
|
|
|
578
|
-
Supports also:
|
|
579
|
-
|
|
580
|
-
- air Quality Sensor (Matter 1.2)
|
|
581
|
-
- smoke Co Alarm
|
|
582
|
-
|
|
583
563
|
## eWeLink
|
|
584
564
|
|
|
585
565
|
Tested by Tamer Salah
|
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import os from 'node:os';
|
|
2
|
-
import { EventEmitter } from 'node:events';
|
|
3
2
|
import { inspect } from 'node:util';
|
|
4
3
|
import { AnsiLogger, BRIGHT, CYAN, db, YELLOW } from 'node-ansi-logger';
|
|
5
4
|
import { getIntParameter, hasParameter } from './utils/export.js';
|
|
6
5
|
import { Matterbridge } from './matterbridge.js';
|
|
7
|
-
|
|
6
|
+
import { cliEmitter, lastCpuUsage, setLastCpuUsage } from './cliEmitter.js';
|
|
8
7
|
export let instance;
|
|
9
8
|
let session;
|
|
10
9
|
let snapshotInterval;
|
|
11
10
|
let memoryCheckInterval;
|
|
12
11
|
let prevCpus;
|
|
13
|
-
export let lastCpuUsage = 0;
|
|
14
12
|
let peakCpu = 0;
|
|
15
13
|
let peakRss = 0;
|
|
16
14
|
const log = new AnsiLogger({ logName: 'Cli', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
|
|
@@ -82,7 +80,7 @@ async function startCpuMemoryCheck() {
|
|
|
82
80
|
}
|
|
83
81
|
else {
|
|
84
82
|
cpuUsageLog = cpuUsage.toFixed(2);
|
|
85
|
-
|
|
83
|
+
setLastCpuUsage(cpuUsage);
|
|
86
84
|
if (lastCpuUsage > peakCpu)
|
|
87
85
|
peakCpu = lastCpuUsage;
|
|
88
86
|
cliEmitter.emit('cpu', lastCpuUsage);
|
|
@@ -11,8 +11,8 @@ import { MatterbridgeEndpoint } from '../matterbridgeEndpoint.js';
|
|
|
11
11
|
import { powerSource, roboticVacuumCleaner } from '../matterbridgeDeviceTypes.js';
|
|
12
12
|
import { MatterbridgeServer, MatterbridgeServiceAreaServer } from '../matterbridgeBehaviors.js';
|
|
13
13
|
export class RoboticVacuumCleaner extends MatterbridgeEndpoint {
|
|
14
|
-
constructor(name, serial, currentRunMode, supportedRunModes, currentCleanMode, supportedCleanModes, currentPhase = null, phaseList = null, operationalState, operationalStateList, supportedAreas, selectedAreas, currentArea) {
|
|
15
|
-
super([roboticVacuumCleaner, powerSource], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}
|
|
14
|
+
constructor(name, serial, mode = undefined, currentRunMode, supportedRunModes, currentCleanMode, supportedCleanModes, currentPhase = null, phaseList = null, operationalState, operationalStateList, supportedAreas, selectedAreas, currentArea) {
|
|
15
|
+
super([roboticVacuumCleaner, powerSource], { uniqueStorageKey: `${name.replaceAll(' ', '')}-${serial.replaceAll(' ', '')}`, mode }, 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)
|
package/dist/frontend.js
CHANGED
|
@@ -13,6 +13,7 @@ import { BridgedDeviceBasicInformation, PowerSource } from '@matter/main/cluster
|
|
|
13
13
|
import { createZip, isValidArray, isValidNumber, isValidObject, isValidString, isValidBoolean, withTimeout, hasParameter } from './utils/export.js';
|
|
14
14
|
import { plg } from './matterbridgeTypes.js';
|
|
15
15
|
import { capitalizeFirstLetter } from './matterbridgeEndpointHelpers.js';
|
|
16
|
+
import { cliEmitter, lastCpuUsage } from './cliEmitter.js';
|
|
16
17
|
export const WS_ID_LOG = 0;
|
|
17
18
|
export const WS_ID_REFRESH_NEEDED = 1;
|
|
18
19
|
export const WS_ID_RESTART_NEEDED = 2;
|
|
@@ -51,7 +52,14 @@ export class Frontend extends EventEmitter {
|
|
|
51
52
|
this.expressApp = express();
|
|
52
53
|
this.expressApp.use(express.static(path.join(this.matterbridge.rootDirectory, 'frontend/build')));
|
|
53
54
|
if (!hasParameter('ssl')) {
|
|
54
|
-
|
|
55
|
+
try {
|
|
56
|
+
this.httpServer = createServer(this.expressApp);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
this.log.error(`Failed to create HTTP server: ${error}`);
|
|
60
|
+
this.emit('server_error', error);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
55
63
|
if (hasParameter('ingress')) {
|
|
56
64
|
this.httpServer.listen(this.port, '0.0.0.0', () => {
|
|
57
65
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -90,6 +98,7 @@ export class Frontend extends EventEmitter {
|
|
|
90
98
|
}
|
|
91
99
|
catch (error) {
|
|
92
100
|
this.log.error(`Error reading certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/cert.pem')}: ${error}`);
|
|
101
|
+
this.emit('server_error', error);
|
|
93
102
|
return;
|
|
94
103
|
}
|
|
95
104
|
let key;
|
|
@@ -99,6 +108,7 @@ export class Frontend extends EventEmitter {
|
|
|
99
108
|
}
|
|
100
109
|
catch (error) {
|
|
101
110
|
this.log.error(`Error reading key file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/key.pem')}: ${error}`);
|
|
111
|
+
this.emit('server_error', error);
|
|
102
112
|
return;
|
|
103
113
|
}
|
|
104
114
|
let ca;
|
|
@@ -110,7 +120,14 @@ export class Frontend extends EventEmitter {
|
|
|
110
120
|
this.log.info(`CA certificate file ${path.join(this.matterbridge.matterbridgeDirectory, 'certs/ca.pem')} not loaded: ${error}`);
|
|
111
121
|
}
|
|
112
122
|
const serverOptions = { cert, key, ca };
|
|
113
|
-
|
|
123
|
+
try {
|
|
124
|
+
this.httpsServer = https.createServer(serverOptions, this.expressApp);
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
this.log.error(`Failed to create HTTPS server: ${error}`);
|
|
128
|
+
this.emit('server_error', error);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
114
131
|
if (hasParameter('ingress')) {
|
|
115
132
|
this.httpsServer.listen(this.port, '0.0.0.0', () => {
|
|
116
133
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://0.0.0.0:${this.port}${UNDERLINEOFF}${rs}`);
|
|
@@ -187,7 +204,6 @@ export class Frontend extends EventEmitter {
|
|
|
187
204
|
this.webSocketServer.on('error', (ws, error) => {
|
|
188
205
|
this.log.error(`WebSocketServer error: ${error}`);
|
|
189
206
|
});
|
|
190
|
-
const { cliEmitter } = await import('./cli.js');
|
|
191
207
|
cliEmitter.removeAllListeners();
|
|
192
208
|
cliEmitter.on('uptime', (systemUptime, processUptime) => {
|
|
193
209
|
this.wssSendUptimeUpdate(systemUptime, processUptime);
|
|
@@ -463,6 +479,7 @@ export class Frontend extends EventEmitter {
|
|
|
463
479
|
this.log.debug('Frontend app closed successfully');
|
|
464
480
|
}
|
|
465
481
|
if (this.webSocketServer) {
|
|
482
|
+
this.log.debug('Closing WebSocket server...');
|
|
466
483
|
this.webSocketServer.clients.forEach((client) => {
|
|
467
484
|
if (client.readyState === WebSocket.OPEN) {
|
|
468
485
|
client.close();
|
|
@@ -483,6 +500,7 @@ export class Frontend extends EventEmitter {
|
|
|
483
500
|
this.webSocketServer = undefined;
|
|
484
501
|
}
|
|
485
502
|
if (this.httpServer) {
|
|
503
|
+
this.log.debug('Closing http server...');
|
|
486
504
|
await withTimeout(new Promise((resolve) => {
|
|
487
505
|
this.httpServer?.close((error) => {
|
|
488
506
|
if (error) {
|
|
@@ -499,6 +517,7 @@ export class Frontend extends EventEmitter {
|
|
|
499
517
|
this.log.debug('Frontend http server closed successfully');
|
|
500
518
|
}
|
|
501
519
|
if (this.httpsServer) {
|
|
520
|
+
this.log.debug('Closing https server...');
|
|
502
521
|
await withTimeout(new Promise((resolve) => {
|
|
503
522
|
this.httpsServer?.close((error) => {
|
|
504
523
|
if (error) {
|
|
@@ -543,7 +562,6 @@ export class Frontend extends EventEmitter {
|
|
|
543
562
|
return `${seconds} second${seconds !== 1 ? 's' : ''}`;
|
|
544
563
|
};
|
|
545
564
|
async getApiSettings() {
|
|
546
|
-
const { lastCpuUsage } = await import('./cli.js');
|
|
547
565
|
this.matterbridge.systemInformation.totalMemory = this.formatMemoryUsage(os.totalmem());
|
|
548
566
|
this.matterbridge.systemInformation.freeMemory = this.formatMemoryUsage(os.freemem());
|
|
549
567
|
this.matterbridge.systemInformation.systemUptime = this.formatOsUpTime(os.uptime());
|
package/dist/index.js
CHANGED
|
@@ -11,14 +11,6 @@ export * from './matterbridgePlatform.js';
|
|
|
11
11
|
export * from './matterbridgeAccessoryPlatform.js';
|
|
12
12
|
export * from './matterbridgeDynamicPlatform.js';
|
|
13
13
|
export { addVirtualDevice } from './helpers.js';
|
|
14
|
-
export * from './devices/roboticVacuumCleaner.js';
|
|
15
|
-
export * from './devices/laundryWasher.js';
|
|
16
|
-
export * from './devices/laundryDryer.js';
|
|
17
|
-
export * from './devices/waterHeater.js';
|
|
18
|
-
export * from './devices/evse.js';
|
|
19
|
-
export * from './devices/solarPower.js';
|
|
20
|
-
export * from './devices/batteryStorage.js';
|
|
21
|
-
export * from './devices/heatPump.js';
|
|
22
14
|
const log = new AnsiLogger({ logName: 'Main', logTimestampFormat: 4, logLevel: hasParameter('debug') ? "debug" : "info" });
|
|
23
15
|
async function main() {
|
|
24
16
|
log.debug('***Matterbridge.loadInstance() called');
|
package/dist/pluginManager.js
CHANGED
|
@@ -241,8 +241,6 @@ export class PluginManager extends EventEmitter {
|
|
|
241
241
|
plugin.help = this.getHelp(packageJson);
|
|
242
242
|
plugin.changelog = this.getChangelog(packageJson);
|
|
243
243
|
plugin.funding = this.getFunding(packageJson);
|
|
244
|
-
if (!plugin.path)
|
|
245
|
-
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no path`);
|
|
246
244
|
if (!plugin.type)
|
|
247
245
|
this.log.warn(`Plugin ${plg}${plugin.name}${wr} has no type`);
|
|
248
246
|
const checkForProjectChipPackages = (dependencies) => {
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "matterbridge",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.2-dev-20250705-7da1eac",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "matterbridge",
|
|
9
|
-
"version": "3.1.
|
|
9
|
+
"version": "3.1.2-dev-20250705-7da1eac",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@matter/main": "0.15.1",
|
package/package.json
CHANGED