matterbridge 3.5.0-dev-20260117-88ddbe4 → 3.5.0-dev-20260119-f9ea00e
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 +12 -6
- package/README.md +14 -14
- package/dist/cli.js +1 -0
- package/dist/frontend.js +45 -36
- package/dist/matterNode.js +3 -1
- package/dist/matterbridge.js +37 -10
- package/frontend/build/assets/index.js +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -32,7 +32,10 @@ Advantages:
|
|
|
32
32
|
|
|
33
33
|
### Breaking Changes
|
|
34
34
|
|
|
35
|
-
- [matter]: This release brings the upgrade to matter 1.4.2 and matter.js 0.16.x.
|
|
35
|
+
- [matter]: This release brings the upgrade to matter 1.4.2 and matter.js 0.16.x. It may cause the controllers to see a new device.
|
|
36
|
+
- [childbridge]: Fixed nodeLabel from deviceName in childbridge mode. It may cause the controllers to see a new device.
|
|
37
|
+
- [modeserver]: Fixed nodeLabel from deviceName for server node devices. It may cause the controllers to see a new device.
|
|
38
|
+
- [matterbridge]: On restart (typically on the Home Assistant addon), when the plugin is not found and is reinstalled, it is reinstalled from the latest dev if it was on the dev branch.
|
|
36
39
|
|
|
37
40
|
### Changed device types in Matter 1.4.2
|
|
38
41
|
|
|
@@ -59,9 +62,9 @@ Advantages:
|
|
|
59
62
|
- [Thermostat]: Revision 9 - Removed AlarmMask attribute and AlarmCodeBitmap Type.
|
|
60
63
|
- [Identify]: Revision 6 - Added Q quality for IdentifyTime attribute.
|
|
61
64
|
- [WindowCovering]: Revision 6 - Marked AbsolutePosition feature and associated elements provisional.
|
|
62
|
-
- [RvcCleanMode]: Revision 4 -
|
|
63
|
-
- [RvcOperationalState]: Revision 4 -
|
|
64
|
-
- [ServiceArea]: Revision 2 -
|
|
65
|
+
- [RvcCleanMode]: Revision 4 - Added VacuumThenMop cleaning mode.
|
|
66
|
+
- [RvcOperationalState]: Revision 4 - Added several operational states and errors.
|
|
67
|
+
- [ServiceArea]: Revision 2 - Renamed InitialTimeEstimate to EstimatedTime.
|
|
65
68
|
|
|
66
69
|
### Added
|
|
67
70
|
|
|
@@ -69,20 +72,23 @@ Advantages:
|
|
|
69
72
|
- [frontend]: Enhanced logging for HTTP/HTTPS server binding in Frontend class.
|
|
70
73
|
- [matterbridge]: Excluded specific network interfaces when looking for the first external interface.
|
|
71
74
|
- [thermostat]: Conformance to new matter.js internal attributes externalMeasuredIndoorTemperature and externallyMeasuredOccupancy (not in Matter 1.4.2 specs).
|
|
72
|
-
- [scenes]: Added SceneManagement when required.
|
|
75
|
+
- [scenes]: Added SceneManagement cluster when required.
|
|
76
|
+
- [server]: Added start and stop devices server mode in plugin restart.
|
|
77
|
+
- [server]: Added start and stop devices server mode in plugin enable and disable.
|
|
73
78
|
- [matter.js]: Bump to matter.j v. 0.16.0.
|
|
74
79
|
- [matter.js]: Bump to matter.j v. 0.16.1.
|
|
75
80
|
- [matter.js]: Bump to matter.j v. 0.16.2.
|
|
76
81
|
- [matter.js]: Bump to matter.j v. 0.16.3.
|
|
77
82
|
- [matter.js]: Bump to matter.j v. 0.16.4.
|
|
78
83
|
- [matter.js]: Bump to matter.j v. 0.16.5.
|
|
84
|
+
- [frontend]: Added the --bind parameter to bind the frontend to a specific address. Defaults to all addresses.
|
|
79
85
|
|
|
80
86
|
### Changed
|
|
81
87
|
|
|
82
88
|
- [package]: Updated dependencies.
|
|
83
89
|
- [eslint]: Moved cache in .cache/.eslintcache.
|
|
84
90
|
- [prettier]: Moved cache in .cache/.prettiercache.
|
|
85
|
-
- [DevContainer]: Refactor DevContainer to use bridge mode.
|
|
91
|
+
- [DevContainer]: Refactor DevContainer to use bridge mode and matterbridge docker network.
|
|
86
92
|
|
|
87
93
|
### Fixed
|
|
88
94
|
|
package/README.md
CHANGED
|
@@ -165,13 +165,13 @@ From the frontend you can do all operations in an easy way.
|
|
|
165
165
|
|
|
166
166
|
Home page
|
|
167
167
|
|
|
168
|
-

|
|
169
169
|
|
|
170
|
-
[Devices page](./
|
|
170
|
+
[Devices page](./screenshots/Screenshot%20devices.jpg)
|
|
171
171
|
|
|
172
|
-
[Logs page](./
|
|
172
|
+
[Logs page](./screenshots/Screenshot%20logs.jpg)
|
|
173
173
|
|
|
174
|
-
[Config editor](./
|
|
174
|
+
[Config editor](./screenshots/Screenshot%20config%20editor.jpg)
|
|
175
175
|
|
|
176
176
|
## Advanced configurations
|
|
177
177
|
|
|
@@ -216,7 +216,7 @@ The other Home Assistant Community Add-ons and plugins are not verified to work
|
|
|
216
216
|
### Shelly
|
|
217
217
|
|
|
218
218
|
<a href="https://github.com/Luligu/matterbridge-shelly">
|
|
219
|
-
<img src="./
|
|
219
|
+
<img src="./screenshots/Shelly.svg" alt="Shelly plugin logo" width="100" />
|
|
220
220
|
</a>
|
|
221
221
|
|
|
222
222
|
Matterbridge shelly plugin allows you to expose all Shelly Gen 1, Gen 2, Gen 3 and Gen 4 and BLU devices to Matter.
|
|
@@ -245,7 +245,7 @@ Features:
|
|
|
245
245
|
### Zigbee2MQTT
|
|
246
246
|
|
|
247
247
|
<a href="https://github.com/Luligu/matterbridge-zigbee2mqtt">
|
|
248
|
-
<img src="./
|
|
248
|
+
<img src="./screenshots/Zigbee2MQTT.svg" alt="Zigbee2MQTT plugin logo" width="100" />
|
|
249
249
|
</a>
|
|
250
250
|
|
|
251
251
|
Matterbridge zigbee2mqtt is a matterbridge production-level plugin that expose all zigbee2mqtt devices and groups to Matter.
|
|
@@ -255,7 +255,7 @@ No hub or dedicated hardware needed.
|
|
|
255
255
|
### Somfy tahoma
|
|
256
256
|
|
|
257
257
|
<a href="https://github.com/Luligu/matterbridge-somfy-tahoma">
|
|
258
|
-
<img src="./
|
|
258
|
+
<img src="./screenshots/Somfy.svg" alt="Somfy plugin logo" width="100" />
|
|
259
259
|
</a>
|
|
260
260
|
|
|
261
261
|
Matterbridge Somfy Tahoma is a matterbridge production-level plugin that expose the Somfy Tahoma screen devices to Matter.
|
|
@@ -263,7 +263,7 @@ Matterbridge Somfy Tahoma is a matterbridge production-level plugin that expose
|
|
|
263
263
|
### Home Assistant
|
|
264
264
|
|
|
265
265
|
<a href="https://github.com/Luligu/matterbridge-hass">
|
|
266
|
-
<img src="./
|
|
266
|
+
<img src="./screenshots/HomeAssistant.svg" alt="Hass logo" width="100" />
|
|
267
267
|
</a>
|
|
268
268
|
|
|
269
269
|
Matterbridge Home Assistant plugin allows you to expose the Home Assistant devices and entities to Matter.
|
|
@@ -445,7 +445,7 @@ Place your own certificates in the `.matterbridge/cert` directory:
|
|
|
445
445
|
- `key.pem`
|
|
446
446
|
- `ca.pem` (optional)
|
|
447
447
|
|
|
448
|
-

|
|
449
449
|
|
|
450
450
|
Matterbridge looks first for .p12 certificate and if it is not found it looks for cert.pem and key.pem.
|
|
451
451
|
|
|
@@ -480,7 +480,7 @@ matterbridge --ssl --mtls --frontend 443
|
|
|
480
480
|
|
|
481
481
|
If the certificate are correctly configured, you will be able to connect with https to the frontend.
|
|
482
482
|
|
|
483
|
-

|
|
484
484
|
|
|
485
485
|
## How to send the debug log files
|
|
486
486
|
|
|
@@ -488,9 +488,9 @@ If the certificate are correctly configured, you will be able to connect with ht
|
|
|
488
488
|
|
|
489
489
|
In the frontend, go to settings and enable debug mode as shown below:
|
|
490
490
|
|
|
491
|
-

|
|
492
492
|
|
|
493
|
-

|
|
494
494
|
|
|
495
495
|
### Restart
|
|
496
496
|
|
|
@@ -498,7 +498,7 @@ Wait a few minutes to allow the logs to to accumulate.
|
|
|
498
498
|
|
|
499
499
|
Then, from the dots menu in the frontend, download the `matterbridge.log` and `matter.log` files.
|
|
500
500
|
|
|
501
|
-

|
|
502
502
|
|
|
503
503
|
Don't forget to unselect the debug mode when is no more needed. The network traffic and cpu usage is very high in debug mode.
|
|
504
504
|
|
|
@@ -510,7 +510,7 @@ There are two ways to pair a second controller:
|
|
|
510
510
|
|
|
511
511
|
- from Matterbridge frontend click `Turn on pairing mode` in the `Paired fabrics` panel and proceed like for the first controller.
|
|
512
512
|
|
|
513
|
-

|
|
514
514
|
|
|
515
515
|
Be patient cause the procedure can fail sometimes.
|
|
516
516
|
|
package/dist/cli.js
CHANGED
|
@@ -145,6 +145,7 @@ function help() {
|
|
|
145
145
|
--ipv4address [address]: set the ipv4 interface address to use for the matter server listener (default all addresses)
|
|
146
146
|
--ipv6address [address]: set the ipv6 interface address to use for the matter server listener (default all addresses)
|
|
147
147
|
--frontend [port]: start the frontend on the given port (default 8283)
|
|
148
|
+
--bind [address]: bind the frontend to the given address (default all addresses)
|
|
148
149
|
--logger: set the matterbridge logger level: debug | info | notice | warn | error | fatal (default info)
|
|
149
150
|
--filelogger: enable the matterbridge file logger (matterbridge.log)
|
|
150
151
|
--matterlogger: set the matter.js logger level: debug | info | notice | warn | error | fatal (default info)
|
package/dist/frontend.js
CHANGED
|
@@ -13,7 +13,7 @@ import { PowerSource } from '@matter/types/clusters/power-source';
|
|
|
13
13
|
import { MATTER_LOGGER_FILE, MATTER_STORAGE_NAME, MATTERBRIDGE_DIAGNOSTIC_FILE, MATTERBRIDGE_HISTORY_FILE, MATTERBRIDGE_LOGGER_FILE, NODE_STORAGE_DIR, plg } from './matterbridgeTypes.js';
|
|
14
14
|
import { isValidArray, isValidNumber, isValidObject, isValidString, isValidBoolean } from './utils/isValid.js';
|
|
15
15
|
import { createZip } from './utils/createZip.js';
|
|
16
|
-
import { hasParameter } from './utils/commandLine.js';
|
|
16
|
+
import { hasParameter, getParameter } from './utils/commandLine.js';
|
|
17
17
|
import { withTimeout, wait } from './utils/wait.js';
|
|
18
18
|
import { inspectError } from './utils/error.js';
|
|
19
19
|
import { formatBytes, formatUptime, formatPercent } from './utils/format.js';
|
|
@@ -205,14 +205,14 @@ export class Frontend extends EventEmitter {
|
|
|
205
205
|
});
|
|
206
206
|
}
|
|
207
207
|
else {
|
|
208
|
-
this.httpServer.listen(this.port, () => {
|
|
208
|
+
this.httpServer.listen(this.port, getParameter('bind'), () => {
|
|
209
209
|
const addr = this.httpServer?.address();
|
|
210
210
|
if (addr && typeof addr !== 'string') {
|
|
211
211
|
this.log.info(`The frontend http server is bound to ${addr.family} ${addr.address}:${addr.port}`);
|
|
212
212
|
}
|
|
213
|
-
if (this.matterbridge.systemInformation.ipv4Address !== '')
|
|
213
|
+
if (this.matterbridge.systemInformation.ipv4Address !== '' && !getParameter('bind'))
|
|
214
214
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://${this.matterbridge.systemInformation.ipv4Address}:${this.port}${UNDERLINEOFF}${rs}`);
|
|
215
|
-
if (this.matterbridge.systemInformation.ipv6Address !== '')
|
|
215
|
+
if (this.matterbridge.systemInformation.ipv6Address !== '' && !getParameter('bind'))
|
|
216
216
|
this.log.info(`The frontend http server is listening on ${UNDERLINE}http://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
217
217
|
this.listening = true;
|
|
218
218
|
this.emit('server_listening', 'http', this.port);
|
|
@@ -341,14 +341,14 @@ export class Frontend extends EventEmitter {
|
|
|
341
341
|
});
|
|
342
342
|
}
|
|
343
343
|
else {
|
|
344
|
-
this.httpsServer.listen(this.port, () => {
|
|
344
|
+
this.httpsServer.listen(this.port, getParameter('bind'), () => {
|
|
345
345
|
const addr = this.httpsServer?.address();
|
|
346
346
|
if (addr && typeof addr !== 'string') {
|
|
347
347
|
this.log.info(`The frontend https server is bound to ${addr.family} ${addr.address}:${addr.port}`);
|
|
348
348
|
}
|
|
349
|
-
if (this.matterbridge.systemInformation.ipv4Address !== '')
|
|
349
|
+
if (this.matterbridge.systemInformation.ipv4Address !== '' && !getParameter('bind'))
|
|
350
350
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://${this.matterbridge.systemInformation.ipv4Address}:${this.port}${UNDERLINEOFF}${rs}`);
|
|
351
|
-
if (this.matterbridge.systemInformation.ipv6Address !== '')
|
|
351
|
+
if (this.matterbridge.systemInformation.ipv6Address !== '' && !getParameter('bind'))
|
|
352
352
|
this.log.info(`The frontend https server is listening on ${UNDERLINE}https://[${this.matterbridge.systemInformation.ipv6Address}]:${this.port}${UNDERLINEOFF}${rs}`);
|
|
353
353
|
this.listening = true;
|
|
354
354
|
this.emit('server_listening', 'https', this.port);
|
|
@@ -1286,28 +1286,27 @@ export class Frontend extends EventEmitter {
|
|
|
1286
1286
|
return;
|
|
1287
1287
|
}
|
|
1288
1288
|
const plugin = this.matterbridge.plugins.get(data.params.pluginName);
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
this.matterbridge.plugins
|
|
1301
|
-
|
|
1302
|
-
.
|
|
1303
|
-
|
|
1304
|
-
this.
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
}
|
|
1310
|
-
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, success: true });
|
|
1289
|
+
plugin.locked = undefined;
|
|
1290
|
+
plugin.error = undefined;
|
|
1291
|
+
plugin.loaded = undefined;
|
|
1292
|
+
plugin.started = undefined;
|
|
1293
|
+
plugin.configured = undefined;
|
|
1294
|
+
plugin.platform = undefined;
|
|
1295
|
+
plugin.registeredDevices = undefined;
|
|
1296
|
+
plugin.matter = undefined;
|
|
1297
|
+
await this.matterbridge.plugins.enable(data.params.pluginName);
|
|
1298
|
+
this.wssSendSnackbarMessage(`Enabled plugin ${data.params.pluginName}`, 5, 'success');
|
|
1299
|
+
setImmediate(async () => {
|
|
1300
|
+
await this.matterbridge.plugins.load(plugin, true, 'The plugin has been enabled', true);
|
|
1301
|
+
if (plugin.serverNode)
|
|
1302
|
+
await this.matterbridge.startServerNode(plugin.serverNode);
|
|
1303
|
+
for (const device of this.matterbridge.devices.array().filter((d) => d.plugin === plugin.name && d.serverNode))
|
|
1304
|
+
await this.matterbridge.startServerNode(device.serverNode);
|
|
1305
|
+
this.wssSendSnackbarMessage(`Started plugin ${localData.params.pluginName}`, 5, 'success');
|
|
1306
|
+
this.wssSendRefreshRequired('plugins');
|
|
1307
|
+
this.wssSendRefreshRequired('devices');
|
|
1308
|
+
sendResponse({ id: localData.id, method: localData.method, src: 'Matterbridge', dst: localData.src, success: true });
|
|
1309
|
+
});
|
|
1311
1310
|
}
|
|
1312
1311
|
else if (data.method === '/api/disableplugin') {
|
|
1313
1312
|
if (!isValidString(data.params.pluginName, 10) || !this.matterbridge.plugins.has(data.params.pluginName)) {
|
|
@@ -1315,6 +1314,13 @@ export class Frontend extends EventEmitter {
|
|
|
1315
1314
|
return;
|
|
1316
1315
|
}
|
|
1317
1316
|
const plugin = this.matterbridge.plugins.get(data.params.pluginName);
|
|
1317
|
+
for (const device of this.matterbridge.devices.array().filter((d) => d.plugin === plugin.name && d.serverNode)) {
|
|
1318
|
+
await this.matterbridge.stopServerNode(device.serverNode);
|
|
1319
|
+
device.serverNode = undefined;
|
|
1320
|
+
}
|
|
1321
|
+
if (plugin.serverNode)
|
|
1322
|
+
await this.matterbridge.stopServerNode(plugin.serverNode);
|
|
1323
|
+
plugin.serverNode = undefined;
|
|
1318
1324
|
await this.matterbridge.plugins.shutdown(plugin, 'The plugin has been disabled.', true);
|
|
1319
1325
|
await this.matterbridge.plugins.disable(data.params.pluginName);
|
|
1320
1326
|
this.wssSendSnackbarMessage(`Disabled plugin ${data.params.pluginName}`, 5, 'success');
|
|
@@ -1327,17 +1333,19 @@ export class Frontend extends EventEmitter {
|
|
|
1327
1333
|
sendResponse({ id: data.id, method: data.method, src: 'Matterbridge', dst: data.src, error: 'Wrong parameter pluginName in /api/restartplugin' });
|
|
1328
1334
|
return;
|
|
1329
1335
|
}
|
|
1336
|
+
this.wssSendSnackbarMessage(`Restarting plugin ${data.params.pluginName}`, 5, 'info');
|
|
1330
1337
|
const plugin = this.matterbridge.plugins.get(data.params.pluginName);
|
|
1331
1338
|
await this.matterbridge.plugins.shutdown(plugin, 'The plugin is restarting.', false, true);
|
|
1332
1339
|
if (plugin.serverNode) {
|
|
1333
1340
|
await this.matterbridge.stopServerNode(plugin.serverNode);
|
|
1334
1341
|
plugin.serverNode = undefined;
|
|
1335
1342
|
}
|
|
1336
|
-
for (const device of this.matterbridge.devices) {
|
|
1337
|
-
if (device.
|
|
1338
|
-
this.
|
|
1339
|
-
|
|
1340
|
-
}
|
|
1343
|
+
for (const device of this.matterbridge.devices.array().filter((d) => d.plugin === plugin.name)) {
|
|
1344
|
+
if (device.serverNode)
|
|
1345
|
+
await this.matterbridge.stopServerNode(device.serverNode);
|
|
1346
|
+
device.serverNode = undefined;
|
|
1347
|
+
this.log.debug(`Removing device ${device.deviceName} from plugin ${plugin.name}`);
|
|
1348
|
+
this.matterbridge.devices.remove(device);
|
|
1341
1349
|
}
|
|
1342
1350
|
if (plugin.type === 'DynamicPlatform' && !plugin.locked)
|
|
1343
1351
|
await this.matterbridge.createDynamicPlugin(plugin);
|
|
@@ -1348,11 +1356,12 @@ export class Frontend extends EventEmitter {
|
|
|
1348
1356
|
if (plugin.restartRequired)
|
|
1349
1357
|
needRestart++;
|
|
1350
1358
|
}
|
|
1351
|
-
if (needRestart === 0)
|
|
1359
|
+
if (needRestart === 0)
|
|
1352
1360
|
this.wssSendRestartNotRequired(true);
|
|
1353
|
-
}
|
|
1354
1361
|
if (plugin.serverNode)
|
|
1355
1362
|
await this.matterbridge.startServerNode(plugin.serverNode);
|
|
1363
|
+
for (const device of this.matterbridge.devices.array().filter((d) => d.plugin === plugin.name && d.serverNode))
|
|
1364
|
+
await this.matterbridge.startServerNode(device.serverNode);
|
|
1356
1365
|
this.wssSendSnackbarMessage(`Restarted plugin ${data.params.pluginName}`, 5, 'success');
|
|
1357
1366
|
this.wssSendRefreshRequired('plugins');
|
|
1358
1367
|
this.wssSendRefreshRequired('devices');
|
package/dist/matterNode.js
CHANGED
|
@@ -685,7 +685,9 @@ export class MatterNode extends EventEmitter {
|
|
|
685
685
|
const plugin = this.pluginManager.get(pluginName);
|
|
686
686
|
if (!plugin)
|
|
687
687
|
throw new Error(`Error removing bridged endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er}): plugin not found`);
|
|
688
|
-
if (
|
|
688
|
+
if (device.serverNode) {
|
|
689
|
+
}
|
|
690
|
+
else if (this.matterbridge.bridgeMode === 'bridge') {
|
|
689
691
|
if (!this.aggregatorNode)
|
|
690
692
|
throw new Error(`Error removing bridged endpoint ${plg}${pluginName}${er}:${dev}${device.deviceName}${er} (${zb}${device.name}${er}): aggregator node not found`);
|
|
691
693
|
await device.delete();
|
package/dist/matterbridge.js
CHANGED
|
@@ -2,7 +2,7 @@ if (process.argv.includes('--loader') || process.argv.includes('-loader'))
|
|
|
2
2
|
console.log('\u001B[32mMatterbridge loaded.\u001B[40;0m');
|
|
3
3
|
import os from 'node:os';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
-
import fs from 'node:fs';
|
|
5
|
+
import fs, { unlinkSync } from 'node:fs';
|
|
6
6
|
import EventEmitter from 'node:events';
|
|
7
7
|
import { inspect } from 'node:util';
|
|
8
8
|
import { AnsiLogger, UNDERLINE, UNDERLINEOFF, db, debugStringify, BRIGHT, RESET, er, nf, rs, wr, RED, GREEN, zb, CYAN, nt, BLUE, or } from 'node-ansi-logger';
|
|
@@ -475,7 +475,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
475
475
|
if (!fs.existsSync(plugin.path) && !hasParameter('add') && !hasParameter('remove') && !hasParameter('enable') && !hasParameter('disable') && !hasParameter('reset') && !hasParameter('factoryreset')) {
|
|
476
476
|
this.log.info(`Error parsing plugin ${plg}${plugin.name}${nf}. Trying to reinstall it from npm...`);
|
|
477
477
|
const { spawnCommand } = await import('./utils/spawn.js');
|
|
478
|
-
if (await spawnCommand('npm', ['install', '-g', plugin.name
|
|
478
|
+
if (await spawnCommand('npm', ['install', '-g', `${plugin.name}${plugin.version.includes('-dev-') ? '@dev' : ''}`, '--omit=dev', '--verbose'], 'install', plugin.name)) {
|
|
479
479
|
this.log.info(`Plugin ${plg}${plugin.name}${nf} reinstalled.`);
|
|
480
480
|
plugin.error = false;
|
|
481
481
|
}
|
|
@@ -525,11 +525,11 @@ export class Matterbridge extends EventEmitter {
|
|
|
525
525
|
let index = 0;
|
|
526
526
|
for (const plugin of this.plugins) {
|
|
527
527
|
if (index !== this.plugins.length - 1) {
|
|
528
|
-
this.log.info(`├─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} ${plugin.enabled ? GREEN : RED}enabled${nf}`);
|
|
528
|
+
this.log.info(`├─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} version: ${plg}${plugin.version}${nf} ${plugin.enabled ? GREEN : RED}enabled${nf}`);
|
|
529
529
|
this.log.info(`│ └─ entry ${UNDERLINE}${db}${plugin.path}${UNDERLINEOFF}${db}`);
|
|
530
530
|
}
|
|
531
531
|
else {
|
|
532
|
-
this.log.info(`└─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} ${plugin.enabled ? GREEN : RED}disabled${nf}`);
|
|
532
|
+
this.log.info(`└─┬─ plugin ${plg}${plugin.name}${nf}: "${plg}${BRIGHT}${plugin.description}${RESET}${nf}" type: ${typ}${plugin.type}${nf} version: ${plg}${plugin.version}${nf} ${plugin.enabled ? GREEN : RED}disabled${nf}`);
|
|
533
533
|
this.log.info(` └─ entry ${UNDERLINE}${db}${plugin.path}${UNDERLINEOFF}${db}`);
|
|
534
534
|
}
|
|
535
535
|
index++;
|
|
@@ -1053,6 +1053,30 @@ export class Matterbridge extends EventEmitter {
|
|
|
1053
1053
|
this.log.info('Matter storage reset done!');
|
|
1054
1054
|
}
|
|
1055
1055
|
await this.stopMatterStorage();
|
|
1056
|
+
function unlinkSafe(path, log) {
|
|
1057
|
+
try {
|
|
1058
|
+
log.debug(`Removing ${path}...`);
|
|
1059
|
+
unlinkSync(path);
|
|
1060
|
+
log.debug(`Removed ${path}`);
|
|
1061
|
+
}
|
|
1062
|
+
catch {
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
this.log.debug(`Cleaning matter storage context for ${GREEN}Matterbridge${db}...`);
|
|
1066
|
+
unlinkSafe(path.join(this.matterbridgeDirectory, MATTER_STORAGE_NAME, 'Matterbridge', 'sessions.resumptionRecords'), this.log);
|
|
1067
|
+
unlinkSafe(path.join(this.matterbridgeDirectory, MATTER_STORAGE_NAME, 'Matterbridge', 'root.subscriptions.subscriptions'), this.log);
|
|
1068
|
+
for (const plugin of this.plugins.array()) {
|
|
1069
|
+
this.log.debug(`Cleaning matter storage context for plugin ${plg}${plugin.name}${db}...`);
|
|
1070
|
+
unlinkSafe(path.join(this.matterbridgeDirectory, MATTER_STORAGE_NAME, plugin.name, 'sessions.resumptionRecords'), this.log);
|
|
1071
|
+
unlinkSafe(path.join(this.matterbridgeDirectory, MATTER_STORAGE_NAME, plugin.name, 'root.subscriptions.subscriptions'), this.log);
|
|
1072
|
+
}
|
|
1073
|
+
for (const device of this.devices.array().filter((d) => d.mode === 'server')) {
|
|
1074
|
+
if (!device.deviceName)
|
|
1075
|
+
continue;
|
|
1076
|
+
this.log.debug(`Cleaning matter storage context for server node device ${dev}${device.deviceName}${db}...`);
|
|
1077
|
+
unlinkSafe(path.join(this.matterbridgeDirectory, MATTER_STORAGE_NAME, device.deviceName.replace(/[ .]/g, ''), 'sessions.resumptionRecords'), this.log);
|
|
1078
|
+
unlinkSafe(path.join(this.matterbridgeDirectory, MATTER_STORAGE_NAME, device.deviceName.replace(/[ .]/g, ''), 'root.subscriptions.subscriptions'), this.log);
|
|
1079
|
+
}
|
|
1056
1080
|
await this.frontend.stop();
|
|
1057
1081
|
this.frontend.destroy();
|
|
1058
1082
|
this.plugins.destroy();
|
|
@@ -1380,8 +1404,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1380
1404
|
await storageContext.set('vendorName', vendorName.slice(0, 32));
|
|
1381
1405
|
await storageContext.set('productId', productId);
|
|
1382
1406
|
await storageContext.set('productName', productName.slice(0, 32));
|
|
1383
|
-
await storageContext.set('nodeLabel', productName.slice(0, 32));
|
|
1384
1407
|
await storageContext.set('productLabel', productName.slice(0, 32));
|
|
1408
|
+
await storageContext.set('nodeLabel', deviceName.slice(0, 32));
|
|
1385
1409
|
await storageContext.set('serialNumber', await storageContext.get('serialNumber', serialNumber ? serialNumber.slice(0, 32) : 'SN' + random));
|
|
1386
1410
|
await storageContext.set('uniqueId', await storageContext.get('uniqueId', uniqueId ? uniqueId.slice(0, 32) : 'UI' + random));
|
|
1387
1411
|
await storageContext.set('softwareVersion', isValidNumber(parseVersionString(this.matterbridgeVersion), 0, UINT32_MAX) ? parseVersionString(this.matterbridgeVersion) : 1);
|
|
@@ -1396,8 +1420,8 @@ export class Matterbridge extends EventEmitter {
|
|
|
1396
1420
|
this.log.debug(`- vendorName: ${await storageContext.get('vendorName')}`);
|
|
1397
1421
|
this.log.debug(`- productId: ${await storageContext.get('productId')}`);
|
|
1398
1422
|
this.log.debug(`- productName: ${await storageContext.get('productName')}`);
|
|
1399
|
-
this.log.debug(`- nodeLabel: ${await storageContext.get('nodeLabel')}`);
|
|
1400
1423
|
this.log.debug(`- productLabel: ${await storageContext.get('productLabel')}`);
|
|
1424
|
+
this.log.debug(`- nodeLabel: ${await storageContext.get('nodeLabel')}`);
|
|
1401
1425
|
this.log.debug(`- serialNumber: ${await storageContext.get('serialNumber')}`);
|
|
1402
1426
|
this.log.debug(`- uniqueId: ${await storageContext.get('uniqueId')}`);
|
|
1403
1427
|
this.log.debug(`- softwareVersion: ${await storageContext.get('softwareVersion')} softwareVersionString: ${await storageContext.get('softwareVersionString')}`);
|
|
@@ -1433,12 +1457,12 @@ export class Matterbridge extends EventEmitter {
|
|
|
1433
1457
|
deviceType: DeviceTypeId(await storageContext.get('deviceType')),
|
|
1434
1458
|
},
|
|
1435
1459
|
basicInformation: {
|
|
1460
|
+
nodeLabel: await storageContext.get('nodeLabel'),
|
|
1436
1461
|
vendorId: VendorId(await storageContext.get('vendorId')),
|
|
1437
1462
|
vendorName: await storageContext.get('vendorName'),
|
|
1438
1463
|
productId: await storageContext.get('productId'),
|
|
1439
1464
|
productName: await storageContext.get('productName'),
|
|
1440
1465
|
productLabel: await storageContext.get('productName'),
|
|
1441
|
-
nodeLabel: await storageContext.get('productName'),
|
|
1442
1466
|
serialNumber: await storageContext.get('serialNumber'),
|
|
1443
1467
|
uniqueId: await storageContext.get('uniqueId'),
|
|
1444
1468
|
softwareVersion: await storageContext.get('softwareVersion'),
|
|
@@ -1537,7 +1561,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1537
1561
|
this.log.notice(`Starting ${matterServerNode.id} server node`);
|
|
1538
1562
|
await matterServerNode.start();
|
|
1539
1563
|
}
|
|
1540
|
-
async stopServerNode(matterServerNode, timeout =
|
|
1564
|
+
async stopServerNode(matterServerNode, timeout = 10000) {
|
|
1541
1565
|
const { withTimeout } = await import('./utils/wait.js');
|
|
1542
1566
|
if (!matterServerNode)
|
|
1543
1567
|
return;
|
|
@@ -1571,7 +1595,7 @@ export class Matterbridge extends EventEmitter {
|
|
|
1571
1595
|
if (!plugin.locked) {
|
|
1572
1596
|
plugin.locked = true;
|
|
1573
1597
|
this.log.debug(`Creating dynamic plugin ${plg}${plugin.name}${db} server node...`);
|
|
1574
|
-
plugin.storageContext = await this.createServerNodeContext(plugin.name,
|
|
1598
|
+
plugin.storageContext = await this.createServerNodeContext(plugin.name, plugin.description, this.aggregatorDeviceType, this.aggregatorVendorId, this.aggregatorVendorName, this.aggregatorProductId, this.aggregatorProductName);
|
|
1575
1599
|
plugin.serverNode = await this.createServerNode(plugin.storageContext, this.port ? this.port++ : undefined, this.passcode ? this.passcode++ : undefined, this.discriminator ? this.discriminator++ : undefined);
|
|
1576
1600
|
this.log.debug(`Creating dynamic plugin ${plg}${plugin.name}${db} aggregator node...`);
|
|
1577
1601
|
plugin.aggregatorNode = await this.createAggregatorNode(plugin.storageContext);
|
|
@@ -1701,7 +1725,10 @@ export class Matterbridge extends EventEmitter {
|
|
|
1701
1725
|
this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: plugin not found`);
|
|
1702
1726
|
return;
|
|
1703
1727
|
}
|
|
1704
|
-
if (
|
|
1728
|
+
if (device.mode === 'server') {
|
|
1729
|
+
this.log.info(`Removed mode server bridged endpoint(${plugin.registeredDevices}) ${dev}${device.deviceName}${nf} (${zb}${device.name}${nf}) for plugin ${plg}${pluginName}${nf}`);
|
|
1730
|
+
}
|
|
1731
|
+
else if (this.bridgeMode === 'bridge') {
|
|
1705
1732
|
if (!this.aggregatorNode) {
|
|
1706
1733
|
this.log.error(`Error removing bridged endpoint ${dev}${device.deviceName}${er} (${zb}${device.name}${er}) for plugin ${plg}${pluginName}${er}: aggregator node not found`);
|
|
1707
1734
|
return;
|